도커(Docker)를 활용해 서비스를 배포하다 보면, 하나의 웹 애플리케이션을 구동하기 위해 생각보다 많은 컨테이너가 필요하다는 것을 알게 됩니다. 예를 들어 일반적인 모던 웹 시스템을 구축하려면 웹 서버(Nginx), 백엔드 어플리케이션(Node.js 또는 Spring Boot), 그리고 데이터베이스(MySQL)까지 최소 3개의 컨테이너가 서로 유기적으로 통신하며 동시에 작동해야 합니다.
이 서비스들을 일반적인 docker run 명령어로 일일이 띄우려면 포트 포워딩, 환경 변수, 네트워크 연동 옵션을 매번 수십 줄씩 타이핑해야 하므로 관리가 불가능에 가깝습니다. 이러한 멀티 컨테이너 환경을 단 하나의 설정 파일로 일괄 정의하고 제어할 수 있게 도와주는 도커의 핵심 도구가 바로 도커 컴포즈(Docker Compose)입니다. 본 가이드에서는 도커 컴포즈의 동작 원리부터 설치, 그리고 docker-compose.yml 설정 파일을 올바르게 작성하는 방법까지 상세히 정리합니다.
1. 도커 컴포즈(Docker Compose)의 개념과 도입 목적
도커 컴포즈는 다중 컨테이너 도커 애플리케이션을 정의하고 실행하기 위한 도구입니다. 복잡하게 얽혀 있는 여러 개의 컨테이너 환경을 YAML 파일 구조로 선언해 두고, 명령어 단 한 줄로 전체 서비스를 동시에 켜거나 끌 수 있는 오케스트레이션 기능을 제공합니다.
도커 컴포즈가 해결하는 실무적 문제
일반 도커 명령어로 3개의 컨테이너를 연동하려면 순서가 매우 중요합니다. 데이터베이스가 먼저 켜진 후 백엔드가 켜져야 연결 오류가 나지 않습니다. 또한 컨테이너들끼리 내부적으로 사설 네트워크망을 공유하도록 별도의 docker network 명령어도 수행해야 합니다.
도커 컴포즈를 사용하면 이러한 컨테이너 간의 실행 순서 의존성, 가상 네트워크 분리, 데이터 보존을 위한 볼륨(Volume) 설정을 docker-compose.yml이라는 단 하나의 텍스트 파일에 일목요연하게 아키텍처 플랜으로 기록해 둘 수 있습니다. 덕분에 인프라 환경 전체를 코드로 관리(IaC, Infrastructure as Code)할 수 있어 깃허브(GitHub) 같은 버전 관리 시스템을 통해 팀원들과 서버 인프라 설정을 고스란히 공유할 수 있다는 엄청난 장점이 있습니다.
2. 리눅스 Ubuntu 서버에 도커 컴포즈 최신 버전 설치하기
과거에는 도커 컴포즈를 별도의 독립된 바이너리 파일로 다운로드하여 /usr/local/bin 경로에 넣는 방식을 사용했으나, 최근 도커 생태계가 업데이트되면서 도커 엔진의 공식 플러그인(Docker Compose V2) 형태로 설치하는 것이 표준 규격이 되었습니다.
앞선 가이드에서 도커 공식 저장소를 통해 도커 엔진을 설치했다면 아래 명령어를 통해 최신 도커 컴포즈 플러그인을 간단하게 추가할 수 있습니다.
Bash
sudo apt update
sudo apt install docker-compose-plugin -y
설치 버전 확인 및 검증
설치가 완료되었다면 도커 컴포즈 명령어가 시스템에 올바르게 등록되었는지 버전을 출력하여 확인합니다.
Bash
docker compose version
화면에 Docker Compose version v2.x.x와 같이 정상적으로 버증 정보가 출력된다면 이제 컴포즈 명령어를 사용할 준비가 완료된 것입니다. 과거 V1 버전 체계에서는 대시가 포함된 docker-compose 형태의 명령어를 썼으나, 최신 V2 체계부터는 도커 표준 명령어의 하위 서브 커맨드로 통합되어 한 칸 띄어 쓰는 docker compose 형식을 사용하는 것이 정석입니다.
3. 핵심 실무: docker-compose.yml 파일 구조 및 작성법
이제 실제로 Nginx 웹 서버와 MySQL 데이터베이스가 가상 네트워크 안에서 결합하여 작동하는 실무용 docker-compose.yml 설정 파일을 작성해 보겠습니다. 작업할 디렉터리를 만들고 파일 편집기를 엽니다.
Bash
mkdir my-app && cd my-app
nano docker-compose.yml
파일이 열리면 아래의 표준 컴포즈 구조 가이드 소스코드를 복사해서 붙여넣습니다. YAML 구조 특성상 들여쓰기(띄어쓰기 칸수)가 조금이라도 틀리면 문법 에러가 발생하므로 열 정렬에 각별히 유의해야 합니다.
YAML
version: '3.8'
services:
db:
image: mysql:8.0
container_name: compose-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: my-strong-password
MYSQL_DATABASE: my_project_db
volumes:
- db_data:/var/lib/mysql
web:
image: nginx:latest
container_name: compose-nginx
ports:
- "80:80"
restart: always
depends_on:
- db
volumes:
db_data:
필수 항목별 핵심 옵션 의미 분석
version: 이 설정 파일이 따르는 도커 컴포즈 규격의 버전입니다. 보통 안정적이고 폭넓은 기능을 지원하는3.8버전을 가장 많이 선언합니다.services: 이 파일 안에서 구동할 컨테이너 묶음들의 목록을 정의하는 최상위 노드입니다. 여기서는db와web이라는 두 개의 서비스를 선언했습니다.image: 컨테이너의 기반이 될 도커 허브의 이미지 이름과 태그 버전을 명시합니다.environment: 컨테이너 내부 리눅스 환경에 주입할 환경 변수 세팅입니다. MySQL의 루트 비밀번호와 생성할 기본 데이터베이스 이름을 지정했습니다.volumes: 컨테이너는 삭제되면 내부 데이터가 모두 소멸하는 휘발성 특징을 가집니다. 이를 방지하기 위해 파일 맨 아래 선언한db_data라는 도커 영구 볼륨을 컨테이너 내부의 MySQL 데이터 저장 경로와 동기화하여 연동해 둡니다. 이렇게 하면 컨테이너가 파괴되어도 데이터는 리눅스 호스트에 온전히 보존됩니다.ports: 외부 호스트 포트와 내부 컨테이너 포트를 포워딩해 줍니다. (호스트포트:컨테이너포트)depends_on: 실행 순서 제어 옵션입니다.web컨테이너는db컨테이너가 먼저 구동된 것을 확인한 후 뒤따라 순차적으로 켜지게 됩니다.
4. 도커 컴포즈 구동 및 관리 명령어 패턴
설정 파일 작성을 마쳤다면, 이제 터미널 창에서 해당 파일이 위치한 디렉터리로 이동하여 아래의 명령어들로 전체 시스템을 한 번에 제어할 수 있습니다.
백그라운드 일괄 실행: docker compose up -d
docker-compose.yml 파일을 읽어 필요한 이미지를 자동으로 다운로드하고, 가상 네트워크와 볼륨을 빌드한 뒤, 정의된 모든 컨테이너를 백그라운드(-d 옵션)에서 일괄 실행합니다.
Bash
docker compose up -d
컴포즈 그룹 상태 조회: docker compose ps
일반 docker ps와 달리, 현재 디렉터리의 컴포즈 설정 파일에 묶여서 한 몸으로 돌고 있는 컨테이너들만 필터링하여 일목요연하게 상태를 보여줍니다.
Bash
docker compose ps
시스템 전체 일괄 중지 및 자원 삭제: docker compose down
현재 구동 중인 모든 컨테이너 프로세스를 정중하게 안전 종료하고 생성되었던 가상 네트워크 통로까지 흔적도 없이 깔끔하게 철거하여 시스템 자원을 반환합니다. 단, 명시했던 볼륨 데이터는 지워지지 않고 영구 보존되므로 안심하셔도 됩니다.
Bash
docker compose down
결론: 복잡한 서버 인프라를 코드 한 줄로 다루는 혁신
도커 컴포즈의 도입은 수동으로 터미널에 명령어를 치며 인프라를 조립하던 과거의 방식에서 벗어나, 완벽하게 정제된 인프라 아키텍처 계획서(docker-compose.yml)를 기반으로 서버를 무인 제어하는 현대적인 데브옵스(DevOps) 환경의 표준으로 진입함을 의미합니다.
오늘 완성한 이 컴포즈 파일을 활용하면, 추후 서버 컴퓨터의 스펙을 올려 다른 인스턴스로 완전히 이주해야 하는 상황이 오더라도 도커 엔진과 도커 컴포즈 플러그인만 설치한 뒤 파일 하나만 복사해 넣으면 기존 운영 환경과 100% 일치하는 멀티 컨테이너 서비스를 단 3초 만에 완벽 재현할 수 있게 됩니다. 이 강력한 코드 기반 인프라 튜닝 기술을 바탕으로 보다 확장성 있고 유연한 웹 인프라 시스템을 설계해 보시기 바랍니다.