Docker & System Architecture 가이드·약 5분 내외

Docker Compose 프로젝트 충돌 원인과 완벽한 환경 분리(Dev/Prod) 가이드

서버 재시작 시 일부 도커 컨테이너가 유실되는 원인을 프로젝트 이름 충돌 관점에서 분석하고, Dev와 Prod 환경을 완벽히 분리하는 방법을 알아봅니다.

Q1. 서버 재시작 후 특정 컨테이너들만 유실되거나 Created 상태에 멈춰있는 이유는 무엇인가요?

이는 `docker-compose.yml` 파일 하나를 로컬 개발(Dev)과 서버 운영(Prod)에서 동시에 공유하며 발생한 프로젝트 이름 충돌(Project Name Conflict) 때문입니다.

충돌 발생 원리

도커 데몬이 기존에 띄워져 있던 로컬 개발용 DB 컨테이너(`quizzer-db`)를 살려놓은 상태에서, 서버 데몬(`systemd`)이 `quizzer-prod`라는 프로젝트 이름으로 전체 컨테이너를 다시 띄우려 시도합니다.
이때 DB 컨테이너 이름(`quizzer-db`)이 중복되어 충돌(Conflict) 에러가 발생합니다.
이 에러로 인해 전체 실행 프로세스가 중간에 중단(Abort)되어 나머지 앱 컨테이너들이 생성조차 되지 않거나 껍데기(Created)만 남게 된 것입니다.

Q2. 로컬 스크립트(package.json)의 프로젝트 이름을 서버(prod)와 똑같이 맞추면, 알아서 충돌이 해결되나요?

아닙니다! 스크립트 수정은 미래의 충돌을 예방하는 조치일 뿐입니다.

이미 도커 데몬에는 서로 다른 프로젝트 소속으로 꼬여버린 컨테이너 찌꺼기들이 남아있습니다. 이들은 스크립트를 수정한다고 자동으로 삭제되지 않습니다.

반드시 1회 수동으로 `docker compose down`을 호출하여 꼬인 기존 컨테이너 잔여물들을 깨끗하게 청소한 뒤 서비스를 재시작해야만 정상 구동됩니다.

Q3. 왜 서버(Prod) 도커를 실행할 때 DB(Postgres, Redis)를 따로 실행해야 했나요? IJM은 어떻게 되어 있나요?

서버(Prod)를 실행할 때 DB를 따로 띄워야 한다는 것은 흔한 오해입니다! 실제 운영 서버는 `docker compose up -d` 한 번으로 앱과 DB 등 모든 컨테이너를 한꺼번에 띄웁니다.

따로 띄우는 스크립트(`pnpm infra`)는 오직 로컬에서 편하게 코딩하기 위해 앱은 직접 돌리고 DB만 도커로 띄우려는 목적으로 만들어진 개발자 편의용 스크립트입니다.

IJM 프로젝트의 모범 사례

IJM 프로젝트는 애초에 `docker-compose.dev.yml`(개발용)과 `docker-compose.prod.yml`(서버용) 파일을 분리했습니다. 컨테이너 이름도 `dev-postgres`처럼 다르게 지어 애초에 두 환경이 충돌할 일이 없도록 안전하게 설계되어 있습니다.

Q4. 이런 충돌을 근본적으로 해결하려면 구조를 어떻게 바꿔야 하나요?

IJM의 모범 사례처럼 목적에 따라 설정 파일을 물리적으로 쪼개야 합니다.

실천 방안

1. 기존 `docker-compose.yml`을 `docker-compose.prod.yml`로 이름 변경하여 프로덕션 전용으로 만듭니다.

2. DB만 들어있는 `docker-compose.dev.yml`을 새로 생성하고, 컨테이너 이름(예: `dev-db`)을 차별화합니다.

3. 무중단 배포 스크립트(`deploy.sh`)와 Systemd 서비스 파일이 명시적으로 `-f docker-compose.prod.yml`을 바라보도록 옵션을 추가합니다.

가이드 모음

다른 가이드도 확인해보세요

이정마 프로젝트의 다양한 가이드와 꿀팁들을 확인하실 수 있습니다.