Docker

실습을 통해 Docker Compose 알아보기

kym8821 2025. 2. 8. 03:48

Docker Compose 기초 개념

Docker Compose?

도커 컴포즈는 여러개의 컴포넌트들을 정의 및 실행하기 위해서 사용하는 도구이다.

docker compose의 대표적인 기능은 아래와 같다.

  • 단일 yaml 파일에서 전체 컨테이너를 관리
  • 컨테이너의 생명주기를 관리할 수 있는 명령어 제공

Docker Compose 이점

docker compose의 이점은 아래와 같다.

  • 빠른 애플리케이션 개발
    • 컨테이너 구성을 캐싱하므로 변경되지 않은 서비스의 빠른 재시작이 가능함
  • 간소화된 제어
    • 단일 yaml 파일에서 여러개의 컨테이너를 제어 및 관리할 수 있음

 

yaml 기초 개념

yaml?

docker compose의 기초 문법을 알아보기 전에, 우선 yaml의 문법에 대해서 알아야 한다

 

yaml은 xml와 json와 같이 데이터를 주고받을 때 사용하는 규칙이 있는 파일이다.

yaml은 주로 docker-compose, spring boot, 쿠버네티스 등에서 설정 파일로 사용한다.

yaml 기초 문법

yaml은 데이터들을 아래와 같이 키-값 형식으로 나타낸다.

key: value

key와 value 사이에 콜론( : )이 들어가고, 콜론과 value 사이에는 공백이 하나 있어야 한다.

yaml 데이터 타입

yaml은 아래 표와 같이 다양한 타입들을 제공해준다.

타입 명칭 예시
숫자 key: 1
문자열 key: 'string'
논리값 key: true
객체 key: {
    field1: 1
    field2: 'string'
    field3: true
}
리스트 key: [1, 2, 3]

혹은

key:
    - 1
    - 2
    - 3

 

docker-compose 기초 문법

 

이제 docker-compose에 대한 기초 문법에 대해서 알아보자.

docker-compose CLI 명령어

docker-compose는 여러 명령어들을 제공한다.

지금은 기초적이고 자주 사용되는 명령어들만 간단하게 알아보자.

명령어 형식 기능
docker-compose up -d docker compose에 속한 컨테이너들 실행
docker-compose down docker compose에 속한 컨테이너들 중지 후 제거
docker-compose logs docker compose에 속한 컨테이너 모니터링
docker-compose ps docker compose에 속한 컨테이너 현재 상태 조회

이 외에도 다양한 명령어들을 제공해주기에 상황에 맞게 사용하면 될 것이다.

간단한 docker-compose.yaml 문법 알아보기

우선 docker compose 공식문서에서 제공하는 docker-compose.yaml 예시를 살펴보자.

 

실습을 원한다면 아래 사이트를 참고하자.

https://docs.docker.com/compose/gettingstarted/

 

Quickstart

Check out this tutorial on how to use Docker Compose from defining application dependencies to experimenting with commands.

docs.docker.com

 

아래와 같은 yaml 파일을 확인할 수 있다.

version은 이번 블로그를 위해서 직접 추가한 부분이다.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"


정말 간단한 docker-compose.yml 파일이다. 우선 각 키워드들이 갖는 역할들을 알아보자.

키워드 이름 역할
version docker compose의 버전을 명시함
services 하나 이상의 컨테이너를 정의하는 부분
web, redis 각 컨테이너를 정의하기 위한 임의의 별칭 (서비스 이름) 지정
build 빌드할 DockerFile의 경로를 지정
port "{hostPort}:{containerPort}" 꼴로 포트포워딩
image 사용할 이미지 지정 (없으면 pull해옴)

 

이젠 각 부분들을 보다 자세하게 알아보자.

  • version : docker compose의 버전을 명시
    • 원하는 기능을 지원해주는 버전을 지정해야함.
    • 주로 가장 최신버전을 사용함
  • services : 하나 이상의 컨테이너를 정의하는 부분
    • docker compose up -d 명령어 실행시 실행할 컨테이너들을 명시함
    • 각 컨테이너들에게 별칭을 부여하고 각각은 하나의 애플리케이션을 의미함
  • build : Dockerfile의 경로를 지정하는 부분
    • Dockerfile을 빌드하여 이미지를 생성 및 사용함
  • images : 사용할 이미지를 직접 지정해주는 부분
    • build와 달리 기존에 존재하는 이미지와 이미지 태그를 지정해줌
    • 만약 해당 이미지가 없다면, docker repository에서 직접 받아옴
  • port : 호스트와 컨테이너 환경 간 포트포워딩을 명시하는 부분
    • "{host}:{container}" 꼴로 포트포워딩을 진행함
    • 포트포워딩을 해주지 않으면, 호스트에서 컨테이너에 접근 불가
    • 포트포워딩을 안해도 컨테이너는 별도의 네트워크 네임스페이스에서 작동하고 있음

 

