[IT-방법] 컴포즈 파일 버전 설정 예제 가이드 – docker-compose.yml 버전 지정 및 옵션 완벽 정리

컴포즈 파일 버전 지정를 설명하는 docker-compose.yml 예제 모음 대표 이미지

컴포즈 파일 버전 설정 때문에 막히는 순간들

도커를 사용하다 보면 갑자기 터미널에 붉은 글씨가 뜨며 실행이 멈추는 경험을 자주 해요. “version is obsolete”라거나 “unsupported config version” 같은 메시지가 출력될 때면 당황스럽기 마련이죠. 분명 예제 코드를 그대로 복사했는데 왜 내 환경에서는 작동하지 않는 걸까요?

이런 문제는 대부분 컴포즈 파일 버전 설정 예제를 찾는 과정에서 발생하는 버전 불일치 때문이에요. 도커 엔진의 버전과 작성한 YAML 파일의 버전 규격이 맞지 않으면 컨테이너는 아예 시작조차 할 수 없어요. 특히 최근에는 도커 컴포즈 V2로 넘어오면서 버전 지정 방식에 큰 변화가 생겼기 때문에 예전 글을 보고 따라 하다가는 실수하기 쉽죠.

단순히 숫자 하나를 적는 것이라고 생각할 수 있지만, 이 숫자에 따라 우리가 사용할 수 있는 네트워크 옵션, 볼륨 설정, 그리고 서비스 배포 방식이 완전히 달라져요. 버전 설정을 잘못하면 운영 중인 서버의 컨테이너가 예기치 않게 종료되거나, 보안 설정이 무시되는 심각한 상황이 벌어질 수도 있어요.

오늘 이 글을 읽고 나면 더 이상 버전 오류 때문에 시간을 허비하지 않게 될 거예요. 실무에서 바로 써먹을 수 있는 다양한 설정 예제와 함께, 현재 내 환경에 딱 맞는 최적의 버전을 선택하는 기준을 명확히 알려드릴게요.

이 글에서 함께 살펴볼 내용들

  • 컴포즈 파일 구조와 버전 필드의 역할 이해하기
  • 버전별 특징 비교와 상황에 맞는 선택 기준
  • 실무에서 바로 복사해 쓰는 단계별 YAML 예제
  • 자주 발생하는 버전 오류와 해결 방법
  • 설정 파일의 무결성을 검증하는 전문적인 방법

설정 전 반드시 알아야 할 기본 지식

본격적으로 예제를 살펴보기 전에, 우리가 다루는 YAML 형식이 무엇인지, 그리고 도커 컴포즈에서 버전이 갖는 의미가 무엇인지 정확히 짚고 넘어가야 해요. YAML은 들여쓰기 하나만 틀려도 전체 파일이 망가지는 아주 예민한 언어예요. 그래서 컴포즈 파일을 작성할 때는 항상 눈을 크게 뜨고 구조를 확인해야 하죠.

도커 컴포즈 파일 최상단에 위치하는 version 필드는 이 파일이 어떤 문법 체계를 따르는지를 정의해요. 예를 들어 버전 2를 사용하면 특정 네트워크 기능이 제한될 수 있고, 버전 3을 사용하면 스웜(Swarm) 모드에서의 배포 기능이 강화되는 식이죠. 최근에는 도커 컴포즈 사양(Compose Specification)이 통합되면서 버전 필드를 아예 생략해도 되는 추세지만, 여전히 기존 프로젝트를 유지보수하려면 각 버전의 차이를 아는 것이 매우 중요해요.

💡 알아두기
도커 컴포즈 V2(최신)를 사용 중이라면 `version: ‘3.8’` 같은 명시적인 버전 선언 없이도 파일이 작동할 수 있어요. 하지만 협업과 안정성을 위해서는 명시적으로 적어주는 습관을 들이는 것이 좋아요.

어떤 버전을 선택해야 할지 고민된다면 아래 비교 표를 참고해 보세요. 자신의 프로젝트가 단순한 로컬 테스트용인지, 아니면 대규모 클러스터 운영용인지에 따라 결정이 달라져야 해요.

