본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 26. · 18 Views
Docker Compose 실전 활용 완벽 가이드
Docker Compose를 활용하여 복잡한 멀티 컨테이너 환경을 손쉽게 구축하고 관리하는 방법을 배웁니다. 개발 환경부터 운영 환경까지, 실무에서 바로 적용할 수 있는 핵심 기법들을 단계별로 알아봅니다.
목차
1. 개발 환경 구축하기
신입 개발자 김개발 씨가 첫 출근날 가장 먼저 마주한 것은 바로 개발 환경 세팅이었습니다. "Node.js 버전 18이 필요하고, PostgreSQL은 15 버전으로, Redis도 설치해야 하고..." 선배의 설명을 듣던 김개발 씨는 점점 머리가 복잡해졌습니다.
그때 옆에 있던 박시니어 씨가 미소를 지으며 말했습니다. "걱정 마세요, docker-compose up 한 번이면 끝나요."
Docker Compose는 여러 개의 컨테이너를 하나의 설정 파일로 정의하고 관리하는 도구입니다. 마치 레스토랑의 주방장이 여러 요리사에게 동시에 지시를 내리는 것처럼, 하나의 명령으로 복잡한 애플리케이션 스택 전체를 실행할 수 있습니다.
이것을 제대로 활용하면 팀원 모두가 동일한 개발 환경에서 작업할 수 있어 "제 컴퓨터에서는 되는데요"라는 말이 사라집니다.
다음 코드를 살펴봅시다.
# docker-compose.yml - 기본 개발 환경 구성
version: '3.8'
services:
# Node.js 애플리케이션 서비스
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app # 소스 코드 실시간 반영
- /app/node_modules # node_modules는 컨테이너 내부 것 사용
environment:
- NODE_ENV=development
# PostgreSQL 데이터베이스
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=devpass
김개발 씨는 입사 첫날부터 난관에 봉착했습니다. 회사의 프로젝트를 로컬에서 실행하려면 설치해야 할 것들이 산더미였습니다.
Node.js, PostgreSQL, Redis, Elasticsearch까지. 각각의 버전도 맞춰야 하고, 설정도 일일이 해줘야 했습니다.
예전에는 이런 상황이 당연했습니다. 신입 개발자가 들어오면 하루 종일, 때로는 며칠에 걸쳐 개발 환경을 세팅했습니다.
그 과정에서 수많은 오류와 씨름해야 했고, 운영체제가 다르면 또 다른 문제가 발생했습니다. Docker Compose는 이런 고통을 한 방에 해결해줍니다.
쉽게 비유하자면, Docker Compose는 마치 이케아 가구의 조립 설명서와 같습니다. 설명서 하나만 있으면 누구나 똑같은 가구를 조립할 수 있듯이, docker-compose.yml 파일 하나만 있으면 누구나 동일한 개발 환경을 구축할 수 있습니다.
위 코드에서 **version: '3.8'**은 Compose 파일의 버전을 지정합니다. 최신 기능을 사용하려면 3.8 이상을 권장합니다.
services 섹션은 실행할 컨테이너들을 정의하는 핵심 부분입니다. 여기서는 app과 db라는 두 개의 서비스를 정의했습니다.
app 서비스를 자세히 살펴보겠습니다. **build: .**은 현재 디렉토리의 Dockerfile을 사용하여 이미지를 빌드한다는 의미입니다.
ports는 호스트의 3000번 포트와 컨테이너의 3000번 포트를 연결합니다. volumes 설정이 특히 중요합니다.
첫 번째 줄의 .:/app은 현재 디렉토리를 컨테이너의 /app에 마운트합니다. 이렇게 하면 코드를 수정할 때마다 컨테이너를 재시작하지 않아도 변경 사항이 바로 반영됩니다.
두 번째 줄의 /app/node_modules는 약간 트릭입니다. node_modules를 호스트와 공유하지 않고 컨테이너 내부 것을 사용하도록 합니다.
이렇게 하면 운영체제별로 다른 바이너리 문제를 피할 수 있습니다. db 서비스는 더 간단합니다.
image: postgres:15로 공식 PostgreSQL 15 이미지를 사용하고, 환경 변수로 비밀번호만 설정했습니다. 이제 김개발 씨가 해야 할 일은 단 하나입니다.
터미널에서 docker-compose up을 실행하는 것입니다. 그러면 모든 서비스가 자동으로 시작되고, 몇 분 만에 완벽한 개발 환경이 준비됩니다.
박시니어 씨는 덧붙였습니다. "새로운 팀원이 들어와도 README에 docker-compose up만 적어두면 되니까 정말 편해요."
실전 팁
💡 - docker-compose up -d를 사용하면 백그라운드에서 실행됩니다
- docker-compose logs -f로 모든 서비스의 로그를 실시간으로 확인할 수 있습니다
- .env 파일을 활용하면 환경 변수를 외부에서 관리할 수 있습니다
2. DB + 앱 서버 구성
개발 환경이 세팅된 후, 김개발 씨는 본격적으로 프로젝트 구조를 파악하기 시작했습니다. 웹 서버, API 서버, 데이터베이스, 캐시 서버까지.
서비스들이 서로 어떻게 연결되어 있는지 궁금해졌습니다. "이 서비스들이 서로 어떻게 통신하는 거죠?" 김개발 씨의 질문에 박시니어 씨가 docker-compose.yml 파일을 가리키며 설명을 시작했습니다.
Docker Compose에서 정의된 서비스들은 자동으로 동일한 네트워크에 속하게 됩니다. 마치 같은 사무실에서 일하는 동료들처럼, 서비스 이름만으로 서로를 찾아 통신할 수 있습니다.
복잡한 IP 주소나 포트 설정 없이도 app 서비스에서 db라는 이름으로 데이터베이스에 접속할 수 있는 것입니다.
다음 코드를 살펴봅시다.
# docker-compose.yml - 실전 멀티 서비스 구성
version: '3.8'
services:
api:
build: ./api
ports:
- "4000:4000"
environment:
# 서비스 이름으로 직접 접근 가능
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
- REDIS_URL=redis://cache:6379
networks:
- backend
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
cache:
image: redis:7-alpine
networks:
- backend
networks:
backend:
driver: bridge
volumes:
postgres_data:
김개발 씨는 이전 회사에서 개발 환경을 세팅할 때마다 고생했던 기억이 떠올랐습니다. 데이터베이스 IP를 확인하고, 방화벽 설정을 바꾸고, 포트 충돌을 해결하느라 반나절이 훌쩍 지나가곤 했습니다.
Docker Compose는 이런 네트워크 설정의 복잡함을 깔끔하게 해결해줍니다. 핵심은 서비스 디스커버리입니다.
같은 Compose 파일에 정의된 서비스들은 자동으로 같은 네트워크에 속하게 되고, 서비스 이름이 곧 호스트명이 됩니다. 마치 회사 내선 전화처럼, 번호만 누르면 바로 연결되는 것입니다.
위 코드에서 api 서비스의 DATABASE_URL을 보면 @db:5432라고 적혀 있습니다. 여기서 db는 IP 주소가 아니라 서비스 이름입니다.
Docker가 알아서 실제 IP로 변환해줍니다. Redis 연결도 마찬가지로 cache:6379로 간단하게 설정됩니다.
networks 섹션을 살펴보겠습니다. 여기서는 backend라는 이름의 네트워크를 정의하고 모든 서비스가 이 네트워크에 연결되도록 했습니다.
driver: bridge는 Docker의 기본 네트워크 드라이버로, 같은 호스트 내에서 컨테이너 간 통신을 가능하게 합니다. 실무에서는 네트워크를 여러 개로 분리하기도 합니다.
예를 들어 frontend 네트워크와 backend 네트워크를 따로 만들어서 웹 서버는 둘 다 연결하고, 데이터베이스는 backend에만 연결하는 식입니다. 이렇게 하면 보안이 강화됩니다.
volumes 섹션도 중요합니다. postgres_data라는 이름의 볼륨을 정의하고 PostgreSQL의 데이터 디렉토리에 마운트했습니다.
이것을 named volume이라고 부릅니다. 왜 named volume이 필요할까요?
컨테이너는 본질적으로 일시적입니다. docker-compose down으로 컨테이너를 삭제하면 그 안의 데이터도 함께 사라집니다.
하지만 named volume을 사용하면 컨테이너가 삭제되어도 데이터는 안전하게 보존됩니다. 박시니어 씨가 경고했습니다.
"개발 중에 실수로 docker-compose down -v를 실행하면 볼륨까지 삭제되니까 조심하세요. 테스트 데이터가 다 날아갈 수 있어요." 김개발 씨는 고개를 끄덕이며 메모했습니다.
볼륨 삭제는 정말 필요할 때만, 신중하게.
실전 팁
💡 - docker-compose down은 컨테이너만 삭제하고, -v 옵션을 추가해야 볼륨도 삭제됩니다
- docker volume ls로 생성된 볼륨 목록을 확인할 수 있습니다
- 네트워크를 분리하면 서비스 간 접근 제어가 가능해져 보안이 강화됩니다
3. depends on과 healthcheck
어느 날 김개발 씨는 이상한 현상을 목격했습니다. docker-compose up을 실행하면 가끔 애플리케이션이 "데이터베이스 연결 실패" 오류를 뱉어내는 것이었습니다.
다시 시작하면 잘 되기도 하고, 안 되기도 했습니다. "왜 이렇게 불안정하죠?" 박시니어 씨가 웃으며 대답했습니다.
"아, 그건 시작 순서 문제예요. depends_on만으로는 부족하거든요."
depends_on은 서비스의 시작 순서를 제어하지만, 서비스가 "진짜로 준비됐는지"는 확인하지 않습니다. 마치 식당 문이 열렸다고 해서 주방이 준비된 것은 아닌 것처럼, 컨테이너가 시작됐다고 해서 내부 애플리케이션이 요청을 받을 준비가 된 것은 아닙니다.
이 문제를 해결하려면 healthcheck를 함께 사용해야 합니다.
다음 코드를 살펴봅시다.
# docker-compose.yml - 안정적인 서비스 시작 순서
version: '3.8'
services:
api:
build: ./api
depends_on:
db:
condition: service_healthy # DB가 healthy 상태일 때만 시작
cache:
condition: service_started
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=secretpass
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s # 5초마다 체크
timeout: 5s # 5초 안에 응답 없으면 실패
retries: 5 # 5번 실패하면 unhealthy
cache:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 3s
retries: 3
김개발 씨가 겪은 문제는 Docker Compose를 사용하는 많은 개발자들이 한 번쯤 마주하는 고전적인 이슈입니다. 문제의 핵심은 이렇습니다.
PostgreSQL 컨테이너가 "시작"되는 것과 PostgreSQL 서버가 "연결을 받을 준비가 되는 것"은 다릅니다. 컨테이너는 몇 초 만에 시작되지만, 내부에서 데이터베이스가 초기화되고 네트워크 연결을 받을 준비를 하는 데는 더 많은 시간이 걸립니다.
depends_on만 사용하면 Docker는 "db 컨테이너가 시작됐으니 api를 시작해도 되겠군"이라고 판단합니다. 하지만 실제로 PostgreSQL은 아직 준비 중입니다.
그래서 api가 연결을 시도하면 실패하는 것입니다. healthcheck는 이 문제를 해결합니다.
healthcheck는 마치 의사가 환자의 상태를 체크하는 것과 같습니다. 주기적으로 컨테이너에게 "너 괜찮아?"라고 물어보고, 대답이 돌아오면 healthy 상태로 표시합니다.
위 코드에서 db 서비스의 healthcheck를 살펴보겠습니다. test 필드는 건강 상태를 확인하는 명령어입니다.
pg_isready는 PostgreSQL이 제공하는 공식 유틸리티로, 데이터베이스가 연결을 받을 준비가 됐는지 확인합니다. interval: 5s는 5초마다 상태를 체크한다는 의미입니다.
timeout: 5s는 명령어가 5초 안에 응답하지 않으면 실패로 간주합니다. retries: 5는 5번 연속 실패해야 unhealthy 상태가 된다는 뜻입니다.
이제 api 서비스의 depends_on을 보겠습니다. condition: service_healthy가 핵심입니다.
이 옵션을 사용하면 db가 단순히 시작된 것이 아니라, healthcheck를 통과해서 healthy 상태가 됐을 때만 api가 시작됩니다. 참고로 condition: service_started는 기존 depends_on과 동일한 동작입니다.
컨테이너가 시작되면 바로 다음 서비스를 시작합니다. Redis처럼 시작이 빠른 서비스에는 이것으로 충분할 수 있습니다.
박시니어 씨가 팁을 하나 더 알려줬습니다. "healthcheck는 운영 환경에서도 유용해요.
로드밸런서가 healthy한 컨테이너에만 트래픽을 보내거든요. Kubernetes의 readinessProbe와 비슷한 개념이에요." 김개발 씨는 docker-compose up을 다시 실행했습니다.
이번에는 PostgreSQL이 완전히 준비된 후에야 API 서버가 시작됐고, 연결 오류는 더 이상 발생하지 않았습니다.
실전 팁
💡 - 각 서비스에 맞는 healthcheck 명령어를 사용하세요 (PostgreSQL: pg_isready, MySQL: mysqladmin ping, Redis: redis-cli ping)
- interval을 너무 짧게 설정하면 불필요한 부하가 발생할 수 있습니다
- docker-compose ps로 각 서비스의 health 상태를 확인할 수 있습니다
4. 여러 환경 설정 분리
프로젝트가 진행되면서 김개발 씨는 새로운 고민에 빠졌습니다. 개발 환경에서는 디버그 모드로, 테스트 환경에서는 테스트 데이터베이스로, 스테이징 환경에서는 실제와 비슷한 설정으로 실행해야 했습니다.
매번 docker-compose.yml을 수정하자니 실수할 것 같고, 파일을 여러 개 만들자니 관리가 복잡해질 것 같았습니다.
Docker Compose는 환경 변수와 .env 파일을 통해 설정을 유연하게 관리할 수 있습니다. 마치 요리 레시피는 같지만 재료의 양을 조절하는 것처럼, 기본 구조는 유지하면서 환경에 따라 세부 설정만 바꿀 수 있습니다.
이렇게 하면 하나의 docker-compose.yml로 여러 환경을 지원할 수 있습니다.
다음 코드를 살펴봅시다.
# .env.development
POSTGRES_USER=devuser
POSTGRES_PASSWORD=devpass
POSTGRES_DB=myapp_dev
NODE_ENV=development
LOG_LEVEL=debug
# .env.production
POSTGRES_USER=produser
POSTGRES_PASSWORD=${SECURE_DB_PASSWORD}
POSTGRES_DB=myapp_prod
NODE_ENV=production
LOG_LEVEL=error
# docker-compose.yml - 환경 변수 활용
version: '3.8'
services:
api:
build: ./api
environment:
- NODE_ENV=${NODE_ENV:-development}
- LOG_LEVEL=${LOG_LEVEL:-info}
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
db:
image: postgres:15
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
김개발 씨의 고민은 실무에서 매우 흔한 문제입니다. 개발, 테스트, 스테이징, 프로덕션 등 여러 환경을 관리해야 하는데, 각 환경마다 설정이 조금씩 다릅니다.
가장 나쁜 방법은 환경별로 docker-compose.yml을 따로 만드는 것입니다. 파일이 늘어나면 관리가 어려워지고, 하나를 수정할 때 다른 파일도 함께 수정해야 하는 번거로움이 생깁니다.
더 좋은 방법은 환경 변수를 활용하는 것입니다. Docker Compose는 기본적으로 같은 디렉토리의 .env 파일을 자동으로 읽습니다.
이 파일에 정의된 변수들은 docker-compose.yml에서 ${변수명} 형태로 사용할 수 있습니다. 위 코드의 예시를 보겠습니다.
**${NODE_ENV:-development}**에서 :-development 부분은 기본값입니다. NODE_ENV 변수가 정의되지 않았을 때 development를 사용한다는 의미입니다.
실무에서는 보통 이런 방식으로 작업합니다. 먼저 .env.example 파일을 만들어 필요한 변수 목록을 정의합니다.
이 파일은 Git에 커밋합니다. 그리고 각 환경에서는 이를 복사해서 .env 파일을 만들고 실제 값을 채웁니다.
.env 파일은 민감한 정보가 포함되어 있으므로 .gitignore에 추가합니다. 박시니어 씨가 중요한 팁을 알려줬습니다.
"프로덕션 환경에서는 .env 파일 대신 시스템 환경 변수를 사용하는 게 더 안전해요. CI/CD 파이프라인에서 비밀 값을 주입하는 방식이죠." 환경별로 다른 .env 파일을 사용하고 싶다면 --env-file 옵션을 활용합니다.
예를 들어 docker-compose --env-file .env.staging up처럼 실행하면 됩니다. 또 하나 주의할 점이 있습니다.
환경 변수에 특수 문자가 포함되어 있다면 따옴표로 감싸야 합니다. 특히 비밀번호에 $나 # 같은 문자가 들어가면 예상치 못한 문제가 발생할 수 있습니다.
김개발 씨는 이제 환경별 설정 파일을 깔끔하게 관리할 수 있게 됐습니다. 개발 환경에서는 .env.development를 복사해서 사용하고, CI/CD에서는 파이프라인이 알아서 적절한 환경 변수를 주입합니다.
실전 팁
💡 - .env.example 파일을 만들어 필요한 환경 변수 목록을 문서화하세요
- 민감한 정보가 담긴 .env 파일은 반드시 .gitignore에 추가하세요
- 프로덕션에서는 시스템 환경 변수나 시크릿 매니저를 사용하는 것이 더 안전합니다
5. docker-compose override
환경 변수로 많은 것을 해결했지만, 김개발 씨는 또 다른 상황에 부딪혔습니다. 개발 환경에서는 소스 코드를 볼륨으로 마운트해서 핫 리로드를 사용하고 싶고, 프로덕션에서는 빌드된 이미지만 사용하고 싶었습니다.
이런 구조적인 차이는 환경 변수로는 해결할 수 없었습니다.
Docker Compose의 override 기능은 기본 설정 파일 위에 추가 설정을 덮어쓸 수 있게 해줍니다. 마치 투명 필름을 겹쳐 놓는 것처럼, 기본 설정은 유지하면서 필요한 부분만 변경하거나 추가할 수 있습니다.
docker-compose.yml과 docker-compose.override.yml이 함께 있으면 자동으로 병합됩니다.
다음 코드를 살펴봅시다.
# docker-compose.yml - 기본 설정 (모든 환경 공통)
version: '3.8'
services:
api:
image: myapp/api:${TAG:-latest}
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
db:
image: postgres:15
# docker-compose.override.yml - 개발 환경용 (자동 적용)
version: '3.8'
services:
api:
build: ./api # 이미지 대신 빌드
volumes:
- ./api:/app # 소스 코드 마운트
ports:
- "4000:4000" # 디버그 포트 노출
environment:
- DEBUG=true
command: npm run dev # 개발 서버 실행
# docker-compose.prod.yml - 프로덕션 환경용
version: '3.8'
services:
api:
deploy:
replicas: 3 # 3개 인스턴스 실행
resources:
limits:
memory: 512M
앞서 환경 변수로 설정값을 바꾸는 방법을 배웠습니다. 하지만 개발 환경에서만 볼륨을 마운트하거나, 프로덕션에서만 리소스 제한을 걸거나 하는 것은 환경 변수로는 불가능합니다.
이럴 때 override 파일이 필요합니다. Docker Compose는 똑똑한 파일 병합 시스템을 가지고 있습니다.
기본 동작은 이렇습니다. docker-compose up을 실행하면 Docker Compose는 먼저 docker-compose.yml을 읽습니다.
그다음 같은 디렉토리에 docker-compose.override.yml이 있으면 자동으로 함께 읽어서 병합합니다. 병합 규칙은 직관적입니다.
같은 서비스에 대해 두 파일에 다른 설정이 있으면, override 파일의 설정이 우선합니다. 배열 타입(volumes, ports, environment 등)은 합쳐집니다.
위 코드를 예로 들어보겠습니다. 기본 docker-compose.yml에서 api 서비스는 image: myapp/api 설정을 가지고 있습니다.
하지만 override 파일에서는 build: ./api를 지정했습니다. 이 경우 개발 환경에서는 이미지를 사용하는 대신 소스 코드를 직접 빌드합니다.
volumes와 environment 설정은 기존 것에 추가됩니다. 기본 파일의 DATABASE_URL과 override 파일의 DEBUG=true가 모두 적용됩니다.
프로덕션 환경에서는 어떻게 할까요? override 파일을 사용하고 싶지 않다면 -f 옵션으로 명시적으로 파일을 지정합니다.
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up 이렇게 하면 docker-compose.override.yml은 무시되고, 기본 파일과 prod 파일만 병합됩니다. 박시니어 씨가 실무 팁을 공유했습니다.
"저희 팀은 이런 구조를 사용해요. docker-compose.yml에는 모든 환경에서 공통인 설정만 넣고, override.yml에는 개발 환경 설정을 넣습니다.
CI/CD에서는 -f 옵션으로 prod 파일을 명시적으로 지정하고요." 이 방식의 장점은 개발자들이 평소에는 그냥 docker-compose up만 실행하면 된다는 것입니다. 별도의 옵션 없이도 개발에 필요한 모든 설정이 자동으로 적용됩니다.
김개발 씨는 이제 환경별로 완전히 다른 구성도 깔끔하게 관리할 수 있게 됐습니다.
실전 팁
💡 - docker-compose.override.yml은 자동으로 적용되므로 .gitignore에 추가하고 개인 설정용으로 사용하기도 합니다
- docker-compose config 명령으로 최종 병합된 설정을 확인할 수 있습니다
- 여러 개의 override 파일을 순서대로 적용할 수 있습니다: -f base.yml -f override1.yml -f override2.yml
6. 로컬 개발 워크플로우
이제 김개발 씨는 Docker Compose의 다양한 기능을 익혔습니다. 하지만 실제로 매일 개발하면서 사용하려니 자잘한 불편함들이 느껴졌습니다.
로그는 어떻게 보지? 컨테이너 안에 들어가서 뭔가 확인하고 싶을 때는?
데이터베이스를 리셋하고 싶을 때는? 박시니어 씨가 일상적으로 사용하는 명령어들을 정리해주기로 했습니다.
효율적인 Docker Compose 개발 워크플로우는 몇 가지 핵심 명령어의 조합으로 이루어집니다. 서비스 시작과 중지, 로그 확인, 컨테이너 접속, 그리고 깔끔한 정리까지.
이 명령어들을 익히면 마치 IDE의 단축키처럼 손에 익어서 개발 속도가 크게 향상됩니다.
다음 코드를 살펴봅시다.
# 1. 기본 실행 명령어
docker-compose up -d # 백그라운드 실행
docker-compose up --build # 이미지 다시 빌드 후 실행
docker-compose up api db # 특정 서비스만 실행
# 2. 로그 확인
docker-compose logs -f # 모든 서비스 로그 (실시간)
docker-compose logs -f api # 특정 서비스 로그만
docker-compose logs --tail=100 api # 마지막 100줄만
# 3. 컨테이너 접속 및 명령 실행
docker-compose exec api sh # api 컨테이너 셸 접속
docker-compose exec db psql -U postgres # DB 직접 접속
docker-compose run --rm api npm test # 일회성 명령 실행
# 4. 서비스 관리
docker-compose restart api # 특정 서비스 재시작
docker-compose stop # 모든 서비스 중지
docker-compose down # 컨테이너 삭제
docker-compose down -v # 컨테이너 + 볼륨 삭제 (주의!)
# 5. 상태 확인
docker-compose ps # 서비스 상태 확인
docker-compose top # 각 컨테이너의 프로세스 확인
프로그래밍을 잘하는 것과 개발 환경을 잘 다루는 것은 별개의 기술입니다. 아무리 코드를 잘 짜도 개발 도구를 다루는 데 시간을 낭비하면 생산성이 떨어집니다.
Docker Compose도 마찬가지입니다. 박시니어 씨는 자신의 일상적인 워크플로우를 설명했습니다.
아침에 출근하면 먼저 docker-compose up -d를 실행합니다. -d 옵션은 detached 모드로, 백그라운드에서 실행됩니다.
터미널을 차지하지 않아서 다른 작업을 할 수 있습니다. 코드를 수정하고 문제가 생기면 docker-compose logs -f api로 로그를 확인합니다.
-f는 follow의 약자로, 새로운 로그가 생길 때마다 실시간으로 출력됩니다. 여러 서비스의 로그를 동시에 보려면 서비스 이름을 생략하면 됩니다.
exec와 run의 차이를 이해하는 것이 중요합니다. docker-compose exec api sh는 이미 실행 중인 api 컨테이너에 접속합니다.
반면 docker-compose run --rm api npm test는 새로운 컨테이너를 만들어서 명령을 실행하고, 끝나면 컨테이너를 삭제합니다. 테스트나 마이그레이션 같은 일회성 작업에 적합합니다.
데이터베이스 작업이 필요할 때는 docker-compose exec db psql -U postgres로 직접 접속합니다. 별도의 데이터베이스 클라이언트를 설치할 필요가 없습니다.
퇴근 전에는 docker-compose down으로 깔끔하게 정리합니다. 하지만 down -v는 조심해야 합니다.
볼륨까지 삭제하면 데이터베이스의 모든 데이터가 사라집니다. 일부러 초기화하고 싶을 때만 사용하세요.
가끔 설정을 변경했는데 반영이 안 될 때가 있습니다. 이럴 때는 docker-compose up --build로 이미지를 강제로 다시 빌드합니다.
Dockerfile이나 의존성을 변경했을 때 필요합니다. 박시니어 씨가 마지막 팁을 전했습니다.
"저는 자주 쓰는 명령어들을 셸 별칭(alias)으로 등록해놨어요. dcu는 docker-compose up -d, dcl은 docker-compose logs -f 이런 식으로요.
하루에 수십 번 치는 명령어니까 초를 아끼면 결국 시간이 많이 절약돼요." 김개발 씨는 이제 Docker Compose를 자유자재로 다룰 수 있게 됐습니다. 처음에는 복잡해 보였던 명령어들이 이제는 손에 익은 도구가 됐습니다.
실전 팁
💡 - 자주 쓰는 명령어는 셸 별칭(alias)으로 등록하면 편리합니다
- docker-compose down -v --remove-orphans는 완전한 초기화가 필요할 때 사용합니다
- docker-compose pull로 이미지를 미리 받아두면 up 할 때 시간을 절약할 수 있습니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Roundcube 웹메일 인터페이스 완벽 가이드
Docker 컨테이너 기반으로 Roundcube 웹메일을 구축하고, Nginx 리버스 프록시부터 플러그인 관리, 테마 커스터마이징까지 전체 과정을 다룹니다. 초급 개발자도 쉽게 따라할 수 있는 실무 중심 가이드입니다.
SSL/TLS 인증서 설정 완벽 가이드 (Let's Encrypt)
메일 서버 운영에 필수적인 SSL/TLS 인증서 설정 방법을 다룹니다. Let's Encrypt를 활용한 무료 인증서 발급부터 자동 갱신까지, 실무에서 바로 적용할 수 있는 내용을 담았습니다.
Docker 환경 준비 및 docker-mailserver 설치
나만의 메일 서버를 Docker로 구축하는 방법을 처음부터 끝까지 안내합니다. docker-mailserver를 활용하여 실무에서 바로 사용할 수 있는 메일 시스템을 단계별로 설정해봅니다.
메일 서버 아키텍처 설계 완벽 가이드
메일 서버를 직접 구축하고 운영하기 위한 아키텍처 설계 방법을 다룹니다. MTA, MDA부터 고가용성 설계까지 실무에서 필요한 모든 것을 초급자도 이해할 수 있도록 쉽게 설명합니다.
Docker 보안 베스트 프랙티스 완벽 가이드
Docker 컨테이너 환경에서 보안을 강화하는 필수 기법들을 다룹니다. 루트 사용자 제한부터 시크릿 관리, 리소스 제한까지 실무에서 바로 적용할 수 있는 보안 설정을 배워봅니다.