docker compose 환경변수와 우선순위

environment 키워드

기존 docker-compose 파일을 좀 수정해보자.

아래와 같이 environment 키워드를 사용하면 컨테이너에서 사용하는 환경변수를 지정해줄 수 있다.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
  mysql:
    image: mysql:8.0
    ports:
      - "23306:3306"
    environment:
      - MYSQL_ROOT_HOST: "%"
      - MYSQL_DATABASE: let_me_drum
      - MYSQL_USER: root
      - MYSQL_PASSWORD: 1234
      - MYSQL_ROOT_PASSWORD: 1234
      - TZ: Asia/Seoul
  redis:
    image: "redis:alpine"

environment 키워드를 사용하여 리스트 형식으로 환경변수를 지정했다.

 

지금은 environment에서 지정한 각 환경변수가 어떤 역할을 하는지는 알 필요 없다.

mysql에 접속하기 위한 환경변수를 지정했다고 알면 된다

docker-compose 환경변수 우선순위

docker-compose와 DockerFile에서 동일한 환경변수에 다른 값을 지정했다고 가정해보자.

이 때, docker-compose의 환경변수는 DockerFile보다 더 높은 우선수위를 갖는다.

정확히는 docker-compose.yml에서 설정한 환경변수는 컨테이너가 실행될 때 우선적으로 적용된다.

 

즉, docker-compose는 DockerFile이나 컨테이너 내부에 설정한 환경변수를 덮어쓴다.

따라서 서로 다른 실행 환경에서 자신에게 맞는 설정 정보를 지정하는데 도움이 된다.

 

docker-compose 볼륨 설정하기

볼륨이란?

볼륨은 쉽게 말해 컨테이너 내부와 외부 사이에 링크를 생성해주는 것이다.

컨테이너 삭제 시 보호해야하는 데이터를 볼륨을 통해서 보존시킬 수 있다.

 

볼륨에 대한 보다 자세한 내용은 아래 게시글에서 확인할 수 있다.

https://kym8821.tistory.com/entry/%EC%8B%A4%EC%8A%B5%EC%9D%84-%ED%86%B5%ED%95%B4-Docker-volume-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

실습을 통해 Docker volume 알아보기

Volume이 필요한 이유원본 이미지 A로부터 컨테이너 ca, cb를 생성했고 ca에 test라는 파일을 생성했다.이러한 상황에서 cb에는 test 파일이 생성되지 않는다. 당연한 이야기이다. 하지만 아래와 같은

kym8821.tistory.com

volume 키워드

이번에는 기존 docker-compose의 mysql 컨테이너에 볼륨을 지정했다.

아래와 같이 리스트 형식의 volume 키워드를 사용하여 볼륨을 지정해줄 수 있다.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
  mysql:
    image: mysql:8.0
    ports:
      - "23306:3306"
    environment:
      - MYSQL_ROOT_HOST: "%"
      - MYSQL_DATABASE: let_me_drum
      - MYSQL_USER: root
      - MYSQL_PASSWORD: 1234
      - MYSQL_ROOT_PASSWORD: 1234
      - TZ: Asia/Seoul
    volumes:
      - ./db/mysql/data:/var/lib/mysql
      - ./db/mysql/init:/docker-entrypoint-initdb.d
  redis:
    image: "redis:alpine"

 

이처럼 volumes 키워드를 사용하면 바인드 마운트 혹은 도커 볼륨을 지정해줄 수 있다.

  • 바인드 마운트 : {호스트}:{컨테이너} 꼴로 호스트와 컨테이너 디렉토리 간 링크 생성
  • 도커 볼륨 : 도커 호스트에서 관리해주는 볼륨.
    • docker volume 계열 명령어로 관리 가능

 

docker-compose에서 네트워크 설정하기

컨테이너 네트워크 네임스페이스

일반적으로 컨테이너는 독립적인 네트워크 네임스페이스를 갖는다.

따라서 컨테이너는 호스트와 별개의 네트워크 공간에서 실행된다.

또한, 같은 네트워크에 속한 컨테이너들은 서로 통신이 가능하다.

 

