안녕하세요? JustKode 입니다. 오늘은 컨테이너 기술을 구현하기 위한 Docker의 사용법에 대해서 배워보는 시간을 가져 보도록 하겠습니다.
오리엔테이션에서 컨테이너 방식으로 프로세스를 격리하여 실행하는 방식이 대두 되기 시작 했다고 이야기 했었습니다. 커널을 공유함으로써 가상화에 많은 자원을 사용하지 않으며, 비슷한 종속성을 가진 컨테이너 끼리는 이미지 자원을 공유하여 최적화 합니다. 또한, 동일한 환경에서 프로세스가 실행 될 수 있도록 하면서 충돌이 일어나지 않도록 프로세스를 구성합니다.
출처: Docker 홈페이지
이러한 가상화 기술을 통해 우리는 프로세스 독립 실행을 통해, 어느 환경에서든 프로그램을 실행 할 수 있게 되었습니다. 하지만, 독립적인 OS를 실행 시킴으로써 오는 Overhead는 감안 해야 겠지만요. 그럼에도 우리는 컨테이너를 실행 함으로써, 로드 밸런싱, Health Check, 예측 가능한 실행 환경을 가져 갈 수 있다는 점은, 매우 큰 장점으로 작용 합니다.
일단, Docker를 사용 하기 전, Docker CLI를 설치하여야 합니다. 운영 체제에 맞게, 아래 링크에 접속하여 설치 해 주세요.
먼저 Docker Image에 대해서 설명 드리겠습니다. Docker Image는 Docker Container를 만들기 위한, 실행 파일 이라고 생각하면 됩니다. 우리는 Docker Image를 어디서 찾아 볼 수 있을까요? 우리는 이를 Docker Hub에서 찾아 볼 수 있습니다.
Docker Hub
저는 Nginx 이미지를 검색 하여 선택 해 보겠습니다. 그럼 다음과 같이 Nginx 이미지 관련 정보를 열람 할 수 있습니다.
Nginx 이미지
그 다음으로, 조금 밑에 내리다 보면 우리는 다음 이미지의 버전 정보를 확인 할 수 있습니다. 여기에 활성화 된 버전 정보를 이용하여, 우리는 이미지를 생성 할 수 있습니다.
Nginx 이미지 버전 정보
이제 Docker CLI에 접근 할 시간입니다. 터미널에서 docker --version
을 입력 하여, 도커가 정상적으로 설치 되었는지 확인 합니다.
$ docker --version
Docker version 20.10.6, build 370c289
자, 우리는 일단 docker pull
명령어를 통해서 이미지를 가져 오도록 하겠습니다. 우리는 nginx의 특정 버전인 1.20을 Pull 해 보도록 하겠습니다.
$ docker pull nginx:1.20
1.20: Pulling from library/nginx
513c6babab2b: Pull complete
91772348f9ab: Pull complete
846cdab430d1: Pull complete
a4a7291136de: Pull complete
6b72e4ce657e: Pull complete
e40ce1e39e7d: Pull complete
Digest: sha256:cd108d06120a7c0d3d073ba4e3eee7b5e6759f0c8a80799e2dbb35d07388840c
Status: Downloaded newer image for nginx:1.20
docker.io/library/nginx:1.20
그 다음 Docker Image를 잘 가져 왔는지 확인 해 볼까요? docker image ls
를 이용하여 현재 있는 Docker Image를 확인 할 수 있습니다.
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.20 807dc38084a8 11 days ago 126MB
이미지를 가져왔으니, 이제 이 이미지를 이용하여 Docker Container를 만들 차례 입니다. docker run [image]
을 이용하여, 현재 가지고 있는 Docker Image를 이용하여, 컨테이너를 생성 할 수 있습니다.
$ docker run -d -p 8080:80 --name my_nginx nginx:1.20
5dfb45ecb86a8b4b51e76cda29c1dbfba3d0752a5fbf999f8fb1a1ae7ad37b1d
일단 주로 쓰이는 옵션에 대해서 설명 드리겠습니다.
run
: 컨테이너를 실행 합니다.-d
: 컨테이너를 detached mode, 즉, 백그라운드에서 실행 한다는 뜻입니다.-p 8080:80
: 호스트의 8080번 포트를 컨테이너의 80번 포트에 mapping 한다는 뜻입니다.--name my_nginx
: --name
옵션을 이용해, 실행 할 컨테이너의 이름을 설정 합니다. 위 코드는 컨테이너의 이름을 my_nginx로 설정 합니다.nginx:1.20
: 저희가 사용할 이미지 입니다. 해당 이미지가 설치 되어 있지 않다면, 설치합니다.우리는 이 과정을 통해 이미지를 간단하게 컨테이너로 실행 할 수 있었습니다. http://localhost:8080 에 접속하면 다음과 같은 화면을 볼 수 있습니다.
Nginx의 성공적 실행
docker ps
를 입력 하면, 현재 실행 중인 컨테이너를 확인 할 수 있습니다.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5dfb45ecb86a nginx:1.20 "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp my_nginx
만약 잠시 컨테이너의 프로세스는 종료 하면서, 스냅샷 (컨테이너 내 설정 및 파일 정버)을 남기고 싶을 땐, docker stop [컨테이너 명 | 컨테이너 아이디]
을 이용 합니다.
$ docker stop my_nginx
my_nginx
docker ps -a
를 이용하여, 모든 상태의 컨테이너를 확인 할 수 있습니다.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5dfb45ecb86a nginx:1.20 "/docker-entrypoint.…" 15 minutes ago Exited (0) About a minute ago my_nginx
다시 실행 하기를 원하신다면, docker start [컨테이너 명 | 컨테이너 아이디]
를 이용 합니다.
$ docker start my_nginx
my_nginx
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5dfb45ecb86a nginx:1.20 "/docker-entrypoint.…" 5 hours ago Up 12 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp my_nginx
만약, 프로세스 실행 상태를 저장하면서 잠깐 일시 정지, 다시 실행을 하고 싶을 때는 위의 방식과 비슷하게 각각 docker pause [컨테이너 명 | 컨테이너 아이디]
, docker unpause [컨테이너 명 | 컨테이너 아이디]
를 입력 하면 됩니다.
더 이상 컨테이너가 필요 하지 않게 되었다면, docker kill [컨테이너 명 | 컨테이너 아이디]
을 이용하여 제거 할 수 있습니다.
$ docker kill my_nginx
my_nginx
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
우리는 Docker Container에 어떻게 Access 할 수 있을까요? 우리는 이를 docker exec -it [컨테이너 명 | 컨테이너 아이디] [실행 할 파일]
을 이용해서 컨테이너 내부 파일에 접근 할 수 있습니다.
다시 docker run -d -p 8080:80 --name my_nginx nginx:1.20
를 입력 해 주신 다음, docker exec -it my_nginx /bin/bash
를 입력 해 주세요. 그럼 다음과 같이 실행 중인 컨테이너 내로 접속 할 수 있습니다.
$ docker exec -it my_nginx /bin/bash
root@5dfb45ecb86a:/#
이런 기존의 이미지로 만든 컨테이너를 직접 실행 한 다음, 컨테이너에 접속해서 환경 설정을 직접 해도 되지만, 이런 식으로 하게되면, 배포가 쉽다는 컨테이너의 장점을 이용하지 못하게 됩니다. 이때, 우리는 어떻게 할 수 있을까요?
이럴 때는, DockerFile 을 이용하면 됩니다. DockerFile은 어떻게 이미지를 구현 할 건지에 대한 내용들을 구성 할 수 있습니다. Django 서버를 여는 예제를 통해서 같이 보겠습니다. 일단 실습을 하기 전 아무 폴더나 만든 후에 다음을 작성해 주세요.
첫 번째로 Dockerfile을 만드는 예제 입니다. 만드신 폴더에 Dockerfile
이라는 이름으로 파일을 만든 후, 다음을 입력 해 주세요.
FROM python:3.9
EXPOSE 8000
ENV mode="development"
COPY /app /app
WORKDIR /app
RUN pip install -r requirements.txt \
&& django-admin startproject mysite . \
&& python manage.py makemigrations \
&& python manage.py migrate
CMD python manage.py runserver 0.0.0.0:8000
두 번째는 파이썬 의존성 정보를 담을 requirements.txt
입니다. 예시 이므로, app 폴더를 만들어, 해당 이름에 django
만 넣도록 하게 하겠습니다.
django
각 명령어의 역할 입니다.
FROM
: DockerFile을 Docker Image로 빌드 시, 기반이 되는 Docker Image를 설정 합니다.EXPOSE
: 컨테이너의 어느 포트를 외부로 노출 시킬 것인지 설정 합니다.ENV
: 환경 변수를 설정 합니다. 키="값" 형태로 삽입 합니다.COPY
: 첫 번째 인자로 들어간 폴더를, 두 번째 인자로 들어간 위치에 복사 합니다.WORKDIR
: 현재 사용 폴더를 해당 폴더로 이동 시킵니다.RUN
: 빌드를 하기 위해 필요한 명령어를 작성합니다. 여기에는 apt-get
, npm
, pip
등의 명령어를 삽입하여, Docker Image를 만드는데 필요한 의존성 파일들을 설치하고, 사전 실행이 필요한 명령어를 사용 하는데 많이 사용합니다.CMD
: docker run
을 통해 실행 했을때, 기본적으로 실행 될 명령어를 입력 합니다.이렇게 입력 한 후, docker build
를 통해, 해당 폴더에 있는 Dockerfile
에 작성 한 내용대로, Docker Image Build를 실행 합니다. -t
옵션을 통해 이미지의 이름을 설정 해 줄 수 있습니다.
$ docker build -t mydjango .
그 다음 만들어진 이미지를 이용해, docker run
으로, 컨테이너를 생성 후 실행 합니다.
$ docker run -d -p 8080:8000 mydjango
http://localhost:8080 에 접속하면 다음과 같은 화면을 볼 수 있습니다.
Django 서버의 성공 적 실행
이렇게 Docker에 대해서 간단하게 다루어 보는 시간을 가졌습니다. 다음 시간에는, Container Orchestration을 위한 Kubernetes에 대해서 배워 보는 시간을 가져 보도록 하겠습니다!