구분 버전 2.x 계열 버전 3.x 계열 Compose 사양 (최신)
주요 목적 단일 호스트 컨테이너 관리 도커 스웜(Swarm) 배포 최적화 모든 환경 통합 관리
네트워크 기능 매우 상세한 설정 가능 스웜 모드 중심의 추상화 유연한 확장성 제공
리소스 제한 직접적인 CPU/메모리 지정 deploy 키를 통한 선언적 제한 환경에 따라 자동 최적화
추천 대상 레거시 환경 유지보수 스웜 모드 사용자 신규 프로젝트 및 최신 환경

결론적으로, 새로운 프로젝트를 시작한다면 최신 Compose 사양을 따르거나 버전 3.8 이상을 권장해요. 하지만 회사 내부 시스템이 구형 도커 엔진을 사용하고 있다면, 억지로 최신 문법을 쓰기보다 현재 엔진이 지원하는 버전을 먼저 확인하는 것이 가장 현명한 방법이에요.

실무에서 바로 쓰는 컴포즈 파일 설정 단계별 예제

이제 이론을 넘어 실제 코드로 들어가 볼게요. 컴포즈 파일 버전 설정 예제는 상황에 따라 그 형태가 매우 다양해요. 가장 기초적인 형태부터 복잡한 네트워크 설정까지 단계별로 차근차근 살펴볼까요?

STEP 1. 가장 기본적인 최소 구성 예제

처음 프로젝트를 세팅하거나 간단한 데이터베이스 하나만 띄울 때는 복잡한 옵션이 필요 없어요. 이때는 가장 안정적인 3.8 버전을 기준으로 작성하는 것이 좋아요. 아래 예제는 웹 서버와 데이터베이스를 연결하는 아주 기본적인 구조를 보여줘요.

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: example_password

이 구조에서 version: ‘3.8’은 우리가 사용할 문법이 3.8 버전임을 선언하는 거예요. 만약 이 줄을 빼먹거나 버전을 너무 낮게 적으면, `ports`나 `environment` 같은 속성이 제대로 인식되지 않을 수 있으니 주의해야 해요.

STEP 2. 네트워크와 볼륨을 활용한 확장 예제

실무에서는 컨테이너끼리 서로 격리된 네트워크를 사용하거나, 데이터가 사라지지 않도록 볼륨을 연결하는 작업이 필수적이에요. 버전 3 이상의 기능을 활용하면 네트워크를 직접 정의해서 보안을 강화할 수 있어요.

version: '3.8'

services:
  app:
    build: .
    networks:
      - backend_net
    volumes:
      - app_data:/var/www/html
    depends_on:
      - db

  db:
    image: mysql:8.0
    networks:
      - backend_net
    volumes:
      - db_data:/var/lib/mysql

networks:
  backend_net:
    driver: bridge

volumes:
  app_data:
  db_data

위 예제에서는 networksvolumes라는 최상위 항목을 사용했어요. 이는 단순히 컨테이너 안에서만 작동하는 게 아니라, 전체 시스템의 인프라 구조를 설계하는 단계예요. `depends_on`을 사용하면 DB가 먼저 실행된 후 앱이 실행되도록 순서를 제어할 수 있어 훨씬 안정적인 운영이 가능해지죠.

STEP 3. 리소스 제한 및 배포 옵션 설정하기

운영 서버에 컨테이너를 올릴 때 가장 무서운 것은 한 컨테이너가 메모리를 다 잡아먹어서 서버 전체가 뻗어버리는 상황이에요. 이를 방지하기 위해 버전 3.x에서 도입된 deploy 옵션을 반드시 익혀둬야 해요.

version: '3.8'

services:
  worker:
    image: my-worker:latest
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 128M
      replicas: 3

