
Docker Compose를 사용하여 로컬 데이터 엔지니어링 환경을 구축하는 방법
요약
Docker Compose를 활용하여 Airflow, PostgreSQL, Spark, Redis 등 복잡한 데이터 엔지니어링 스택을 로컬 환경에 일관되게 구축하는 방법을 설명합니다. 수동 설치로 인한 환경 불일치 문제를 해결하고, 코드로서의 인프라(IaC) 개념을 통해 팀 온보딩 효율을 높이는 가이드를 제공합니다.
핵심 포인트
- Docker Compose를 통한 데이터 스택의 코드화 및 재현성 확보
- Airflow, PostgreSQL, Spark 등 다중 컨테이너 오케스트레이션
- Docker Compose v1 종료에 따른 v2 사용 권장
- 서비스, 네트워크, 볼륨 설정을 통한 로컬 환경 표준화
요약 (TL;DR): Docker Compose를 사용하면 단 하나의 YAML 파일과 명령어 하나로 Airflow, PostgreSQL, Spark, Redis와 같은 전체 로컬 데이터 스택 (Data Stack)을 실행할 수 있습니다. 이 가이드는 정확한 설정 방법, 실제 Compose 설정, 그리고 많은 엔지니어들이 과정 중에 저지르는 실수들을 안내합니다.
당신의 로컬 데이터 환경이 아마도 엉망인 이유
문제는 이렇습니다. 제가 아는 대부분의 데이터 엔지니어들은 기술적으로는 작동하지만, 오직 본인의 컴퓨터에서, 운이 좋은 날에만, 모든 조건이 완벽하게 맞아떨어질 때만 작동하는 로컬 설정을 가지고 있습니다.
PostgreSQL을 수동으로 설치합니다. Python 버전을 고정합니다. 다른 무언가를 망가뜨리지 않고 Airflow를 실행하기 위해 고군분트합니다. 그러다 새로운 팀원이 합류하면, 당신의 환경을 재현하는 데만 꼬박 사흘을 보냅니다.
이것은 엔지니어링의 문제가 아닙니다. 도구 (Tooling)의 문제입니다. 그리고 Docker Compose가 이 문제를 해결합니다.
Docker Compose를 사용하면 서비스 (Services), 네트워크 (Networks), 볼륨 (Volumes), 환경 변수 (Environment Variables)와 같은 전체 로컬 데이터 스택을 코드로서 기술할 수 있으며, 명령어 하나로 이를 실행하거나 제거할 수 있습니다. 더 이상 "내 컴퓨터에서는 되는데"라는 말은 필요 없습니다. 3일간의 온보딩 (Onboarding) 악몽도 더 이상 없습니다.
이 가이드는 전체적인 그림을 다룹니다: Docker Compose가 실제로 무엇인지 (그리고 무엇이 아닌지), 이해해야 할 구성 요소들, 그리고 Airflow, PostgreSQL, Redis, Spark를 포함한 프로덕션 품질의 예시 스택을 다룹니다.
Docker Compose란 무엇인가 (그리고 무엇이 아닌가)
Docker Compose는 단일 머신에서 **다중 컨테이너 Docker 애플리케이션 (Multi-container Docker applications)**을 정의하고 실행하기 위한 오케스트레이션 (Orchestration) 도구입니다. 각 서비스가 어떤 이미지 (Image)를 사용하는지, 어떤 포트 (Ports)를 노출하는지, 다른 서비스와 어떻게 연결되는지, 그리고 데이터를 어디에 저장하는지를 기술하는 compose.yaml 파일을 작성합니다.
더 진행하기 전에 짧게 언급하자면, Docker Compose v1은 2023년 7월에 수명이 종료(End-of-life)되었습니다. 기존의 docker-compose 바이너리(하이픈 포함)는 더 이상 사용되지 않습니다. 여러분은 내장 CLI 플러그인으로 제공되는 Docker Compose v2를 사용해야 합니다. 스크립트나 튜토리얼 어디에서든 docker-compose를 보게 된다면, 이를 docker compose(하이픈 없이 공백 사용)로 교체하십시오.
또한 알아두어야 할 점은, Compose 파일 상단의 version: 필드는 이제 공식적으로 지원 중단(Deprecated)되었다는 것입니다. 이 필드는 더 이상 필요하지 않습니다. 새로 작성하는 모든 파일에서 이를 완전히 제거하십시오.
Docker Compose는 다음과 같은 용도가 아닙니다:
- 운영 환경(Production)에서 Kubernetes를 대체하는 도구
- 여러 대의 머신에 분산된 배포를 관리하는 도구
- 운영 환경에서 적절한 비밀 관리(Secrets management)를 대신하는 도구
하지만 로컬 개발(Local development), CI 파이프라인, 그리고 단일 머신 스테이징(Staging) 환경에서는? 이보다 더 나은 도구를 찾기 어렵습니다.
출처: Docker 공식 문서 — docs.docker.com/compose; freeCodeCamp Docker Compose v2 가이드 (2026); compose-spec.io의 Docker Compose 명세(Specification)
사전 요구 사항 (Prerequisites)
YAML 코드를 한 줄이라도 작성하기 전에, 다음 사항을 갖추었는지 확인하십시오:
- Docker Desktop (v4.0 이상) 또는 Linux 환경의 Docker Engine + docker-compose-plugin
- 최소 8GB RAM 사용 가능 (데이터 스택은 메모리를 많이 소모합니다)
- 최소 4 CPU 코어 — 특히 Spark는 여유 공간이 필요합니다
- 명령줄 인터페이스(Command line)에 대한 기본적인 익숙함
설정이 최신 상태인지 확인하려면 다음을 실행하십시오:
docker compose version
# 2026년 기준으로 v2.24 이상이 표시되어야 합니다
만약 해당 명령어가 실패하거나 v1.x를 표시한다면, 계속 진행하기 전에 Docker를 업데이트하십시오.
핵심 구성 요소 이해하기 (Understanding the Core Building Blocks)
전체 스택으로 뛰어들기 전에, Docker Compose가 실제로 관리하는 네 가지 요소에 대한 개념 모델(Mental model)이 필요합니다.
서비스 (Services)
서비스 (Services)는 실행 중인 컨테이너를 의미합니다. Compose 파일의 services: 아래에 있는 각 항목은 하나 이상의 컨테이너가 됩니다. 데이터 엔지니어링 스택 (Data engineering stack)의 경우, 서비스는 데이터베이스 (Database), 오케스트레이터 (Orchestrator), 메시지 브로커 (Message broker), 변환 도구 (Transformation tool) 등이 될 수 있습니다.
네트워크 (Networks)
기본적으로 Compose 파일 내의 모든 서비스는 **서비스 이름 (Service name)**을 호스트 이름 (Hostname)으로 사용하여 다른 모든 서비스와 통신할 수 있습니다. IP 주소도 필요 없고, 수동 DNS 설정도 필요 없습니다. 이는 가장 과소평가된 기능 중 하나입니다. 예를 들어, Airflow 스케줄러는 말 그대로 postgres를 호스트 이름으로 사용하여 Postgres에 연결합니다.
볼륨 (Volumes)
볼륨 (Volumes)은 컨테이너가 재시작되어도 데이터가 유지되도록 하는 방법입니다. 두 가지 유형이 있습니다: 이름이 지정된 볼륨 (Named volumes) (Docker가 관리하며, 데이터베이스에 권장됨)과 바인드 마운트 (Bind mounts) (호스트 머신의 폴더를 컨테이너에 마운트하는 방식으로, DAG, 스크립트 및 현재 편집 중인 코드에 유용함)입니다.
환경 변수 (Environment Variables)
Compose 파일에 자격 증명 (Credentials)을 절대 하드코딩하지 마세요. 항상 .env 파일을 사용하고 ${VARIABLE_NAME} 구문을 사용하여 변수를 참조하십시오. .env 파일은 버전 관리 (Version control) 대상에서 제외되지만, compose.yaml은 포함됩니다.
스택 구축하기: 실제 데이터 엔지니어링 환경
실제적인 것을 구축해 봅시다. 이 스택은 대부분의 데이터 엔지니어링 워크플로우 (Workflows)에 등장하는 도구들을 다룹니다:
| 서비스 (Service) | 역할 (Role) | 포트 (Port) |
|---|---|---|
| PostgreSQL | 메타데이터 DB + 데이터 웨어하우스 (Data warehouse) | 5432 |
| ... | ||
![]() |
1단계 — 프로젝트 구조 (Project Structure)
깔끔한 폴더 구조로 시작하세요. 이는 대부분의 튜토리얼이 인정하는 것보다 더 중요합니다. 지저분한 폴더는 엉킨 볼륨 마운트 (Volume mounts)와 혼란스러운 빌드 컨텍스트 (Build contexts)를 생성합니다.
data-eng-local/
├── compose.yaml
├── .env
...
두 가지 규칙: compose.yaml을 루트 (Root)에 두고, .env를 절대로 git에 커밋하지 마세요. 잊어버리기 전에 지금 바로 .gitignore에 추가하십시오.
2단계 — .env 파일
# .env — 버전 관리 시스템에 커밋하지 마세요
POSTGRES_USER=dataeng
POSTGRES_PASSWORD=changeme_local
...
다음 명령어로 Fernet 키를 생성하세요:
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
3단계 — compose.yaml 파일
전체 설정입니다. 인라인 주석을 읽어보세요. 이 주석들은 단순히 구문(syntax)뿐만 아니라 결정된 이유를 설명해줍니다.
# compose.yaml — 버전 필드가 필요하지 않음 (Compose v2에서 사용 중단됨)
x-airflow-common: &airflow-common
...
4단계 — 스택 시작하기
# 처음 실행 시 — Airflow의 데이터베이스를 초기화하고 관리자 사용자(admin user)를 생성합니다.
docker compose up airflow-init
...
이것으로 끝입니다. 모든 것이 녹색(green) 상태가 되면, 서비스는 다음 주소에서 접근할 수 있습니다:
- Airflow UI: http://localhost:8080 (admin / admin)
- Spark UI: http://localhost:4040
- Adminer: http://localhost:8085 (server:
postgres, user:dataeng)
상태 확인(Health Checks): 대부분의 사람들이 건너뛰는 기능
이것은 대부분의 튜토리얼에서 생략하는 부분이며, 실제로 매우 중요합니다.
상태 확인 없이는 depends_on이 거의 쓸모가 없습니다. 기본적으로 Docker는 프로세스가 시작되는 순간 컨테이너를
compose.yaml에 자격 증명(Credentials)을 하드코딩하는 것 — 하지 마세요. .env 파일을 사용하세요. 설정하는 데 30초밖에 걸리지 않으며, 실수로 비밀번호를 공개 저장소(Public repo)에 커밋하는 것을 방지해 줍니다. 생각보다 자주 발생하는 일입니다.
docker compose (v2) 대신 docker-compose (v1)를 사용하는 것 — 구형 바이너리는 이제 사용되지 않습니다. 2023년 중반 이전의 튜토리얼에서 설정을 복사하고 있다면 이 부분을 확인하세요.
Compose 파일에 version:을 포함하는 것 — 이 필드는 Docker Compose v2부터 폐지(Obsolete)되었으며, 현재 Docker Desktop에서 지원 중단(Deprecation) 경고를 발생시킵니다. 직접 작성하거나 유지 관리하는 모든 파일에서 이를 제거하세요.
이미지 버전을 고정(Pinning)하지 않는 것 — postgres:latest는 함정입니다. 한 번의 업그레이드만으로 초기화 SQL(Init SQL)이 실패하거나, 연결 문자열(Connection string)이 변경되거나, 확장 프로그램(Extension)이 존재하지 않을 수 있습니다. 항상 postgres:16과 같이 버전을 고정하세요.
.gitignore에 .env를 추가하는 것을 잊는 것 — 진심입니다. 이것부터 하세요.
docker compose down을 의도했을 때 docker compose down -v를 실행하는 것 — -v 플래그는 이름이 지정된 볼륨(Named volumes)을 삭제합니다. 즉, 데이터베이스 데이터가 사라진다는 뜻입니다. 되돌릴 수 없습니다. 해당 플래그를 사용할 때는 매우 신중해야 합니다.
스택을 일상적으로 운영하기
스택이 실행되면, 가장 자주 사용하게 될 명령어는 다음과 같습니다:
# 실행 중인 상태와 상태 확인(Health status)을 체크합니다
docker compose ps
...
프로필(Profiles)을 사용하여 여러 환경 관리하기
스택이 더 복잡해졌을 때 알아두면 유용한 내용입니다. Docker Compose 프로필(Profiles)을 사용하면 특정 컨텍스트에서만 시작되는 서비스를 정의할 수 있습니다. 서비스에 profiles: [dev] 또는 profiles: [monitoring] 태그를 지정하면, 해당 프로필을 명시적으로 요청할 때만 실행됩니다.
services:
# 이 서비스는 docker compose --profile monitoring up 명령을 실행할 때만 시작됩니다
prometheus:
...
이것이 바로 여러 개의 파일을 유지 관리하지 않고도 로컬 개발 (local dev), CI, 스테이징 (staging) 등 모든 환경에서 작동하는 단일 compose.yaml을 유지하는 방법입니다. 이는 Compose가 알려진 평판보다 훨씬 더 프로덕션 환경에 적합하게 만들어주는, 조용하지만 강력한 기능 중 하나입니다.
E-E-A-T 참조: 도구, 버전 및 출처
이 가이드에서 사용된 검증된 도구 버전과 공식 문서를 확인할 수 있는 빠른 참조 테이블입니다.
| 도구 | 사용된 버전 | 공식 문서 |
|---|---|---|
| Docker Compose | v2.24+ | docs.docker.com/compose |
| ... |
추가 읽을거리:
- Docker Compose Specification: compose-spec.io — 모든 YAML 구문에 대한 권위 있는 참조 자료
- Apache Airflow 공식 Docker Compose 설정: airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html
- Data Engineering Zoomcamp (DataTalks.Club): Docker + Airflow + dbt 워크플로를 다루는 실무 중심의 핸즈온 코스 — datatalks.club/courses/data-engineering-zoomcamp.html
- freeCodeCamp — "How to Use Docker Compose for Production Workloads" (2026년 3월): 프로파일 (profiles), watch 모드, GPU 지원을 심도 있게 다룸
마무리
신뢰할 수 있는 로컬 데이터 엔지니어링 환경을 구축하는 것은 과거에는 하루 종일 좌절하며 씨름해야 하는 작업이었습니다. Docker Compose를 사용하면 이는 단 한 번의 투자로 끝납니다. compose.yaml을 한 번 작성하여 리포지토리 (repo)에 커밋하면, 팀의 모든 구성원이 docker compose up 명령만으로 정확히 동일한 환경을 갖게 됩니다.
진행하면서 기억해야 할 몇 가지 사항입니다:
version:필드는 사용되지 않으므로(deprecated) 삭제하세요depends_on사용 시 항상condition: service_healthy를 사용하세요latest대신 이미지 버전을 고정(pin)하세요- 자격 증명 (credentials)은
.env에 보관하고, 절대 compose 파일에 넣지 마세요 - 볼륨 (volumes)에 이름을 지정하세요 — 복구할 수 없는 데이터는 가치가 없습니다
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

