[IT-정보] docker compose yml 정리 완벽 가이드 – 핵심 문법부터 실무 설정법까지

docker-compose.yml 기본 문법를 설명하는 완벽 정리 대표 이미지

복잡한 컨테이너 명령어를 한 번에 해결하는 방법

터미널 창에 길게 늘어진 docker run 명령어를 보고 한숨을 내쉰 적이 있으신가요? 컨테이너 하나를 띄울 때도 네트워크를 지정하고, 볼륨을 연결하고, 환경 변수를 하나하나 입력하다 보면 어느새 명령어가 끝도 없이 길어져 버려요. 만약 데이터베이스와 웹 서버, 그리고 캐시 서버까지 함께 띄워야 한다면 상황은 더 심각해져요. 각 컨테이너가 서로 통신할 수 있도록 네트워크를 설정하는 과정에서 실수가 생기면, 서비스는 제대로 작동하지 않고 에러 메시지만 가득하게 되죠.

이런 번거로움을 해결하기 위해 등장한 것이 바로 docker-compose.yml 파일이에요. 이 파일 하나만 잘 작성해 두면, 복잡한 설정들을 마치 하나의 설계도처럼 관리할 수 있어요. 명령어를 수십 번 입력할 필요 없이, 단 한 줄의 명령어로 전체 서비스를 실행하고 정지할 수 있죠. 서버 운영의 효율성이 비약적으로 상승하는 순간이에요.

지금 이 글을 읽고 계신 분들은 아마 도커를 막 도입했거나, 여러 개의 컨테이너를 유기적으로 연결하는 과정에서 어려움을 겪고 계실 거예요. 단순히 명령어를 외우는 것이 아니라, 설정 파일의 구조를 이해해야 실무에서 마주하는 예상치 못한 오류를 스스로 해결할 수 있어요. 오늘 이 가이드를 끝까지 읽고 나면, 여러분은 더 이상 터미널과 씨름하지 않고 깔끔하게 설계된 인프라를 운영할 수 있게 될 거예요.

이 글에서는 다음과 같은 내용을 구체적으로 다룰 예정이에요.

  • 도커 컴포즈를 사용하기 위해 반드시 알아야 할 핵심 개념과 용어
  • docker-compose.yml 파일의 내부 동작 방식과 데이터 처리 흐름
  • 실무에서 바로 복사해서 쓸 수 있는 단계별 설정 예시와 옵션 해설
  • 설정 과정에서 흔히 발생하는 실수와 이를 해결하는 구체적인 방법

설계도를 그리기 전 알아야 할 핵심 개념

본격적으로 파일을 작성하기 전에, 우리가 다루는 용어들이 무엇을 의미하는지 정확히 짚고 넘어가야 해요. 도커 컴포즈는 단순히 컨테이너를 실행하는 도구가 아니라, 여러 개의 컨테이너를 하나의 프로젝트로 묶어서 관리하는 오케스트레이션 도구이기 때문이에요. 개념이 흔들리면 나중에 네트워크 설정이나 볼륨 연결에서 큰 혼란을 겪게 돼요.

반드시 이해해야 하는 4가지 핵심 용어

먼저 서비스(Service)라는 개념이 가장 중요해요. 서비스는 컨테이너를 어떻게 실행할 것인지에 대한 ‘설계도’라고 생각하면 쉬워요. 예를 들어 ‘web-server’라는 서비스는 Nginx 이미지를 사용하고, 80번 포트를 연다는 내용을 담고 있죠. 이 서비스를 바탕으로 실제 돌아가는 실체가 바로 컨테이너(Container)예요.

다음으로 네트워크(Network)는 서비스들 사이의 통로 역할을 해요. 도커 컴포즈는 기본적으로 파일을 실행할 때 전용 네트워크를 생성해서, 서비스들이 서로의 이름만으로도 통신할 수 있게 도와줘요. 마지막으로 볼륨(Volume)은 컨테이너가 사라져도 데이터가 유지되도록 돕는 저장 공간이에요. 데이터베이스의 데이터가 컨테이너 재시작과 함께 사라진다면 큰 문제가 생기겠죠? 그래서 볼륨 설정은 선택이 아닌 필수예요.

