도커 컴포즈가 등장하게 된 배경
지금까지 위의 게시물들을 순서대로 보셨다면 컨테이너가 무엇인지 알고 계실겁니다.
이미지를 실행중인 환경이 컨테이너이고 하나의 이미지를 이용해서 여러개의 컨테이너를 만들어 낼 수 있었습니다.
이제 많은 이미지가 등장하고 여러개의 컨테이너를 만들어야 하는 서비스가 등장함에 따라서, 한꺼번에 컨테이너를 관리해주는 것의 필요성을 느끼게 되었습니다. 또 추가적으로 늘 네트워크 설정을 해서 컨테이너간 통신을 하는 것에 불편함을 느낀 사람들은 그것들을 한번에 해주는 툴을 만들기 시작합니다.
저희가 mongo 이미지를 이용해서 컨테이너를 실행하는 예를 들어 보겠습니다.
docker run -d \
--name mongodb \
-p 27017:27017 \
-e MONGO-INITDB_ROOT_USERNAME=admin \
-e MONGO-INITDB_ROOT_PASSWORD=password\
--net mongo-network \
mongo
이름은 mongodb로 짓고 , 포트 설정은 27017:27017, 이 이미지를 컨테이너로 활용해서 원하는 대로 사용하려면 이렇게 환경변수도 설정을 해줘야 합니다.
이걸 간단하게 쉘에서 실행하는 docker run을 사용하면 이렇게 명령을 사용자가 입력을 해야합니다.
이런 명령어 실행은 컨테이너를 하나만 실행할 때는 큰 문제가 되지 않았습니다.
그러나 사용을 하면 할수록 사용자들에게 불만이 생기기 시작했습니다.
그 불편함들은 컨테이너를 실행해야 할때, 명령 실행 중 실수로 오타를 치는 경우의 불편함, 오랜만에 사용하려니 명령어를 까먹는 문제까지 많은 불편함이 생겼습니다. 그래서 도커를 사용하는 사용자들은 자동화를 원했고 그것을 가능하게 해주는 것이 docker compose 입니다.
docker compose란
Docker Compose는 다중 컨테이너 애플리케이션을 정의 공유할 수 있도록 개발된 도구로 단일 명령을 사용하여 모두 실행 또는 종료할 수 있도록 개발된 도구입니다.
docker compose는 명령을 자동화해주기 위해서 등장했기 때문에 기본적으로 docker run을 이용해서 할 수 있는 모든 작업을 할 수가 있습니다.
Docker compose를 사용함으로써 여러개의 컨테이너로 구성된 어플리케이션을 하나의 파일을 이용해서 한번에 올리거나 내리는 것이 가능해졌습니다.
이러한 편리함때문에, Docker compose는 개발환경이나 테스트 환경에서 컨테이너 오케스트레이션(Container Orchestration) 도구로 많이 사용됩니다.
일반적으로 docker for desktop을 설치했다면 docker-compose패키지도 함께 설치가 되어있을 것 입니다.
다만 그림에서 보이듯 docker-compose는 도커 엔진에 포함된 기능이 아니다 보니, 도커 엔진만 설치한 경우에는 설치가 되어있지 않은 경우가 있습니다.
아래 공식 사이트를 참고해서 설치하세요!
https://docs.docker.com/compose/install/
도커 컴포즈 파일 형식
docker run command
원래는 컨테이너간 통신을 위해서는 docker network create 원하는_네트워크_이름 로 도커 네트워크를 생성 후 2개의 run명령을 실행해야합니다.
이렇게 하면 수동으로 네트워크를 만들어서 직접 컨테이너를 추가해주는 과정을 겪어야만 합니다.
docker run -d \
--name mongodb \
-p 27017:27017 \
-e MONGO-INITDB_ROOT_USERNAME=admin \
-e MONGO-INITDB_ROOT_PASSWORD=password\
--net mongo-network \
mongo
docker run -d \
--name mongo-express \
-p 8080:8080 \
-e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \
-e ME_CONFIG_MONGODB_ADMINPASSWORD=password \
-e ME_CONFIG_MONGODB_SERVER=mongodb\
--net mongo-network \
mongo-express
docker-compose file
도커 컴포즈 파일은 기본적으로 docker-compose.yml 파일을 사용합니다.
일반적으로 docker-compose파일은 프로젝트의 최상위 디렉토리에 위치시킵니다. 개발자가 프로젝트 디렉토리에 들어오자마자 손쉽게 어플리케이션을 올릴 수 있도록 하기 때문에 생긴 관행입니다.
docker-compose.yml 파일의 구조를 설명하기 위해서 mongo-db의 docker-compose파일을 가져오겠습니다. 이 파일은 일반적인 docker-compose 파일입니다.
version:'3'
services:
mongodb: #어플리케이션 설정
image:mongo
ports:
-27017:27017
environment:
-MONGO-INITDB_ROOT_USERNAME=admin
-MONGO-INITDB_ROOT_PASSWORD=password
mongo-express: #어플리케이션 설정
image:mongo-express
ports:
-8080:8080
environment:
-ME_CONFIG_MONGODB_A...
...
.
.
networks:
# 네트워크 설정
volumes:
# 볼륨 설정
이 docker-compose 파일 을 순차적으로 설명해보겠습니다.
설명에 앞서 docker-compose파일은 들여쓰기가 상당히 중요합니다. 따라서 들여쓰기 level 실수를 하지 않을 수 있도록 합시다.
version
version : Docker Compose 규격의 어떤 버전을 사용하는지 명시합니다.
version: '3' 은 도커컴포즈 버전을 3으로 설정하겠다는 의미입니다.
Docker Compose는 1.x, 2.x, 3.x 버전으로 나뉘게 되며, 각 버전마다 기능들이 상이하므로 이용하려는 버전의 기능을 명확히 인지하고 사용하는 것이 좋습니다.
저희는 3.x버전을 사용할 것인데 3.x버전은 Docker Compose와 Docker Swarm간 호환이 가능합니다.
- 여기서 도커컴포즈의 버전 및 업그레이드 정보를 볼 수 있습니다.
- https://docs.docker.com/compose/compose-file/legacy-versions/
도커 컴포즈 사용의 장점
- 메인 애플리케이션 뿐만 아니라 정상적으로 구동되기 위해서 필요한 기반 시스템까지 Docker Compose로 설정합니다. 이것은 사용자가 로컬에서 별도의 셋업 없이 Docker Compose 명령 한번으로 어플리케이션을 올릴 수 있게 되는 장점이 있습니다.
- 관리가 용의합니다. 수정이 쉽고 포트를 바꾸는 등 설정을 바꾸는 것이 용이합니다.
- 네트워크 설정이 간단해집니다. docker compose를 사용하면 도커의 이름만을 사용해서 서로 통신할 수 있는 공용 네트워크를 제공합니다(creating common Network). 그래서 특별한 경우가 아니라면 따로 새로운 네트워크를 생성해 줄 필요성이 없습니다.
- 이것이 명령에서는 네트워크 설정을 해줬지만, docker compose파일에서는 따로 해주지 않은 이유입니다.
서비스 영역과 서비스 영역의 주요 필드
services
services 는 독립된 컨테이너에서 돌아가는 애플리케이션의 구성 요소입니다. 가장 먼저 프로젝트에서 개발하고 있는 애플리케이션 자체가 서비스가 될 것이고, 그 밖에 해당 애플리케이션이 의존하는 데이터베이스나 캐시 등도 서비스가 될 수 있습니다.
쉽게 말하면 services 는 컨테이너 리스트가 들어갑니다. 여러개의 컨테이너를 사용해서 어플을 만들 수 있는데, 사용되는 컨테이너들을 적어준다고 생각하면 됩니다.
따라서 위의 예시에서 저희가 만들려는 컨테이너 mongodb 와 mongo-express 이 둘이 의존성을 가지고 있어 함께 적어줬습니다.
image
image 는 보통 서비스 영역에 컨테이너를 적어주고 나서 적어줍니다. 이것은 컨테이너가 어떤 이미지를 이용해서 run 이 되는지를 의미합니다. 물론 이미지 옆에 버전을 적어줘서 버전을 지정해줄 수도 있습니다. (ex: mongo:1.0)
ports
ports : port host-port:container-port여기에서는 앞으로 열 포트를 지정해줄 수 있습니다.
앞으로 열 포트라는 말이 무슨말이냐면, 컨테이너가 빌드 된 이후에 컨터이너에서 사용할 포트를 지정해준다는 의미로 이전에 port번호를 run할 때 포워딩 해주는 명령을 이렇게 사용할 수 있습니다.
environment
환경변수를 직접 도커컴포즈에 지정해주는 역활입니다.
이전 커맨드창에서는 -e 옵션을 줘서 지정해줬으나 이제는 -를 이용해서 넣어줍니다.
build
build 항목은 해당 서비스의 이미지를 빌드하기 위한 Dockerfile이 위치하는 경로를 지정하기 위해 사용됩니다. 디렉토리와 동일한 위치에 Dockerfile 을 사용해서 서비스 이미지를 빌드하려면, build: . 로 적어줍니다. 만약 Dockerfile이 아닌 다른 이름의 파일로 빌드를 하고 싶거나, 빌드 인자를 넘겨야 하는 경우에는 다음과 같이 하위 항목을 사용해서 좀 더 구체적으로 설정을 해줄 수 있습니다.
services:
web:
build:
context: ./app
dockerfile: Dockerfile-dev
args:
env: "development"
volumes
volumes 항목은 볼륨 설정을 위해 쓰입니다. 마운트(mount)가 필요한 호스트의 경로와 컨테이너의 경로를 명시해주면 됩니다.
이렇게 해주는 이유는 컨테이너는 이전에 수행하던 데이터들을 저장하지 못하기 때문입니다. 컨테이너는 이미지를 이용해서 만들어지기 때문에 데이터 영속성이 없습니다.
아직 볼륨에 대해서 다루지 않았는데 volume을 마운트 한다는 것은 간단하게 말하면, 컨테이너의 저장하는 데이터들을 저장하기 위해서 로컬 환경에 데이터를 저장할 곳을 지정해준다 라고 생각하시면 됩니다.
depends_on
- depends_on 항목은 서비스 간 의존 관계를 지정하기 위해서 사용됩니다. 예를 들어, 웹 애플리케이션이 올라오기 전에 데이터베이스가 먼저 올라와야 한다면 다음과 같이 설정합니다.
services: web: depends_on: - db
command
- command 항목은 해당 서비스가 올라올 때 Dockerfile의 CMD 명령문을 무시하고 실행할 명령어를 설정하기 위해서 사용됩니다.
restart
restart컨테이너 종료 시 플랫폼이 적용할 정책을 정의합니다.
- no :기본 재시작 정책입니다.어떠한 경우에도 컨테이너를 재시작하지 않습니다.
- always :정책은 컨테이너가 제거될 때까지 항상 컨테이너를 재시작합니다.
- on-failure :종료 코드가 오류를 나타내는 경우 정책이 컨테이너를 다시 시작합니다.
- unless-stopped :정책은 종료 코드에 관계없이 컨테이너를 다시 시작하지만 서비스가 중지되거나 제거되면 다시 시작하지 않습니다.
만약 여기 없는 키워드가 나온다면
이곳에 들어가서 레퍼런스를 참고하시길 바랍니다.
https://docs.docker.com/compose/compose-file/build/#context-required
또는 파일 참조에 대해서 링크도 확인해 보시면 좋을 것 같습니다.
https://docs.docker.com/compose/use-secrets/
context : Dockerfile이 포함된 디렉토리의 경로 또는 git 리포지토리의 URL을 정의합니다.
docker compose환경변수 설정
비밀번호 설정
환경변수를 사용해서 비밀번호와 같은 민감한 정보를 컨테이너에게 전달하지 말라고 권고하는 부분을 볼 수가 있습니다. 대신에 Secret을 사용하는 방법을 보여줍니다.
도커에서는 다음과 같은 방법을 권장하지만 위와 같은 방법을 사용하면 평가에 많은 어려움이 있습니다. 그래서 inception 과제에서는 평가를 받아야 하므로 이렇게 하지 않고 .env 파일을 이용하는 방법으로 진행합니다.
.env 파일
환경 변수로 이용하려는 값을 .env에 명시하여 작성하게 되면, Docker Compose는 서비스로 유지하려는 Container를 생성할 때 파일의 환경변수들을 읽어서 환경에 적용해줍니다.
환경변수를 따로 설정하는 수고를 하지 않고 .env 파일만 관리하고, 변수 설정 값을 바꿀 필요가 있는 경우에는 .env 만 수정하면 됩니다.
위의 공식문서를 보면 환경변수를 설정하는 방법에 대해서 몇가지를 소개합니다.
.env파일은 저장해야 하는 여러 환경 변수가 있는 경우에 유용합니다.
예를 들어 docker-compose파일에서 환경변수를 사용하고 싶을 때 다음과 같이 사용할 수 있습니다.
사용 예시
- $ cat .env
TAG=v1.5
- $ cat docker-compose.yml
services: web: image: "webapp:${TAG}"
이렇게 docker-compose.yml 에서 환경변수를 사용하려면 프로젝트 루트에 .env 파일을 두고 그 안에 원하는 환경변수를 적어두면 실행될 때 환경변수를 사용할 수 있습니다.
- docker compose config
services: web: image: 'webapp:v1.5'
저렇게 config명령을 사용해서 확인해보면 환경변수 설정이 잘 적용된 모습을 볼 수 있습니다.
환경변수의 우선순위
각 환경변수를 설정할 수 있는 위치는 많습니다. 따라서 우선순위를 외울 필요는 없지만 정리해두겠습니다.
- CLI에서 사용 설정 (예 :docker compose run -e )
- 쉘 에서 대체
- Compose 파일에서 속성 environment 사용하여 설정
- CLI에서 -env-file인수 사용
- Compose 파일에서 env_file속성 사용
- 프로젝트 디렉터리의 기반에 있는 .env파일을 사용하여 설정
- 도커 파일에 ENV또는 ARG 속성이 있는 경우 (단, Docker Compose 항목이 environment, env_file or run --env 가 없는 경우에만 사용이 됩니다.)
그 외의 환경변수 설정 방법을 알고 싶으시면 공식문서를 참고하시길 바랍니다.
https://docs.docker.com/compose/use-secrets/
따라서 .env로 설정하는 환경변수는 따로 compose 파일에서 설정이 되어있다면 덮어써진다 정도를 알고 가면 될 것 같습니다.
소소한 궁금증 :docker compose 와 docker-compose 간의 차이점
시스템에 이전 버전의 Docker가 설치되어 있는 경우 docker-composeDocker Compose 명령을 실행하는 데 사용할 수 있습니다. 그러나 최신 버전의 Docker가 있는 경우 docker compose. 두 명령 모두 동일한 작업을 수행하고 동일한 Compose 파일로 작업합니다.
- docker compose에 대해서 공식문서를 보고 공부하고 싶다면 아래 링크를 들어가서 쭉 보기를 권장드립니다.
https://docs.docker.com/compose/environment-variables/
https://docs.docker.com/compose/compose-file/
https://meetup.nhncloud.com/posts/277
'42Seoul > Inception' 카테고리의 다른 글
docker compose를 사용한 네트워크 [42 inception 과제 개념 8] (0) | 2023.06.24 |
---|---|
docker compose 명령어 [42 inception 과제 개념 7] (0) | 2023.06.24 |
도커 네트워크란 [42 inception 과제 개념 5] (0) | 2023.06.24 |
Docker 명령어, 포트번호, 컨테이너 디버깅 [42 inception 과제 개념 4] (0) | 2023.06.24 |
Docker, Docker Engine ( Client, Daemon) [42 inception 과제 개념 3] (0) | 2023.06.24 |