Docker 퀵 스타트 가이드

Docker의 작업 흐름

컨테이너 기동까지의 흐름으로서는 대략적으로 아래와 같다.

  1. 코드를 작성한다.
  2. Docker 이미지를 빌드한다.
  3. 리포지토리에 이미지를 푸시한다.
  4. 프로덕션 환경에서 이미지 다운로드한다.
  5. 컨테이너를 시작한다.

docker pull : 도커 이미지 받아오기

우선은 2번까지는 이미 작성한 것을 사용하는 방법으로서 docker pull 명령에 관해서 살펴보겠다.

DockerHub에서 업로드 된 이미지를 다운로드하면 된다. DockerHub 외에 따로 구축한 docker registry에서도 다운로드 할 수 있다.

이미지를 다운로드하기 위한 명령은 아래와 같은 형식이다.

docker pull [이미지명](:버전)

예를 들어, nginx을 pull을 받으면 아래와 같다.

$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
5b1423465504: Pull complete
1cdde8b981f2: Pull complete
6c0b05f215c0: Pull complete
004f1937a10a: Pull complete
fd61d71c75fe: Pull complete
717bf61a04cf: Pull complete
Digest: sha256:b95a99feebf7797479e0c5eb5ec0bdfa5d9f504bc94da550c2f58e839ea6914f
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

또, 이미지명 뒤에 태그를 붙여 Version을 지정할 수도 있다. 아무것도 지정하지 않으면 최신 버전(latest)이 지정된다.

nginx에 버전을 지정하는 방법은 아래와 같다.

$ docker pull nginx:1.21.1

docker images : 도커 이미지 조회

다운로드했거나 작성한 이미지의 목록은 아래 명령어로 확인할 수 있다.

docker images

예를 들어, 명령어의 실행 결과는 아래와 같이 표시된다.

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    fc5ec3f147e4   13 days ago   135MB

docker rmi : 도커 이미지 삭제

더 이상 필요하지 않은 이미지는 다음 명령으로 삭제할 수 있다.

docker rmi [이미지ID|이미지명]

예를 들어, nginx을 rmi 삭제하면 아래와 같다.

$ docker rmi nginx
Untagged: nginx:latest
Untagged: nginx@sha256:b95a99feebf7797479e0c5eb5ec0bdfa5d9f504bc94da550c2f58e839ea6914f
Deleted: sha256:fc5ec3f147e43825672b6b308944040fa0ba4a547f4b50e911770f0d154eeed0
Deleted: sha256:3e85098616c4513b241d95d1a0c49740da10d191738bdd6b9220eab71ad15ddb
Deleted: sha256:714a2b51cf12dfc0219555fc2c71ff56a99da0f257fc1e81fbdc722d55821519
Deleted: sha256:ca9b331c8e9078528f222eacfdff111fc19a511e3f6282d307780b2d06da0e2a
Deleted: sha256:082aa9054c2265e06a3a62ab2afdbeb22768565808c7e5143f4652a997825b06
Deleted: sha256:f5355920965616631532773783ab892ba7d5b686833964b34968bd64d22b5521
Deleted: sha256:21ec097e7be7f53b7882fa719131a83be79e5b65e73993fa54929e5065e5b3e5

삭제를 하고난 이후에 실제 삭제되었는데 확인해 보자.

$ docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

위에 rmi 명령어로 nginx가 삭제 된 것을 확인 할 수 있다.

docker run : 도커 실행

Docker Image에서 컨테이너를 시작하려면 다음 명령을 실행한다.

docker run [이미지명] (옵션)

옵션을 따로 붙이지 않아도 기동시킬 수 있지만, 보다 편리하게 사용하기 위한 아래와 같은 옵션이 준비되어 있다.
여기에 자주 사용하는 옵션만 있으므로, 다른 옵션에 대해서는 도커 공식 문서를 참조 하여라.

옵션 의미 사용 예시
--name 컨테이너 이름 지정 docker run --name "test" nginx
-d 백그라운드 실행 docker run -d nginx
-it (shell 지정) 콘솔에 결과 출력 docker run -it nginx bash
-p host:container 포트 매핑 docker run -p 8080:80 nginx
-v host:container 디렉터리 공유 docker run -v /test1:/test2 nginx
-e 환경 변수 설정 docker run -e foo=bar nginx
-w 안에 작업 디렉터리 지정 docker run -it -w=/tmp/work nginx bash