실행 방식에 따른 비교: docker run vs docker compose

기존의 개별 실행 방식과 컴포즈 방식이 어떻게 다른지 비교해 보면 왜 이 도구가 필요한지 명확히 알 수 있어요.

구분 항목 docker run (개별 실행) docker compose (파일 기반)
설정 관리 매번 긴 명령어를 입력해야 함 YAML 파일에 저장하여 재사용
다중 컨테이너 연결 수동으로 네트워크를 생성/연결 파일 내 정의로 자동 연결
환경 변수 관리 -e 옵션으로 일일이 지정 environment 항목으로 일괄 관리
인프라 재현성 낮음 (기억에 의존해야 함) 매우 높음 (파일만 있으면 동일 환경 구축)
💡 알아두기
YAML 파일 작성 시 가장 주의해야 할 점은 들여쓰기(Indentation)예요. 탭(Tab) 대신 반드시 공백(Space)을 사용해야 하며, 들여쓰기 깊이가 하나라도 틀리면 문법 오류가 발생하여 실행되지 않으니 주의하세요.

docker-compose.yml 완벽 구축을 위한 단계별 가이드

이제 실전으로 들어가 볼까요? 단순히 문법을 아는 것을 넘어, 실제로 어떻게 구성해야 안정적인 서비스를 만들 수 있는지 단계별로 살펴볼게요. 전체적인 구조는 큰 틀에서 version, services, networks, volumes라는 네 가지 기둥으로 이루어져 있어요.

STEP 1. 서비스의 뼈대 구성하기

가장 먼저 작성해야 할 부분은 services 항목이에요. 여기서 우리가 실행할 모든 컨테이너를 정의해요. 각 서비스 안에는 어떤 이미지를 사용할지, 어떤 설정을 적용할지가 들어갑니다. 가장 기본이 되는 옵션들을 먼저 이해해 두는 것이 중요해요.

  • image: 사용할 도커 이미지의 이름을 지정해요.
  • build: 이미지를 직접 만들고 싶을 때, Dockerfile이 있는 경로를 지정해요.
  • ports: 호스트 컴퓨터와 컨테이너 사이의 포트 매핑을 설정해요. (예: “8080:80”)
  • environment: 컨테이너 내부에서 사용할 환경 변수를 설정해요. 비밀번호나 API 키 등을 전달할 때 유용해요.
💡 알아두기
포트 설정 시 “80:80″처럼 작성하면, 호스트의 80번 포트로 들어온 요청을 컨테이너의 80번 포트로 전달한다는 의미예요. 만약 호스트의 80번 포트가 이미 사용 중이라면 오류가 발생하니 주의하세요.

STEP 2. 데이터 영속성을 위한 볼륨 설정하기

컨테이너는 일회용품과 같아요. 컨테이너를 삭제하면 그 안에서 생성된 데이터도 모두 날아가 버리죠. 이를 방지하기 위해 volumes 설정을 반드시 해주어야 해요. 볼륨 설정에는 크게 두 가지 방식이 있어요.

첫 번째는 바인드 마운트(Bind Mount)예요. 호스트의 특정 폴더와 컨테이너의 폴더를 직접 연결하는 방식이에요. 코드를 수정하면 컨테이너에 즉시 반영되어야 하는 개발 환경에서 주로 사용해요. 두 번째는 네임드 볼륨(Named Volume)이에요. 도커가 관리하는 별도의 저장 공간을 생성하는 방식으로, 데이터베이스처럼 데이터의 안정성이 중요한 프로덕션 환경에서 권장돼요.

STEP 3. 서비스 간의 통신을 위한 네트워크 설계

