(MLOps-2) docker 정리

dddwsd·2022년 5월 5일
0

Docker

docker는 containerization(container화 하는 기술)을 할 수 있게 해주는 소프트웨어이다.
docker의 slogan은 Build Once, Run Anywhere로 어디에서나 동일한 실행 결과를 보장한다.

image

image는 container 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로 immutable하며 image를 실행하면 container가 생성된다.
같은 이미지에서 여러개의 container를 생성할 수 있고 container의 상태가 바뀌거나 container가 삭제되더라도 이미지는 변하지 않고 그대로 남아있다.

container

container는 virtualization(가상화) 기술의 하나로 격리된 공간에서 프로세스가 동작하는 기술을 의미한다.

cf) virtualization

  • 물리적인 하드웨어 장치를 논리적인 객체로 추상화 하는 것
  • 하나의 resource를 쪼개서 쓰거나, 여러 resource를 하나인 것처럼 묶어서 사용하는 것


기존의 virtualization은 host OS위에 guest OS 전체를 가상화하여 사용하는 방식인데 이는 무겁고 느려서 운영환경에선 사용할 수 없었음.
이를 개선하기 위해 프로세스를 격리하는 방식이 등장했다. 리눅스에선 이 방식을 리눅스 컨테이너라고 한다.

Layer


docker는 union filesystem을 이용해서 layer들을 하나의 filesystem으로 사용할 수 있게 해준다.
image는 여러개의 read only layer로 구성되고 파일이 추가되거나 수정되면 새로운 layer가 생성된다.

container를 생성할 때도 layer 방식을 사용하는데, 기존의 image layer위에 read-write layer를 추가한다.
image layer를 그대로 사용하면서 container가 실행중에 생성하거나 변경된 것들에 대한 내용은 read-write layer에 저장되므로 여러개의 container를 생성해도 최소한의 용량만 사용한다.


docker 내부적으로는 container를 위한 resource를 분리하고, lifecycle을 제어하는 기능은 linux kernel의 cgroup등이 수행한다.
docker는 추상화 layer를 만들었고 이를 통해 user는 Docker CLI만으로 container를 제어할 수 있다.

  1. Docker CLI
    • user는 Docker CLI로 dockered(docker daemon)에게 명령을 내린다.
    • 이 과정에서 unix socket을 사용하기 때문에 var/run/docker.sock 관련 에러가 나온다.
  2. dockered
    • containered에게 명령을 내리는 역할을 한다.
  3. containered
    • runC(OCI layer)에게 명령을 내리기 위한 추상화 단계이며, 표준화된 인터페이스(OCI)를 사용한다.
  4. runC
    • linux kernel의 기능을 직접 사용해서 container라는 하나의 프로세스가 사용할 수 있는 namespace와 resource(cpu, memory, filesystem)등을 격리시켜주는 기능을 수행한다.

Docker practice

  1. MacOS docker 설치
$ brew install docker
  1. Practice
    https://mlops-for-all.github.io/prerequisites/docker/command/ 참조

Dockerfile internal command

  1. FROM

    • Dockerfile이 base image로 어떤걸 사용할 것인지 명시하는 명령어
    FROM <image>[:<tag>] [AS <name>]
    
    # example
    From nginx:latest AS ngx
  2. COPY

    • 로컬에 존재하는 파일 또는 디렉토리를 container 내부에서의 경로에 복사하는 명령어
    COPY <src> <dest>
    
    # example
    COPY local-file /file
    COPY local-dir /dir
  3. ADD

    • 로컬에 압축되어 있는 파일을 풀면서 컨테이너 내부로 COPY
    • Remote URLs에 있는 파일을 COPY
    ADD scripts.tar.gz /tmp
    ADD http://www.example.com/script.sh /tmp
  4. RUN

    • 명시한 command를 docker container 내부에서 실행하는 명령어
    • docker image는 해당 command들이 실행된 상태를 유지한다.
      RUN <command>
      RUN ["executable-command", "parameter1", "parameter2"]
      
      # example
      RUN pip install torch
      RUN pip install -r requirements.txt
  5. CMD & ENTRYPOINT

    • CMD
      • 명시한 command를 docker container가 시작될 때, 실행한다.
      • 하나의 docker image에서는 하나의 CMD만 실행할 수 있다.
      • container 실행할때 parameter값을 주면 Dockerfile에 지정된 CMD 값을 대신 하여 지정한 parameter값으로 변경하여 실행된다.
    • ENTRYPOINT
      • 컨테이너를 수행할 때 반드시 지정한 명령을 수행하도록 된다.
      • container를 실행할 때 parameter값을 주면 에러가 발생한다.
    CMD <command>
    CMD ["executable-command", "parameter1", "parameter2"]
    CMD ["parameter1", "parameter2"] # ENTRYPOINT와 함께 사용할 때
    
    # example
    CMD python main.py
  6. WORKDIR

    • 이후 추가될 명령어를 container 내의 어떤 디렉토리에서 수행할 것인지를 명시하는 명령어
    • 해당 디렉토리가 없다면 생성한다.
    WORKDIR /path/to/workdir
    
    # example
    WORKDIR /home/demo
    RUN pwd # /home/demo 가 출력된다
  7. ENV

    • container 내부에서 지속적으로 사용될 environment variable의 값을 설정하는 명령어
    ENV <KEY> <VALUE>
    ENV <KEY>=<VALUE>
    
    # example
    # default 언어 설정
    RUN locale-gen ko_KR.UTF-8
    ENV LANG ko_KR.UTF-8
    ENV LANGUAGE ko_KR.UTF-8
    ENV LC_ALL ko_KR.UTF-8
  8. EXPOSE

    • 컨테이너에 뚫어줄 port/protocol을 지정할 수 있다.
    • 지정하지 않으면 TCP가 default
    EXPOSE <port>
    EXPOSE <port>/<protocol>
    
    # example
    EXPOSE 8080

