프로그래밍/[ Docker ]

Docker 사용하기

gooooooood 2020. 8. 18. 18:05
반응형

Docker를 사용해보긴 했지만 아직 부족한 부분이 많다는 생각을 하고 있는데 때마침 Medium에서 좋은 정리글을 발견하여 이 시점을 계기로 더 전문적으로 Docker를 사용하기 위한 포스팅들을 할 예정입니다.

 

Photo by Teo Zac on Unsplash 

 

프로그래머에게 "environment"란 개념은 정말 중요하면서도 관리하기가 어려운 부분 중 하나입니다.

 

그 이유 중 하나는 코드에 사용되는 라이브러리가 지속적으로 업데이트 되고 그에 따라서 하나의 라이브러리 버전 업데이트가 코드에 영향을 끼치고 에러를 발생시킬 수 있기 때문입니다. 

 

특히나 동시에 여러 프로젝트를 진행하고 있다면 이러한 문제들은 더욱 복잡해집니다. 또한, 개발한 코드를 다른 OS에서 동작하도록 하려면 코드를 전부 다 수정해야 할 수도 있습니다.

 

이러한 문제를 간단하게 만들어 주는 것이 바로 Docker의 "container"라는 개념입니다. "container"는 시스템과 독립적으로 "environment"를 동작시킬 수 있게 도와줍니다. 이 "container"를 활용하여 손쉽게 새로운 "environment"를 만들고 공유할 수 있습니다.

 

 

설치

Docker를 사용하기 위해 아래 파일을 설치해야 합니다.

 

파이썬 서비스

아래와 같은 server.py 파일이 포함된 Flask 서비스를 만든다고 가정해 봅시다.

from flask import Flask
server = Flask(__name__)
@server.route("/")
 def hello():
    return "Hello World!"
if __name__ == "__main__":
   server.run(host='0.0.0.0')

 

프로젝트에는 다음과 같은 내용의 requirements.txt 파일이 포함됩니다.

Flask==1.1.1

 

최종 프로젝트 패키지는 다음과 같은 구조를 갖게 됩니다.

app
├─── requirements.txt
└─── src
     └─── server.py

 

이제 Python interpreter를 설치하고 프로그램을 실행 할 수 있습니다. 여기서 실행 환경을 Docker의 container를 활용여 구축해보도록 하겠습니다.

 

 

도커를 활용해서 프로젝트 실행하기

파이썬 코드를 실행하기 위해서, Docker image를 이용해서 container를 생성하고 실행해야 합니다. 이 과정을 단계별로 정리하면 다음과 같습니다.

 

  1. Docker image를 빌드하기 위한 Dockerfile 생성
  2. Docker builder를 활용해서 Docker image 생성
  3. 간단한 docker run <image> 커맨드로 container를 생성하고 app 실행

- Dockerfile -

# set base image (host OS)
FROM python:3.8
# set the working directory in the container
WORKDIR /code
# copy the dependencies file to the working directory
COPY requirements.txt .
# install dependencies
RUN pip install -r requirements.txt
# copy the content of the local src directory to the working directory
COPY src/ .
# command to run on container start
CMD [ "python", "./server.py" ]

 

- Docker image build -

$ docker build -t myimage .
Sending build context to Docker daemon 6.144kB
Step 1/6 : FROM python:3.8
3.8.3-alpine: Pulling from library/python
…
Status: Downloaded newer image for python:3.8.3-alpine
---> 8ecf5a48c789
Step 2/6 : WORKDIR /code
---> Running in 9313cd5d834d
Removing intermediate container 9313cd5d834d
---> c852f099c2f9
Step 3/6 : COPY requirements.txt .
---> 2c375052ccd6
Step 4/6 : RUN pip install -r requirements.txt
---> Running in 3ee13f767d05
…
Removing intermediate container 3ee13f767d05
---> 8dd7f46dddf0
Step 5/6 : COPY ./src .
---> 6ab2d97e4aa1
Step 6/6 : CMD python server.py
---> Running in fbbbb21349be
Removing intermediate container fbbbb21349be
---> 27084556702b
Successfully built 70a92e92f3b5
Successfully tagged myimage:latest

 