여러 서비스가 하나의 애플리케이션으로 작동하려면 서로를 찾아낼 수 있어야 해요. 도커 컴포즈는 파일 내에 networks를 정의하면, 각 서비스가 동일한 네트워크 안에 속하게 만들어 줘요. 이렇게 하면 컨테이너의 IP 주소를 몰라도 서비스의 이름(예: db, redis)만으로 데이터베이스에 접속할 수 있어요. 이것이 바로 도커 컴포즈가 제공하는 강력한 서비스 디스커버리 기능이에요.

STEP 4. 실행 순서 제어하기: depends_on

애플리케이션이 실행될 때, 웹 서버가 데이터베이스보다 먼저 뜨면 어떻게 될까요? 당연히 연결 오류가 발생하겠죠. 이때 사용하는 것이 depends_on 옵션이에요. 이 옵션을 사용하면 특정 서비스가 먼저 실행된 후에 다른 서비스가 시작되도록 순서를 지정할 수 있어요. 다만, 이것은 컨테이너가 ‘실행’되는 순서만 보장할 뿐, 데이터베이스 내부의 프로세스가 완전히 ‘준비’될 때까지 기다려주는 것은 아니라는 점을 기억하세요.

실전 예시: 웹 서버와 데이터베이스 결합 모델

이 모든 개념을 종합하여, Nginx 웹 서버와 PostgreSQL 데이터베이스가 함께 작동하는 실무형 예시를 만들어 볼게요. 이 구조를 그대로 복사해서 여러분의 환경에 맞게 수정해 보세요.

version: '3.8'

services:
  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydatabase
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - backend-network

  web:
    image: nginx:latest
    ports:
      - "80:80"
    depends_on:
      - db
    networks:
      - backend-network

networks:
  backend-network:
    driver: bridge

volumes:
  db_data:

위 설정의 흐름을 함께 살펴볼까요? 먼저 db 서비스가 생성돼요. PostgreSQL 이미지를 사용하며, 환경 변수를 통해 사용자 이름과 비밀번호를 설정했어요. 데이터는 db_data라는 이름의 볼륨에 안전하게 보관되죠. 그 다음 web 서비스가 실행돼요. Nginx 이미지를 사용하며, 호스트의 80번 포트를 열어줍니다. depends_on 덕분에 DB가 먼저 실행된 후 웹 서버가 뜹니다. 마지막으로 두 서비스는 backend-network라는 동일한 네트워크를 공유하므로, 웹 서버의 설정 파일에서 호스트 이름을 db라고 입력하는 것만으로 데이터베이스에 접속할 수 있어요.

⚠️ 주의
환경 변수에 비밀번호와 같은 민감한 정보를 직접 적는 것은 보안상 위험해요. 실제 운영 환경에서는 .env 파일을 별도로 만들어 관리하는 것을 강력하게 추천해요.

자주 하는 실수와 해결법 및 궁금한 점

설정 파일을 작성하다 보면 이론과 실제 사이의 괴리 때문에 당황스러운 순간이 많아요. 많은 개발자가 공통으로 겪는 실수들을 정리했으니, 에러 메시지를 읽기 전에 먼저 체크해 보세요.

실무에서 자주 하는 실수 TOP 5

실수: 들여쓰기에 탭(Tab)을 사용함
왜 발생하는가: YAML 문법은 들여쓰기에 매우 민감해요. 탭과 공백을 혼용하면 문법 오류가 발생해요.
해결법: 에디터(VS Code 등)의 설정을 확인하여 탭을 입력할 때 자동으로 공백 4칸으로 변환되도록 설정하세요.

실수: 포트 충돌 문제
왜 발생하는가: 호스트 컴퓨터에서 이미 80번이나 3306번 포트를 다른 프로그램이 사용 중일 때 발생해요.
해결법: ports 설정의 앞부분(호스트 포트)을 “8081:80″처럼 변경하여 중복을 피하세요.

실수: 볼륨 경로 오타
왜 발생하는가: 호스트의 경로를 바인드 마운트로 설정할 때 상대 경로를 잘못 지정하면 데이터가 저장되지 않아요.
해결법: 가능하면 절대 경로를 사용하거나, 현재 디렉토리를 의미하는 “./”를 명확히 사용하세요.

