제가 이번에 하게될 프로젝트에서는 자연어 처리 관련 딥러닝 모델을 활용하게 됩니다. 이러한 딥러닝 모델은 각각의 모델마다 사용해야하는 패키지, 서버 환경 등이 제각각이기 때문에 사용하는데 주의가 필요합니다. 딥러닝을 활용하여 서비스를 배포하기 위해서는 누구나 한번쯤 사용할법한 도커에 대해서 알아본 내용을 이번 포스팅에서 정리하고자 합니다. 우선 도커가 등장한 배경과 그리고 도커의 핵심 개념인 컨테이너와 이미지에 대해 알아보고 실제로 도커를 설치하고 컨테이너를 실행해 보도록 하겠습니다.
What is Docker?
도커란?
도커는 컨테이너 기반의 오픈소스 가상화 플랫폼입니다.
컨테이너라 하면 배에 실는 네모난 화물 수송용 박스를 생각할 수 있는데 각각의 컨테이너 안에는 옷, 신발, 전자제품, 술, 과일등 다양한 화물을 넣을 수 있고 규격화되어 컨테이너선이나 트레일러등 다양한 운송수단으로 쉽게 옮길 수 있습니다.
이처럼 도커에서 이야기하는 컨테이너도 다양한 프로그램, 실행환경 등을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해줍니다. 매번 사용하는 패키지를 다시 깔거나 버전을 새로 맞추지 않아도 내가 짠 코드가 안정적으로 돌아갈 수 있도록 어디에서든 실행할 수 있습니다.
Docker for Mac / Docker for Windows
도커를 맥이나 윈도우즈에 설치하려면 Docker for mac 또는 Docker for windows를 설치하면 됩니다. 파일을 다운받고 설치하고 재부팅하면 대부분 문제없이 완료됩니다.
컨테이너(Container)
도커에서 가장 중요한 개념은 컨테이너와 함께 이미지라는 개념입니다.
이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로 상태값을 가지지 않고 변하지 않습니다(Immutable). 컨테이너는 이미지를 실행한 상태라고 볼 수 있고 추가되거나 변하는 값은 컨테이너에 저장됩니다. 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 남아있습니다.
예를 들어 내가 필요한 패키지를 모두 설치한 이미지를 가지고 있으면, 코드나 설정값에 약간의 변화를 준 컨테이너를 여러개 만들 수 있습니다. Docker Image Hub에 가면 다양한 소프트웨어 업체 및 개인이 올려둔 도커 이미지를 확인할 수 있습니다. 유저는 자신만의 이미지를 생성하거나 도커허브에 올라와있는 이미지를 활용하여 컨테이너를 자유롭게 생성할 수 있습니다.
How to create a Docker image
도커는 이미지를 만들기 위해 Dockerfile이라는 파일에 자체 DSLDomain-specific language언어를 이용하여 이미지 생성 과정을 적습니다. 아래에 문법에 대해 자세히 다루겠지만 아래의 샘플을 보면 그렇게 복잡하지 않다는 걸 알 수 있습니다.
Dockerfile
1 | # Base Image |
위와 같은 dockerfile을 생성한 후 소스코드가 있는 폴더에 넣어둔 후 도커 이미지 생성을 진행하면 도커 이미지가 생성됩니다.
몇 가지 중요한 문법은 아래와 같습니다.
FROM : Docker hub에 있는 image 의 이름을 명시하면 됩니다. 자신이 구현하고자 하는 딥러닝 모델의 환경에 맞는 이미지를 찾아서 적습니다. 하나의 Docker 이미지는 base 이미지부터 시작해서 기존 이미지위에 새로운 이미지를 중첩해서 여러 단계의 이미지 층(layer)을 쌓아가며 만들어집니다.
FROM 명령문은 이 base 이미지를 지정해주기 위해서 사용되는데, 보통 Dockerfile 내에서 최상단에 위치합니다. base 이미지는 일반적으로 Docker Hub와 같은 Docker repository에 올려놓은 잘 알려진 공개 이미지인 경우가 많습니다.
RUN : RUN 명령문은 마치 쉘(shell)에서 커맨드를 실행하는 것 처럼 이미지 빌드 과정에서 필요한 커맨드를 실행하기 위해서 사용됩니다. 쉘(shell)을 통해 거의 못하는 작업이 없는 것 처럼 RUN 명령문으로 할 수 있는 작업은 무궁무진하지만 보통 이미지 안에 특정 소트트웨어를 설치하기 위해서 많이 사용됩니다.
CMD : CMD 명령문은 해당 이미지를 컨테이너로 띄울 때 디폴트로 실행할 커맨드나, ENTRYPOINT 명령문으로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용합니다. CMD 명령문과 RUN 명령문이 햇갈릴 수가 있는데, RUN 명령문은 이미지 빌드 시 항상 실행되며, 한 Dockerfile에 여러 개의 RUN 명령문을 선언할 수 있습니다. 반면에, CMD 명령문은 이미지를 continaer로 띄울 때 딱 한 번 실행 기회를 가지게 됩니다.
EXPOSE : EXPOSE 명령문은 네트워크 상에서 컨테이너로 들어오는 트래픽(traffic)을 리스닝(listening)하는 포트와 프로토콜를 지정하기 위해서 사용됩니다. 호스트 컴퓨터로부터 해당 포트로의 접근을 허용하려면, docker run 커맨드를 -p 옵션을 통해 호스트 컴퓨터의 특정 포트를 포워딩(forwarding)시켜줘야 합니다.
COPY : COPY 명령문은 호스트 컴퓨터에 있는 디렉터리나 파일을 Docker 이미지의 파일 시스템으로 복사하기 위해서 사용됩니다. 도커 컨테이너 안에 소스파일을 밀어넣는 역할을 합니다.
How to deploy a Docker container
Docker build
이미지를 빌드하는 명령어 예시는 다음과 같습니다.
1 | docker build -t image_name /path_to_image/ |
위와 같이 생성할 이미지 이름을 지정하기 위한 -t(–tag) 옵션만 알면 빌드가 가능합니다.
이미지가 잘 생성되었는지 확인하기 위해서는 아래와 같은 명령어를 사용할 수 있다.
1 | docker images |
output:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
Docker run
Docker를 사용하면서 가장 자주 접하는 커맨드는 단연 컨테이너를 실행하기 위해서 쓰이는 docker run입니다. docker run 커맨드는 상당히 여러가지 옵션을 통해 다양한 방식으로 컨테이너를 실행할 수 있도록 해줍니다. 아래는 docker run을 사용하는 다양한 예제입니다.
-it 옵션
-i 옵션과 -t 옵션은 같이 쓰이는 경우가 매우 많은데요. 이 두 옵션은 컨테이너를 종료하지 않은체로, 터미널의 입력을 계속해서 컨테이너로 전달하기 위해서 사용합니다. 따라서, -it 옵션은 특히 컨테이너의 쉘(shell)이나 CLI 도구를 사용할 때 매우 유용하게 사용됩니다.
1 | $ docker run -it python:3.8-alpine |
-d 옵션
많은 경우 컨테이너를 백그라운드에서 실행해야 하는데 이 때는 -d 옵션을 사용하면 됩니다. -d 옵션을 사용하면 컨테이너가 detached 모드에서 실행되며, 실행 결과로 컨테이너 ID만을 출력합니다. 예를 들어, python:3.8-alpine 이미지로 부터 python -m http.server 명령어를 백그라운드로 실행한 결과는 아래와 같습니다.
1 | $ docker run -d python:3.8-alpine python -m http.server |
이 명령어를 -d 옵션없이 실행했다면, 해당 터미널에서 Ctrl + C를 눌러서 빠져나오는 순간 해당 컨테이너는 종료될 것입니다.
이렇듯 금번 프로젝트에서 사용한 도커에 대한 내용을 정리하였습니다. 다음 포스팅은 역시 이번 프로젝트에서 사용하게 된 쿠버네티스 환경에 대하여 살펴보도록 하겠습니다.