42서울/Inception

docker-compose 란 무엇인가? [42 inception 과제 개념 6]

뜨거운 개발자 2023. 6. 24. 17:57

도커 컴포즈가 등장하게 된 배경

👨🏻‍💻
도커파일을 관리하는게 도거 컴포즈인데, 설명의 편의를 위해 도커파일보다, 도커 컴포즈를 먼저 설명하도록 하겠습니다.

지금까지 위의 게시물들을 순서대로 보셨다면 컨테이너가 무엇인지 알고 계실겁니다.

이미지를 실행중인 환경이 컨테이너이고 하나의 이미지를 이용해서 여러개의 컨테이너를 만들어 낼 수 있었습니다.

이제 많은 이미지가 등장하고 여러개의 컨테이너를 만들어야 하는 서비스가 등장함에 따라서, 한꺼번에 컨테이너를 관리해주는 것의 필요성을 느끼게 되었습니다. 또 추가적으로 늘 네트워크 설정을 해서 컨테이너간 통신을 하는 것에 불편함을 느낀 사람들은 그것들을 한번에 해주는 툴을 만들기 시작합니다.

저희가 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도커 엔진에 포함된 기능이 아니다 보니, 도커 엔진만 설치한 경우에는 설치가 되어있지 않은 경우가 있습니다.

아래 공식 사이트를 참고해서 설치하세요!

Overview
Learn how to install Docker Compose. Compose is available natively on Docker Desktop, as a Docker Engine plugin, and as a standalone tool.
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-dbdocker-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 ComposeDocker Swarm간 호환이 가능합니다.

도커 컴포즈 사용의 장점

  • 메인 애플리케이션 뿐만 아니라 정상적으로 구동되기 위해서 필요한 기반 시스템까지 Docker Compose로 설정합니다. 이것은 사용자가 로컬에서 별도의 셋업 없이 Docker Compose 명령 한번으로 어플리케이션을 올릴 수 있게 되는 장점이 있습니다.
  • 관리가 용의합니다. 수정이 쉽고 포트를 바꾸는 등 설정을 바꾸는 것이 용이합니다.
  • 네트워크 설정이 간단해집니다. docker compose를 사용하면 도커의 이름만을 사용해서 서로 통신할 수 있는 공용 네트워크를 제공합니다(creating common Network). 그래서 특별한 경우가 아니라면 따로 새로운 네트워크를 생성해 줄 필요성이 없습니다.
  • 이것이 명령에서는 네트워크 설정을 해줬지만, docker compose파일에서는 따로 해주지 않은 이유입니다.

서비스 영역과 서비스 영역의 주요 필드

services

services 는 독립된 컨테이너에서 돌아가는 애플리케이션의 구성 요소입니다. 가장 먼저 프로젝트에서 개발하고 있는 애플리케이션 자체가 서비스가 될 것이고, 그 밖에 해당 애플리케이션이 의존하는 데이터베이스나 캐시 등도 서비스가 될 수 있습니다.

쉽게 말하면 services 는 컨테이너 리스트가 들어갑니다. 여러개의 컨테이너를 사용해서 어플을 만들 수 있는데, 사용되는 컨테이너들을 적어준다고 생각하면 됩니다.

따라서 위의 예시에서 저희가 만들려는 컨테이너 mongodbmongo-express 이 둘이 의존성을 가지고 있어 함께 적어줬습니다.

🚨
여기서 나오는 각각의 요소가 전부 이해가 가지는 않을 것입니다. 우선 이해하는 부분까지는 읽어보고 뒤에 나오는 volumes게시물과, Dockerfile에 대해서 전부 이해하고 이후 docker compose를 설정 할 때 다시 돌아와 참고하시길 바랍니다.

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 :정책은 종료 코드에 관계없이 컨테이너를 다시 시작하지만 서비스가 중지되거나 제거되면 다시 시작하지 않습니다.

만약 여기 없는 키워드가 나온다면

The Compose file
https://docs.docker.com/compose/compose-file/03-compose-file/

이곳에 들어가서 레퍼런스를 참고하시길 바랍니다.

또는 파일 참조에 대해서 링크도 확인해 보시면 좋을 것 같습니다.

Compose file build reference
https://docs.docker.com/compose/compose-file/build/#context-required

context : Dockerfile이 포함된 디렉토리의 경로 또는 git 리포지토리의 URL을 정의합니다.

docker compose환경변수 설정

비밀번호 설정

Using secrets in Compose
How to use secrets in Compose and their benefits
https://docs.docker.com/compose/use-secrets/

환경변수를 사용해서 비밀번호와 같은 민감한 정보를 컨테이너에게 전달하지 말라고 권고하는 부분을 볼 수가 있습니다. 대신에 Secret을 사용하는 방법을 보여줍니다.

도커에서는 다음과 같은 방법을 권장하지만 위와 같은 방법을 사용하면 평가에 많은 어려움이 있습니다. 그래서 inception 과제에서는 평가를 받아야 하므로 이렇게 하지 않고 .env 파일을 이용하는 방법으로 진행합니다.

.env 파일

환경 변수로 이용하려는 값을 .env에 명시하여 작성하게 되면, Docker Compose는 서비스로 유지하려는 Container를 생성할 때 파일의 환경변수들을 읽어서 환경에 적용해줍니다.

환경변수를 따로 설정하는 수고를 하지 않고 .env 파일만 관리하고, 변수 설정 값을 바꿀 필요가 있는 경우에는 .env 만 수정하면 됩니다.

위의 공식문서를 보면 환경변수를 설정하는 방법에 대해서 몇가지를 소개합니다.

Overview
Explainer on the ways to set, use and manage environment variables in Compose
https://docs.docker.com/compose/environment-variables/

.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명령을 사용해서 확인해보면 환경변수 설정이 잘 적용된 모습을 볼 수 있습니다.

환경변수의 우선순위

각 환경변수를 설정할 수 있는 위치는 많습니다. 따라서 우선순위를 외울 필요는 없지만 정리해두겠습니다.

  1. CLI에서 사용 설정 (예 :docker compose run -e )
  1.  에서 대체
  1. Compose 파일에서 속성 environment 사용하여 설정
  1. CLI에서 -env-file인수 사용
  1. Compose 파일에서 env_file속성 사용
  1. 프로젝트 디렉터리의 기반에 있는 .env파일을 사용하여 설정
  1. 도커 파일에 ENV또는 ARG 속성이 있는 경우 (단, Docker Compose 항목이 environmentenv_file or run --env 가 없는 경우에만 사용이 됩니다.)

그 외의 환경변수 설정 방법을 알고 싶으시면 공식문서를 참고하시길 바랍니다.

따라서 .env로 설정하는 환경변수는 따로 compose 파일에서 설정이 되어있다면 덮어써진다 정도를 알고 가면 될 것 같습니다.

소소한 궁금증 :docker compose 와 docker-compose 간의 차이점

시스템에 이전 버전의 Docker가 설치되어 있는 경우 docker-composeDocker Compose 명령을 실행하는 데 사용할 수 있습니다. 그러나 최신 버전의 Docker가 있는 경우 docker compose. 두 명령 모두 동일한 작업을 수행하고 동일한 Compose 파일로 작업합니다.


Uploaded by N2T

728x90