실수: 환경 변수 적용 실패
왜 발생하는가: .env 파일을 만들었지만 docker-compose가 해당 파일을 읽지 못하는 위치에 있는 경우예요.
해lement: docker-compose.yml 파일과 같은 위치에 .env 파일을 두거나, 실행 시 직접 경로를 지정하세요.

실수: 네트워크 연결 불가
왜 발생하는가: 서비스들이 서로 다른 네트워크에 속해 있어서 이름을 통한 통신이 안 되는 경우예요.
해결법: 모든 서비스가 동일한 networks 항목을 공유하고 있는지 확인하세요.

자주 묻는 질문

Q. docker-compose.yml 파일의 버전(version)은 꼭 써야 하나요?
최신 도커 엔진에서는 버전 명시가 필수는 아니지만, 구버전과의 호환성이나 명확한 문법 규격 지정을 위해 작성하는 것이 관례예요. 3.8 버전을 가장 안정적으로 추천해요.

Q. 설정 파일을 수정했는데 변경 사항이 적용되지 않아요.
단순히 실행 명령만 내리면 기존 컨테이너가 그대로 유지될 수 있어요. docker compose up -d 명령을 다시 실행하면, 도커가 변경 사항을 감지하여 해당 서비스만 재생성해 줍니다.

Q. 컨테이너 내부의 로그를 실시간으로 보고 싶어요.
docker compose logs -f 명령어를 사용하세요. 특정 서비스의 로그만 보고 싶다면 docker compose logs -f [서비스명]을 입력하면 돼요.

Q. 실행 중인 컨테이너를 모두 한꺼번에 끄고 싶어요.
docker compose down 명령어를 사용하세요. 이 명령어는 컨테이너뿐만 아니라 생성된 네트워크까지 깔끔하게 정리해 줍니다. 다만, 볼륨까지 삭제하려면 -v 옵션을 붙여야 해요.

Q. 여러 개의 compose 파일을 동시에 사용할 수 있나요?
네, 가능해요. docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d와 같이 -f 옵션을 사용하여 여러 파일을 겹쳐서 사용할 수 있어요.

효율적인 운영을 위한 마지막 정리

도커 컴포즈는 복잡한 인프라를 코드로 관리할 수 있게 해주는 마법 같은 도구예요. 처음에는 문법이 낯설고 들여쓰기 하나에도 에러가 나서 힘들 수 있지만, 한 번 익숙해지면 이전의 수동 방식으로는 절대 돌아갈 수 없을 만큼 편리해요. 오늘 배운 내용을 바탕으로 여러분의 개발 환경을 더욱 견고하게 만들어 보세요.

✅ 핵심 요약

  • YAML 문법의 핵심은 정확한 들여쓰기와 공백 사용이에요.
  • 서비스, 네트워크, 볼륨의 역할을 구분하여 설계도를 그려야 해요.
  • 데이터 보존을 위해 네임드 볼륨 사용을 습관화하세요.
  • 서비스 간 통신은 서비스 이름을 호스트네임으로 활용하세요.
  • 설정 변경 후에는 docker compose up으로 변경 사항을 적용하세요.
  • 민감한 정보는 반드시 .env 파일로 분리하여 관리하세요.

이제 이론은 충분히 학습하셨어요. 가장 좋은 학습 방법은 직접 해보는 것이에요. 위에 제공해 드린 설정 예시를 그대로 복사해서 여러분의 테스트 서버나 로컬 환경에서 실행해 보세요. 직접 에러를 마주하고 해결하는 과정에서 실력은 가장 빠르게 늘어난답니다.

오늘 할 일은 예시 코드를 복사해 실행해 보는 것이고, 이번 주 할 일은 본인만의 웹 서비스를 위한 compose 파일을 직접 작성해 보는 것이에요. 실행 직전에는 반드시 .env 파일에 비밀번호가 잘 들어갔는지 확인하는 것을 잊지 마세요!

더 깊이 있는 도커 활용법이 궁금하다면, 다음 단계로 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드 글을 읽어보시는 것을 추천드려요.

댓글 남기기