- Check Docker image - 

$ docker images
REPOSITORY    TAG       IMAGE ID        CREATED          SIZE
myimage       latest    70a92e92f3b5    8 seconds ago    991MB



Dockerfile

Dockerfile은 Docker image를 생성하기 위한 설명서와 같다고 할 수 있습니다.

 

Dockerfile을 통해서 Docker image를 빌드하고 빌드된 Docker image를 통해서 container를 빌드할 수 있습니다.

 

Dockerfile 내용에 대해서 하나씩 자세히 알아보도록 하겠습니다.

FROM — specifies the base (parent) image.

LABEL — provides metadata. Good place to include maintainer info.

ENV — sets a persistent environment variable.

RUN — runs a command and creates an image layer. Used to install packages into containers.

COPY — copies files and directories to the container.

ADD — copies files and directories to the container. Can upack local .tar files.

CMD — provides a command and arguments for an executing container. Parameters can be overridden. 
      There can be only one CMD.
      
WORKDIR — sets the working directory for the instructions that follow.

ARG — defines a variable to pass to Docker at build-time.

ENTRYPOINT — provides command and arguments for an executing container. Arguments persist.

EXPOSE — exposes a port.

VOLUME — creates a directory mount point to access and store persistent data.

 

FROM

FROM 키워드는 사용할 base image (parent image) 입니다. 예를 들어, ubuntu:15.04를 base image로 정하게 되면 아래와 같이 read only인 Image layers를 다운받아서 이를 앞으로 우리가 추가할 Container layer의 기반으로 사용한다는 의미가 됩니다.

https://docs.docker.com/storage/storagedriver/

LABEL

LABEL은 image의 metadata로써, image의 maintainer의 contact info 입니다. 즉, 이미지를 생성하고 지속 관리하는 사람의 연락 정보 입니다. LABEL을 추가함으로써 image build의 성능에 영향을 주지 않습니다.

 

ENV

ENV는 container run time에 사용될 수 있는 영구 환경 변수를 설정할 수 있습니다. 예를 들어, ENV ADMIN="jeff"로 설정했다면, container를 생성하고 ADMIN 변수를 사용할 수 있게 됩니다.

 

RUN

Docker는 RUN 커맨드 이후 상태의 image를 commit 합니다. RUN은 image에 패키지 설치 등의 작업에 사용됩니다. 예를 들어, "RUN apk update && apk upgrade"는 Docker에게 base image로 부터 패키지들을 업데이트 하도록 명령합니다. 여기서 apk는 Apline Linux package manager를 의미합니다. 만약 Alpine이 아닌 Linux base image를 사용한다면 apk 대신 RUN apt-get를 사용하면 됩니다.

또한, RUN은 ["my_executable", "first_param", "second_param"]와 같은 JSON array syntax를 사용하여 위 패키지 설치에 사용되었던 shell form이 아닌 exec form도 사용할 수 있습니다. 예를 들어 다음과 같이 디렉토리를 생성하는 것이 가능합니다: RUN ["mkdir", "/a_directory"]

 

 

COPY

COPY . ./app은 Docker에게 로컬에 위치한 파일과 폴더를 Docker image의 현재 작업 디렉토리에 추가하도록 합니다. 만약 target 디렉토리가 존재하지 않으면 직접 생성하게 됩니다.

위의 예제에서 사용된 COPY requirements.txt . 은 현재 로컬에 있는 requirements.txt 파일을 Docker image의 작업 디렉토리 . 에 추가하도록 합니다.

 

ADD

ADD는 COPY와 같은 작업을 하지만 다른 기능이 존재합니다. 원격  URL을 사용하여 파일을 옮길 수 있고, 로컬 TAR 파일을 extract 할 수도 있습니다.

 

CMD

CMD는 Docker에게 container를 언제 시작할지 알려주는 역할을 합니다. 

 

 

 

참조

[1] You're living in 1985 if you don't use Docker for your Data Science Projects

[2] Learn Enough Docker to be Useful

반응형