Dockerfile command

  1. build
    • .: 현재 경로에 있는 Dockerfile
    • -t: my-image라는 name과 v1.0.0 tag로 image를 빌드
    docker build -t my-image:v1.0.0 .
  2. run
    • build한 이미지로 docker container 생성
    docker run my-image:v1.0.0
  3. run with env
    • TEST env에 값을 변경
    docker run -e TEST=bye my-image:v1.0.0

docker image 잘 만드는 법

Docker image는 여러 개의 Read-Only layer로 구성되어 있고, 이미지를 빌드할 때 이미 존재하는 layer는 cache되어 재사용되기 때문에, 이를 생각해서 Dockerfile을 구성한다면 시간을 줄일 수 있기 때문에 Dockerfile을 활용하여 docker image를 만들때 layer의 순서가 중요하다.


docker container에는 위 그림과 같은 방식으로 layer가 쌓이며 최상단의 Read/Write layer는 이미지에 영향을 주지 않고 container 내부에서 작업한 내용으로 모두 volatility이다.

image layers에 해당하는 하단의 layer가 변경되면, 그 위의 layer는 모두 새로 빌드되기 때문에 자주 변경되는 부분은 최대한 위쪽 layer로 놓는게 좋다.

또한 합칠 수 있는 Layer는 적절히 합치는 것이 성능향상효과를 이끈다.

.dockerignore.gitignore와 유사한 역할로 docekr build시에 자동으로 제외한다.

docker image의 tag로 latest는 사용하지 않는 것을 권장한다. 왜냐하면 latest가 default tag name이므로 의도치않게 overwritten 되는 경우가 너무 많이 발생하기 때문이다.

log등의 정보는 container 내부에 저장할 경우 날아갈 수 있으므로 외부에 저장하는 것이 좋으며, secret한 정보들은 Dockerfile에 직접 적는게 아니라 env var 또는 .env config file을 사용한다.

docker run 옵션


docker는 container 내부에서 작업한 모든 사항이 저장되지 않기 때문에 docker container끼리 격리된 파일 시스템을 사용하고 이 때문에 docker container끼리 데이터를 공유하기 어렵다.

docker volume

docker cli를 통해서 volume이라는 리소스를 직접 관리한다.
local에서 docker area(/var/lib/docker) 아래에 특정 디렉토리를 생성한 다음, 해당 경로를 docker container에 mount한다.

blind mount

local의 특정 경로를 docker container에 mount

restart policy

docker run --restart=always ubuntu

background process

docker run -it ubuntu sleep 10

-it = -i + -t 옵션은 container를 실행시킴과 동시에 interactive한 terminal로 접속시켜주는 옵션.

docker run -d ubuntu sleep 10

-d 옵션은 docker container를 background에서 실행시켜서, 컨테이너에서 접속 종료를 하더라도 계속 실행중이 되도록 하는 커맨드

계속해서 log를 지켜볼 필요가 없는 DB의 경우 detached mode로 실행시키고
계속해서 log를 확인해야 하는 Backend API server는 attached mode로 log를 following하면서 실행시키면 효율적이다.

refer

profile
Github - https://github.com/dddwsd

0개의 댓글