예시로서 기동시의 설정과 실행 명령을 아래와 간다.

docker run --name my-nginx -p 8080:80 -v ~/develop/docker:/usr/share/nginx/html -e foo=bar -w /tmp/work -it nginx bash
  • 사용하는 이미지 : nginx
  • 컨테이너 이름 : my-bash
  • 포트 : 컨테이너의 80 포트를 호스트의 8080에 매핑
  • 디렉터리 : 호스트의 ~/develop/docker을 컨테이너의 /usr/share/nginx/html에 마운트
  • 환경 변수 : foo에 bar을 설정
  • 작업 디렉터리 : /tmp/work
  • 콘솔에 결과를 출력
  • 쉘은 bash를 지정

docker ps : 컨테이너 목록 조회

컨테이너의 목록을 조회하기 명령어로서는 아래와 같다. 이 경우 작동중인 컨테이너만 표시된다.

docker ps

실행 중인 컨테이너를 조회해 보자.

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
caf5180d8506   nginx     "/docker-entrypoint...."   4 minutes ago   Up 7 seconds   0.0.0.0:8080->80/tcp   my-nginx

실행 중인 컨테이너가 없다면 아래와 같이 표시될 것이다.

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

중지된 컨테이너를 포함해 모든 컨테이너를 보고 싶다면 -a 옵션을 추가하여 실행하면 된다.

docker ps -a

-a 옵션을 추가하여 실행하면 아래와 같이 중지된 컨테이너도 확인할 수 있다.

$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS                      PORTS     NAMES
caf5180d8506   nginx     "/docker-entrypoint...."   6 minutes ago   Exited (0) 32 seconds ago             my-nginx

도커 실행 중지 : docker stop

실행 중 컨테이너를 중지하려면 다음 명령을 실행한다.

docker stop [컨테이너ID|컨테이너명]

여기서 나오는 “컨테이너ID"와 “컨테이너명"은 위에 docker ps을 실행했을 때 출력된는 맨왼쪽와 맨오른쪽의 컬럼 CONTAINER ID, NAME이다.

실습으로 먼저 nginx를 실행한다.

$ docker run --name my-nginx -p 8080:80 -v ~/develop/docker:/usr/share/nginx/html -d nginx
caf5180d85067eae71a9ee6f4bb52e8222cc7f6a54b4b318384d0cd2c8794a63

시작이 되고, 컨테이너를 중지한다.

$ docker stop my-nginx
my-nginx

docker logs : 컨테이너 실행 로그 확인

컨테이너 실행 로그를 보는 방법은 다음과 같다.

docker logs [컨테이너ID|컨테이너명]

위에 docker ps을 실행해서 나온 컨테이너 기준이라면 아래와 같이 명령어를 입력하면 된다.

$ docker logs caf5180d8506
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh

... 중간 생략 ...

2022/09/05 18:20:28 [notice] 1#1: start worker process 27
2022/09/05 18:20:28 [notice] 1#1: start worker process 28

docker inspect : 컨테이너의 메타데이터 조회

컨테이너의 메타데이터를 보려면 다음 명령을 사용한다.

docker inspect [컨테이너ID|컨테이너명]

실제로 명령어를 실행해 보면 아래와 같이 출력된다.