컨테이너 네트워크는 크게 아래 4가지로 나눌 수 있다.

  • bridge network (기본값)
    • 컨테이너가 호스트와 별개의 네트워크 네임스페이스에서 동작함
    • 호스트에서 컨테이너에 접근하기 위해서는 포트 포워딩이 필요함 
    • docker-compose는 bridge network를 기본값으로 사용한다.
  • host network
    • 컨테이너가 호스트의 네트워크 환경을 직접 사용함
    • 브릿지 네트워크와 달리 포트 포워딩 없이 컨테이너에 접근 가능
  • container network
    • 특정 컨테이너의 네트워크 네임스페이스를 공유함
  • None
    • 완전히 네트워크를 비활성화하여 호스트와 컨테이너를 격리함

디폴트 네트워크

기존 docker-compose를 살펴보자.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
  mysql:
    image: mysql:8.0
    ports:
      - "23306:3306"
    environment:
      - MYSQL_ROOT_HOST: "%"
      - MYSQL_DATABASE: let_me_drum
      - MYSQL_USER: root
      - MYSQL_PASSWORD: 1234
      - MYSQL_ROOT_PASSWORD: 1234
      - TZ: Asia/Seoul
    volumes:
      - ./db/mysql/data:/var/lib/mysql
      - ./db/mysql/init:/docker-entrypoint-initdb.d
  redis:
    image: "redis:alpine"

직접 테스트해보지 않았지만, 위 컨테이너들은 서로 통신할 수 있다.

이러한 이유는 네트워크를 지정하지 않았을 때 생성해주는 디폴트 네트워크 덕분이다.

 

디폴트 네트워크는 "현재 디렉토리 이름" + "_default" 라는 이름을 갖는다.

docker compose는 네트워크 설정이 없다면 모든 컨테이너를 디폴트 네트워크에 연결한다.

따라서 위 컨테이너들이 같은 네트워크 네임스페이스에 속해서 서로 통신할 수 있는 것이다.

networks 키워드를 사용한 사용자 지정 네트워크

당연히 사용자가 직접 네트워크를 지정해줄 수도 있다.

아래와 같이 networks 키워드를 사용하면 컨테이너에서 사용할 네트워크를 지정할 수 있다.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
    networks:
      - webapp-network
      - mysql-network
      - redis-network
  mysql:
    image: mysql:8.0
    ports:
      - "23306:3306"
    environment:
      - MYSQL_ROOT_HOST: "%"
      - MYSQL_DATABASE: let_me_drum
      - MYSQL_USER: root
      - MYSQL_PASSWORD: 1234
      - MYSQL_ROOT_PASSWORD: 1234
      - TZ: Asia/Seoul
    networks:
      - webapp-network
      - mysql-network
    volumes:
      - ./db/mysql/data:/var/lib/mysql
      - ./db/mysql/init:/docker-entrypoint-initdb.d
  redis:
    image: "redis:alpine"
    networks:
      - webapp-network
      - redis-network
networks:
  redis-network: {}
  mysql-network: {}
  webapp-network:
  	driver: bridge

 

이번에는 좀 복잡하다.

 

일단 아래 내용들을 이해하고 있어야 한다.

  • 같은 네트워크 네임스페이스에 속한 컨테이너 간 통신만이 가능하다.
  • docker compose는 네트워크 설정이 없을 때만 bridge network를 생성해준다.

그럼 이제 위 docker-compose.yml을 확인해보자.

  • 맨 아래에 networks를 통해서 세 개의 네트워크 네임스페이스를 생성했다.
    • redis-network, mysql-network : 따로 설정이 없으므로 기본값(브릿지) 방식으로 생성한다.
    • webapp-network는 driver 키워드를 통해 명시적으로 bridge network를 사용하도록 지정했다.
  • services의 각 컨테이너에 networks 키워드를 통해 컨테이너의 네트워크 네임스페이스를 지정했다.
    • 이 때, 같은 네트워크 네임스페이스에 존재하는 컨테이너 간 통신만이 가능하다.
    • 따라서 아래와 같은 통신 상태를 갖는다.
컨테이너 이름 web mysql redis
web 통신 가능 통신 가능 통신 가능
mysql 통신 가능 통신 가능 통신 불가
redis 통신 가능 통신 불가 통신 가능

 

docker compose의 driver 키워드를 통해서 보다 다양한 네트워크 방식을 선택할 수 있다.

자세한 내용은 아래 공식문서에서 확인할 수 있다.

https://docs.docker.com/engine/network/drivers/ 

 

Network drivers

Learn the basics of Docker network drivers

docs.docker.com

 

마무리

 

이번에는 docker-compose의 전반적인 문법에 대해서 알아보았다.

이번에 다룬 내용은 극히 기초이고, 위에서 다룬 내용 외에도 다양한 키워드와 명령어들이 있다.

 

이번에 공부한 내용을 바탕으로 부족한 부분을 채워나가는 것이 좋을 것이다.