여기서 limits는 이 컨테이너가 최대로 사용할 수 있는 자원의 한계선이고, reservations는 최소한으로 보장받아야 하는 자원량이에요. 또한 `replicas: 3`을 설정하면 컨테이너를 3개로 복제해서 실행하므로, 트래픽이 몰려도 대응할 수 있는 확장성을 갖추게 돼요. 이 기능은 주로 도커 스웜 환경에서 강력한 힘을 발휘하지만, 최신 컴포즈 엔진에서는 로컬에서도 어느 정도 동작을 지원해요.

STEP 4. 실무형 통합 시나리오: 풀스택 웹 서비스

마지막으로 앞선 개념들을 모두 합친 통합 시나리오를 볼게요. 실제 개발 환경에서 흔히 볼 수 있는 3-Tier 아키텍처(Web-App-DB) 구조예요. 이 예제를 보면 전체적인 흐름을 잡는 데 큰 도움이 될 거예요.

version: '3.8'

services:
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - public_net
    depends_on:
      - api_server

  api_server:
    build: ./api
    environment:
      DB_HOST: database
    networks:
      - public_net
      - private_net
    depends_on:
      - database

  database:
    image: mariadb:10.6
    volumes:
      - db_storage:/var/lib/mysql
    networks:
      - private_net

networks:
  public_net:
    driver: bridge
  private_net:
    internal: true

volumes:
  db_storage:

이 구성의 핵심은 네트워크 분리에 있어요. `frontend`는 외부와 통신하는 `public_net`에 있고, `database`는 외부에서 접근이 불가능한 `private_net`에만 존재해요. `api_server`만이 두 네트워크를 모두 연결하는 브리지 역할을 수행하죠. 이렇게 설계하면 외부 공격자가 데이터베이스에 직접 침투하는 것을 원천적으로 차단할 수 있어요. 보안을 고려한 실무형 설계의 정석이라고 할 수 있죠.

💡 알아두기
`internal: true` 옵션은 해당 네트워크가 외부 인터넷과 연결되지 않도록 차단해요. 민감한 데이터를 다루는 DB 서버를 운영할 때는 반드시 고려해야 할 옵션이에요.

자주 하는 실수와 해결법

설정 파일을 작성하다 보면 누구나 실수를 해요. 특히 YAML은 눈에 보이지 않는 규칙들이 많아서 더욱 그렇죠. 실무에서 가장 자주 발생하는 문제들을 정리했으니, 비슷한 증상을 겪고 있다면 바로 확인해 보세요.

  • 실수: YAML 파일의 들여쓰기를 탭(Tab) 키로 작성함
    왜 발생하는가: YAML 표준은 탭 문자를 허용하지 않고 오직 스페이스(Space)만 허용해요.
    ✅ 해결법: 에디터(VS Code 등) 설정에서 ‘Tab을 Space로 변환’ 기능을 켜고 반드시 스페이스로만 들여쓰기를 하세요.
  • 실수: `version` 필드에 지원하지 않는 버전을 기입함
    왜 발생하는가: 설치된 도커 엔진 버전보다 높은 버전을 명시하면 해석 단계에서 오류가 발생해요.
    ✅ 해결법: `docker version` 명령어로 엔진 버전을 확인한 후, 그에 맞는 버전을 지정하세요.
  • 실수: `ports` 설정 시 숫자를 따옴표 없이 작성함
    왜 발생하는가: `80:80` 같은 값은 YAML에서 숫자로 오인될 수 있어 파싱 오류를 일으켜요.
    ✅ 해결법: 항상 "80:80"처럼 따옴표로 감싸서 문자열임을 명시하세요.
  • 실수: `depends_on`을 사용했지만 서비스가 준비되지 않은 채 접속됨
    왜 발생하는가: `depends_on`은 컨테이너의 ‘실행’ 순서만 보장할 뿐, 내부 앱의 ‘완전한 준비’를 보장하지 않아요.
    ✅ 해결법: 헬스체크(Healthcheck) 기능을 함께 사용하여 서비스가 준비되었는지 확인하는 로직을 추가하세요.
  • 실수: 볼륨 경로를 상대 경로로 잘못 지정함
    왜 발생하는가: 실행하는 위치에 따라 상대 경로의 기준이 달라져 파일이 안 보일 수 있어요.
    ✅ 해결법: 가급적 절대 경로를 사용하거나, 프로젝트 루트 기준의 경로를 명확히 관리하세요.