% docker inspect caf5180d8506
[
    {
        "Id": "caf5180d85067eae71a9ee6f4bb52e8222cc7f6a54b4b318384d0cd2c8794a63",
        "Created": "2022-09-05T18:10:41.606382836Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 5950,
            "ExitCode": 0,

... 중간 생략 ...
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

docker exec : 도커 실행

백그라운드로 실행하여 현재 동작중인 컨테이너에 들어가려면 아래 명령을 사용한다. 이 때, 쉘을 지정해야 한다.

docker exec -it [컨테이너ID|컨테이너명] [Shell명] 

my-nginx 컨테이너에 bash을 지정하여 들어간다.

$ docker exec -it my-nginx bash
root@61dc29dec3e4:/tmp/work#

docker rm : 컨테이너 삭제

중지된 컨테이너는 아래 명령을 사용하여 삭제할 수 있다.

docker rm [컨테이너ID|컨테이너명]

위에서 사용한 컨테이너 my-nginx를 삭제 해보겠다.

$ docker rm my-nginx
my-nginx

컨테이너, 이미지 일괄 삭제

docker rmi, docker rm 명령으로 각각 이미지 삭제, 컨테이너 삭제를 할 수 있다는 것을 위에서 설명하였다. 이 명령으로는 각각 삭제 대상을 지정해야 하기 때문에 일괄적으로 삭제를 하고 싶은 경우에는 불편하다. 일괄 삭제 방법은 아래와 같다.

중지된 컨테이너와 익명 이미지 삭제:

docker system prune

시작 중인 컨테이너를 포함하여 모든 컨테이너 삭제:

docker rm -vf $(docker ps -a -q)

모든 이미지 삭제:

docker rmi -f $(docker images -a -q)

Docker Image 만들기

위에서는 Dokcer Image를 받아오는 방법으로 DockerHub에서 리포지토리를 pull 하였다.

이 외에도 Docker Image를 받아오는 방법에는 여러 가지가 있으며, 여기에서는 다음 두 가지 점을 살펴 보겠다.

  • 컨테이너에서 이미지를 만듭니다.
  • Dockerfile에 기술한다.

컨테이너에서 이미지 만들기

컨테이너내에서 새롭게 패키지를 다운로드 했을 때에는 기동했을 때에 사용한 이미지로부터 작성되는 컨테이너와는 다른 상태의 컨테이너가 된다. 이렇게 새롭게 추가가 이루어진 컨테이너를 작성할 수 있는 이미지를 만드는 방법으로서 아래와 같은 명령이 있다.

docker commit [컨테이너ID] [새로 작성되는 컨테이너명]

docker container ls

docker container ls 명령어를 실행했을 때 표시되는 항목에 대해 알아보도록 하자.

$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
2axaf8tx4gjd        registry            "/entrypoint.sh /etc..."   7 weeks ago         Up 7 weeks          0.0.0.0:5000->5000/tcp   devkuma-private-registry

실행중인 컨테이너 및 종료의 컨테이너를 표시하는 명령이다.

항목 내용
CONTAINER ID 컨테이너를 식별하기 위한 유일한 식별자
IMAGE 컨테이너를 만드는 데 사용한 Docker Image
COMMAND 컨테이너에서 실행되는 응용 프로그램 프로세스
CREATED 컨테이너 생성 후 후 경과 시간
STATUS Up (실행) Exited (종료) 등의 컨테이너의 실행 상태
PORTS 호스트 포트와 컨테이너 포트의 연결 관계 (포트 포 워 딩)
NAMES 컨테이너 이름

Dockerfile에 작성

ockerfile에 이미지에 대한 설정을 쓰면 이미지를 만들 수 있다. Docker 이미지를 만들 때 반듯이 필요한 설정 파일이다. 이 파일에 작성된 지침을 인스트럭션(instruction) 이미지가 만들어 진다.

DDockerfile은 다음과 같다.

Dockerfile

FROM centos:7
  
RUN echo "now building..."
RUN yum -y install httpd
RUN sed -i '/#ServerName/a ServerName www.example.com:80' /etc/httpd/conf/httpd.conf
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

이 파일을 보면 FROM이나 RUN, ADD 등의 명령과 인수라고 하는 구조로 Dockerfile가 쓰여져 있는 것을 알 수 있다. FROM이나 RUN, ADD 등 명령이 각각 무엇을 의미와 사용법은 아래의 표와 같다. 여기에서도 자주 이용하는 것만을 있고, 그 외의 것에 대해서는 공식 문서를 참고 하여라.

명령 의미 사용법
FROM 기본 이미지 지정 FROM [이미지명] 또는 FROM [이미지명]:[태그]
RUN 명령 실행 RUN [커멘드]
CMD 컨테이너 시작시 실행 명령 CMD [커멘드] 또는 CMD ["실행 바이너리", "매개 변수 1", "매개 변수 2"]
EXPOSE 포트 해제 EXPOSE [포트]
VOLUME 마운트 VOLUME ["/data"]
ADD 파일/디렉터리 추가 ADD [소스] [대상]
COPY 파일/디렉터리 복사 COPY [소스] [대상]
WORKDIR 작업 디렉터리 지정 WORKDIR [디렉터리 경로]
ENV 환경 변수 설정 ENV [key]=[value]

인스트럭션(instruction)

FROM
  • 해당 Docker 이미지의 기본 이미지를 지정한다.

mysql을 지정하는 경우는 다음과 같다.

FROM mysql
COPY
  • 호스트 컴퓨터의 파일이나 디렉터리를 Docker 컨테이너에 복사한다.
  • 이미지가 Build 될 때 한 번만 실행된다.
COPY ./cnf/my.cnf /etc/mysql/conf.d/my.cnf
RUN
  • Docker 이미지를 Docker에서 실행하는 명령을 정의한다.
  • COPY와 마찬가지로 Build 될 때 한 번만 실행된다.
  • 특별한 지침이 없는 경우는 사용되지 않는다.

다음은 Test.java를 javac로 컴파일하고 있다.

RUN javac Test.java
ADD

기본은 COPY과 동일하며, 다음과 같은 기능이 추가로 있다.

  • source가 remote URL이면 다운로드 후 destination에 복사한다.
  • source가 자주 사용되고 있는 압축 파일 형식(zip 등)이면 압축을 풀어준다.
  • source가 remote URL + 압축 파일 형식인 경우 압축을 풀지 않는다.
CMD
  • 컨테이너에서 실행하는 프로세스 (명령)을 지정한다. 이것은 이미지를 실행할 때마다 실행되는 명령이다.
  • CMD는 Dockerfile에 하나만 만들 수 있다. 여러개를 만들 때 맨 마지막에있는 명령만 실행된다.

다음은 mysqld를 실행하고 있다.

CMD ["mysqld"]

도커 빌드 : docker build

위에 Dockerfile의 명령을 보면 Docker run에서 옵션과 비슷한 것을 할 수 있다.

이렇게 작성한 Dockerfile을 사용하여 Image를 빌드하려면 아래 명령을 사용한다.

docker build [Dockerfile 경로]

기본적으로 Dcokerfile라는 이름을 사용하여 파일 이름을 변경하려면 Build시 추가 옵션을 주어야 한다. -f

이 빌드를 실행했을 때의 이미지는 Docker 파일의 각 행(Layer)마다 하나씩 실행해 나가듯이 작성된다.

이는 빌드를 실행했을 때의 출력을 보면 알 수 있다. 위의 Dockerfile을 실행하면 다음과 같다.

$ docker build .
[+] Building 89.3s (8/8) FINISHED
 => [internal] load build definition from Dockerfile                                                                           0.0s
 => => transferring dockerfile: 252B                                                                                           0.0s
 => [internal] load .dockerignore                                                                                              0.0s
 => => transferring context: 2B                                                                                                0.0s
 => [internal] load metadata for docker.io/library/centos:7                                                                    5.0s
 => [1/4] FROM docker.io/library/centos:7@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407             49.1s
 => => resolve docker.io/library/centos:7@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407              0.0s
 => => sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407 1.20kB / 1.20kB                                 0.0s
 => => sha256:73f11afcbb50d8bc70eab9f0850b3fa30e61a419bc48cf426e63527d14a8373b 530B / 530B                                     0.0s
 => => sha256:c9a1fdca3387618f8634949de4533419327736e2f5c618e3bfebe877aa331352 2.77kB / 2.77kB                                 0.0s
 => => sha256:6717b8ec66cd6add0272c6391165585613c31314a43ff77d9751b53010e531ec 108.37MB / 108.37MB                            46.2s
 => => extracting sha256:6717b8ec66cd6add0272c6391165585613c31314a43ff77d9751b53010e531ec                                      2.6s
 => [2/4] RUN echo "now building..."                                                                                           0.3s
 => [3/4] RUN yum -y install httpd                                                                                            34.3s
 => [4/4] RUN sed -i '/#ServerName/a ServerName www.example.com:80' /etc/httpd/conf/httpd.conf                                 0.2s
 => exporting to image                                                                                                         0.2s
 => => exporting layers                                                                                                        0.2s
 => => writing image sha256:b32d2ca733218ab8a1d1840b775d2baed16cab3e1775477ae3839e990ffbc479                                   0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

이 출력 결과를 보면 Dockerfile에 작성한 대로 FROM으로 작성한대로 베이스 이미지 위에 하나씩 행(Layer)을 실행해 나가는 것을 볼 수 있다.

신규 이미지가 생성되었는지 확인할 있을 것이다.

% docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
<none>       <none>    b32d2ca73321   13 minutes ago   417MB

여기서는 REPOSITORY, TAG<none>으로 지정되지 않은 것을 볼 수 있다.

그리고, 아래의 명령어로 위에 내용을 다시 확인할 수도 있다.

docker history [이미지ID|이미지명]
$ docker history b32d2ca73321
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
b32d2ca73321   9 minutes ago   CMD ["/usr/sbin/httpd" "-D" "FOREGROUND"]       0B        buildkit.dockerfile.v0
<missing>      9 minutes ago   EXPOSE map[80/tcp:{}]                           0B        buildkit.dockerfile.v0
<missing>      9 minutes ago   RUN /bin/sh -c sed -i '/#ServerName/a Server...   11.8kB    buildkit.dockerfile.v0
<missing>      9 minutes ago   RUN /bin/sh -c yum -y install httpd # buildk...   117MB     buildkit.dockerfile.v0
<missing>      9 minutes ago   RUN /bin/sh -c echo "now building..." # buil...   0B        buildkit.dockerfile.v0
<missing>      6 months ago    /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      6 months ago    /bin/sh -c #(nop)  LABEL org.label-schema.sc...   0B
<missing>      6 months ago    /bin/sh -c #(nop) ADD file:5b1e63a3cb041177b...   301MB

생성한 이미지 push

위와 같은 방법으로 만든 이미지를 DockerHub에 게시하는 방법을 살펴 보겠다.

먼저, DokcerHub의 계정이 필요하므로 아래에서 생성한다.

공개를 하려면 먼저 태그를 지정해야 한다. 아래와 같이 DockerHub에서 등록한 사용자 이름을 사용하여 태그를 붙여준다.

docker tag [Image ID] [DockerHub 사용자명]/[리포지토리명]

위에 신규 생성한 이미지에 태그를 지정하면 아래와 같이 명령을 실행하면 된다.

docker tag b32d2ca73321 devkuma/centos7

실행을 하면 아무 내용이 표시가 출력되지 않는다.

% docker tag b32d2ca73321 devkuma/centos7

이미지를 조회해 보면 REPOSITORY, TAG가 지정한 되로 들어가 있는 것을 볼 수 있다.

% docker images
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
devkuma/centos7   latest    b32d2ca73321   17 minutes ago   417MB

그리고, push를 하기 전에 DockerHub에 로그인해야 하기 때문에 다음을 실행하여 로그인한다.

docker login
% docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: devkuma
Password:

Login Succeeded

Logging in with your password grants your terminal complete access to your account.
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
user@AL02263852 docker

여기까지 완료하였다면, DockerHub에 리포지토리를 업로드할 수 있게 되었다.

docker push [DockerHub 사용자명]/[리포지토리명]

이제는 다음 명령을 실행한다.

$ docker push devkuma/centos7
Using default tag: latest
The push refers to repository [docker.io/devkuma/centos7]
5818d7ffd9ac: Pushed
085e94a3a50e: Pushed
6a9a145374b8: Pushed
65f23ff12f4d: Mounted from library/centos
latest: digest: sha256:2845b5f6439dff6a80ed8ed45a10cfd39e19d8178182fe043db939ccc3b7f982 size: 1156

여러 컨테이너 관리(docker-compose)

여러 컨테이너를 시작하고 중지하려는 경우 각각에 대해 docker run, docker stop을 실행하는데 시간이 많이 걸린다. 이를 해결하기 위해 일괄적으로 관리하는 것이 docker-compose이다. 이 방법은 yaml 파일(docker-compose.yaml)에 여러 컨테이너의 정보를 쓰고 관리한다.

예제 파일 내용은 다음과 같다.

docker-compose.yaml

version: '3'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

자세한 내용은 여기서는 설명하지 않겠지만, 대략적으로는 version 속성에 docker-compose의 version을 넣고, services 속성에는 기동하려는 서버의 정보를 넣는다. 이 파일의 경우라면 DB 서버와 Web 서버를 각각 기동하도록 작성되어 있다. 또 그 하위에 작성되어 있는 내용은 Dockerfile에 작성하는 내용과 유사하다. 자세한 내용은 아래를 Docker 공식 문서를 참조하여라.

이러한 yaml 파일을 작성한 후에 다음 명령을 실행하여 컨테이너를 시작할 수 있다.

docker-compose –f [yaml 파일 경로] up

그리고, 시작된 컨테이너의 경우에는 yaml 파일에 나열된 컨테이너를 중지하려면 다음 명령을 실행한다.

docker-compose -f [yaml 파일 경로] dowm

이렇게 시작된 여러 컨테이너의 로그를 모와서 보려고 하려면 다음 명령을 실행한다.

dokcer-compose -f [yaml 파일 경로] logs

서버의 클러스터화를 구성 등과 같은 하기 위해, Web 서버 등을 여러 대를 기동하고 싶은 경우가 있다. 이렇개 여러대를 기동한 같은 역할을 해주는 것이 컨테이너를 복제(replica)라고 한다. 이러한 docker-compose에서 컨테이너 복제본을 여러 개를 시작하는 방법을 살펴 보겠다.

여러 개의 부팅을 수행하려면 위의 yaml 파일의 포트에 대한 설정을 변경해야 한다. 특히 포트가 각 컨테이너에서 중복되지 않도록 범위 표기해야 한다.

docker-compose2.yaml

version: '3'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000-3004:3000"
    depends_on:
      - db

이렇게 작성된 내용을 변경하면 호스트 측 포트에 3000,3001,3002,3003,3004가 할당되므로 5개의 복제본 세트를 만들 수 있다. 이러한 docker-compose 파일을 사용하여 시작을 수행하지만 up 명령을 실행할 때 –scale 옵션을 추가하고 복제본 수를 지정한다.

docker-compose –f [yaml 파일 경로] up –scale [컨테이너 이름]=[복제본 수]

네트워크

docker-compose로 정의된 컨테이너는 기본 설정으로 서로 통신할 수 있다. 그러나 다른 위치(yaml에 작성된 컨테이너 이외의 컨테이너)에서는 액세스할 수 없게 되어 있다. 이는 컨테이너가 시작될 때 네트워크 네임스페이스가 만들어지고 컨테이너가 할당되기 때문이다.

컨테이너를 개별적으로 시작했을 경우에 특별히 설정을 따로하지 않으면, 디폴트로 준비되어 있는 Bridge 네트워크에 연결처럼 연결되도록 네트워크 네임스페이스가 만들어 진다. 한편 docker-compose에서 작성한 컨테이너 군집들은 다른 Bridge 네트워크를 개별적으로 설정하고, 그 Bridge 네트워크에 연결되도록 네트워크 네임스페이스가 만들어 진다.
따라서 docker-compose에서 만든 컨테이너와 개별적으로 만든 컨테이너는 통신할 수 없다.

이 문제를 해결하고 연결하려면 네트워크를 설정해야 한다. (여기서는 설명하지 않겠다. 차후에 이 내용에 대해서 다뤄보겠다.)

네트워크 목록을 보려면 다음 명령을 실행한다.

docker network ls
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
7f8103f64ff5   bridge    bridge    local
540c2f32637b   host      host      local
a0053c593c0e   none      null      local

이 출력 결과를 보면 DRIVER 열에 몇 가지 유형이 있다는 것을 알 수 있다. 이는 네트워크 모드에 해당한다. Docker 네트워크에는 다음과 같은 4가지 모드가 있다.

  • bridge
    • 호스트 안의 DockerBridge 네트워크로부터 IP가 배분되기 때문에 IP 레인지가 호스트와는 별개가 된다.
  • host
    • 호스트의 IP 레인지로부터 IP가 나뉘어져 또 호스트의 포트를 이용하므로, -p 옵션등의 포트의 매핑은 할 수 없다.
  • null
    • Bridge에도 호스트에도 링크되지 않고, IP가 배분되지 않는다. 따라서, 접속 불가 상태가 된다.
  • overlay
    • 복수 호스트의 경우에 사용한다.

새 네트워크를 만들려면 다음 명령을 실행한다.

docker network create –driver bridge [네트워크명]

네트워크를 삭제하려면 다음 명령을 실행한다.

docker network rm [네트워크명]

스토리지

컨테이너는 라이프 사이클가 짧을 수 있으며 데이터는 컨테이너가 아닌 호스트에 저장된다.
이를 위해 docker run 명령에서 -v 로 지정한 것처럼 호스트의 폴더와 컨테이너의 폴더를 지정하고 마운트를 수행한다.




최종 수정 : 2022-09-06