1. 멀티 컨테이너 구성의 필요성
컨테이너는 “하나의 컨테이너 = 하나의 프로세스”라는 원칙을 따르는 것이 이상적입니다. 즉, 하나의 컨테이너에 웹 서버, DB, 캐시를 모두 넣기보다 역할에 따라 분리하는 것이 바람직합니다.
예시:
- web: Django 또는 Flask와 같은 애플리케이션 서버
- db: PostgreSQL, MySQL 등 데이터베이스 서버
- cache: Redis, Memcached
- proxy: Nginx, Caddy와 같은 리버스 프록시/로드밸런서
이렇게 분리하면 얻는 장점은 다음과 같습니다.
- 유지보수성: 특정 서비스에 문제가 생겨도 해당 컨테이너만 재시작 가능
- 확장성: 트래픽이 몰리면 웹 컨테이너만 수평 확장 가능
- 표준화: 각 컨테이너가 독립적이므로 다른 프로젝트에도 쉽게 재활용 가능
2. Docker Compose 기본 개념
멀티 컨테이너 환경을 일일이 docker run 명령어로 관리하는 것은 번거롭습니다. 이를 해결해주는 도구가 Docker Compose입니다.
docker-compose.yml 파일 하나로 서비스 정의, 네트워크, 볼륨을 함께 관리할 수 있습니다.
예시: Django + PostgreSQL + Nginx
version: '3.8'
services:
web:
build: ./app
container_name: django_app
command: gunicorn myproject.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./app:/usr/src/app
ports:
- "8000:8000"
depends_on:
- db
environment:
- DATABASE_URL=postgres://user:password@db:5432/mydb
db:
image: postgres:14
container_name: postgres_db
restart: always
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
nginx:
image: nginx:latest
container_name: nginx_proxy
volumes:
- ./nginx/conf:/etc/nginx/conf.d
ports:
- "80:80"
depends_on:
- web
volumes:
postgres_data:
핵심 포인트
- depends_on: 컨테이너 간 실행 순서 보장
- volumes: 데이터 영속성 확보
- environment: 환경변수를 통해 유연하게 설정
- ports: 외부와 연결할 포트 지정
이렇게 정의된 Compose 파일은 docker-compose up -d 한 줄로 실행 가능합니다.
3. 로컬 개발 vs 운영 환경 분리
Compose는 환경에 따라 설정을 다르게 가져갈 수 있습니다.
- 로컬 개발: 코드 볼륨 마운트, 디버깅을 위한 포트 개방
- 운영 환경: 보안 강화, 불필요한 포트 차단, 로그 관리
예를 들어 docker-compose.override.yml을 두어 로컬에서는 디버깅용 설정을 추가하고, 서버에서는 배포용 설정을 적용할 수 있습니다.
4. 배포 파이프라인(CI/CD) 구성하기
멀티 컨테이너 구성을 마쳤다면 이제 남은 과제는 자동 배포입니다. 개발자가 코드를 푸시할 때마다 자동으로 빌드, 테스트, 배포가 이루어지면 생산성이 크게 향상됩니다.
CI/CD 기본 흐름
- 코드 푸시 (GitHub, GitLab 등)
- CI 서버 (GitHub Actions, GitLab CI, Jenkins 등)이 Docker 이미지를 빌드
- 테스트 실행 (단위 테스트, 통합 테스트)
- 이미지 레지스트리에 푸시 (Docker Hub, AWS ECR 등)
- 운영 서버에서 pull & 재배포
GitHub Actions 예시
name: CI/CD Pipeline
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t myrepo/myapp:${{ github.sha }} .
- name: Login to DockerHub
run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Push image
run: docker push myrepo/myapp:${{ github.sha }}
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: SSH to server and deploy
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
docker pull myrepo/myapp:${{ github.sha }}
docker-compose down
docker-compose up -d
5. 실무에서의 고려사항
- 보안: 환경 변수 관리 시 .env 파일과 Secret Manager 활용
- 모니터링: Prometheus, Grafana, ELK 스택 연동
- 무중단 배포: Blue-Green Deployment, Rolling Update 전략 적용
- 스케일링: 필요하다면 Docker Swarm이나 Kubernetes로 확장 고려
마무리
멀티 컨테이너 구성은 현대 애플리케이션에서 사실상 필수적인 패턴입니다. Docker Compose를 통해 개발/운영 환경을 표준화하고, CI/CD 파이프라인까지 구축하면 프로젝트 생산성과 안정성이 크게 향상됩니다. 작은 사이드 프로젝트라도 초기부터 이 구조를 도입하면, 추후 확장과 협업이 훨씬 수월해집니다.
앞으로는 Compose에서 한 단계 나아가 Kubernetes 같은 오케스트레이션 도구로 확장하는 것도 고려할 수 있습니다. 그러나 그 출발점은 멀티 컨테이너와 Compose라는 점을 기억하면 좋겠습니다.
'백엔드' 카테고리의 다른 글
Django ORM, 이것만 알면 된다! 개념·종류·실습 올인원 가이드 (2) | 2025.08.21 |
---|---|
Django REST Framework 기초와 JWT 인증 이해하기 (1) | 2025.08.20 |
Django ORM 기초: 개념과 예제 (2) | 2025.06.20 |
Docker의 실무 활용 사례 및 사용법 (0) | 2025.06.09 |
Django 프로젝트의 settings.py 주요 설정과 활용법 (3) | 2025.06.04 |