자주 묻는 질문

Q. 최신 도커 컴포즈를 쓰는데 왜 version 필드를 꼭 써야 하나요?

최신 사양에서는 생략해도 무방하지만, 협업하는 동료의 환경이 다를 수 있어요. 명시적으로 버전을 적어두면 어떤 환경에서도 동일한 문법으로 해석되도록 보장하는 안전장치가 됩니다.

Q. version ‘3.8’과 ‘3.0’의 가장 큰 차이가 무엇인가요?

주로 지원하는 네트워크 기능과 스웜 모드에서의 고급 옵션 유무예요. 3.8은 최신 엔진에서 지원하는 대부분의 기능을 포함하고 있어 특별한 이유가 없다면 3.8을 쓰는 것이 유리해요.

Q. 작성한 컴포즈 파일이 문법적으로 맞는지 어떻게 미리 알 수 있나요?

터미널에서 docker compose config 명령어를 실행해 보세요. 문법 오류가 있다면 즉시 알려주고, 문제 없다면 해석된 전체 설정 내용을 보여줍니다.

Q. YAML 파일에서 들여쓰기가 맞는데도 에러가 나요.

눈에 보이지 않는 특수문자나 잘못된 공백이 포함되었을 가능성이 높아요. 파일을 새로 만들어서 직접 타이핑하거나, YAML Validator 사이트를 이용해 검증해 보는 것을 추천해요.

Q. 컨테이너가 자꾸 재시작되는데 버전 문제일 수도 있나요?

버전 문제라면 아예 실행이 안 되는 경우가 많아요. 자꾸 재시작된다면 설정 파일의 문법보다는 컨테이너 내부의 실행 명령어나 환경 변수 값이 잘못되었을 가능성이 훨씬 커요.

성공적인 컨테이너 운영을 위한 마무리

컴포즈 파일 버전 설정은 단순한 숫자 기입을 넘어, 우리 서비스의 인프라 구조를 정의하는 아주 중요한 첫걸음이에요. 올바른 버전을 선택하고 정교한 YAML 파일을 작성하는 것만으로도 운영 중 발생할 수 있는 수많은 장애를 미리 예방할 수 있답니다.

✅ 핵심 요약

  • 신규 프로젝트는 가급적 버전 3.8 이상 혹은 최신 사양을 사용하세요.
  • YAML 작성 시 반드시 스페이스(Space)를 사용하고 들여쓰기를 엄격히 지키세요.
  • 포트 번호와 같은 설정값은 항상 따옴표(” “)로 감싸는 습관을 들이세요.
  • 배포 전에는 반드시 docker compose config로 검증하세요.
  • 보안을 위해 DB 같은 민감한 서비스는 내부 네트워크(internal)를 활용하세요.
  • 리소스 제한(limits)을 설정하여 서버 전체의 안정성을 확보하세요.

오늘 배운 내용을 바탕으로 지금 바로 여러분의 docker-compose.yml 파일을 점검해 보는 건 어떨까요? 작은 설정 하나가 여러분의 서버를 훨씬 더 단단하고 안전하게 만들어줄 거예요.

🚀 다음 단계로 나아가기
설정 파일 작성이 익숙해졌다면, 이제 컨테이너 간의 통신을 더 깊게 다루는 법을 배워보세요. 준비된 예제 파일을 내려받아 여러분의 프로젝트 구조에 맞게 값만 바꿔 사용하며 실습해 보시길 권장해요!

관련해서 더 깊이 있는 내용이 궁금하다면 도커 컴포즈 기본 개념 완벽 정리 — 개념부터 실무 활용까지 한눈에 보는 가이드를 함께 읽어보세요. 더 효율적인 컨테이너 운영을 위한 여정에 큰 도움이 될 거예요.

댓글 남기기