← 전체 글로 돌아가기

Docker

Docker Compose로 배포할 때 반복해서 밟는 실수들

포트 충돌, 볼륨 마운트, --build 누락까지, 개인 프로젝트를 Compose로 배포하면서 직접 겪은 실수를 정리했다.

개인 프로젝트를 VPS에 올릴 때 Docker Compose를 쓰면 편한데, 처음 몇 번은 꼭 같은 실수를 반복하게 된다. 그냥 놓쳐서 30분씩 날린 것들만 추려봤다.

코드를 바꿨는데 반영이 안 될 때

docker compose up -d만 치면 이미 빌드된 이미지를 그대로 쓴다. 코드를 수정했다면 반드시 --build를 붙여야 한다.

docker compose up -d --build

"아 분명히 고쳤는데 왜 안 바뀌지" 하고 로그 뒤지다 보면 대부분 이 문제다.

포트가 이미 쓰이고 있을 때

서버에서 다른 프로세스가 같은 포트를 쓰고 있으면 컨테이너가 뜨다가 죽는다. 오류 메시지가 꽤 장황하게 나와서 놓치기 쉬운데, 핵심은 address already in use다.

sudo ss -lntp | grep 3000

이걸로 어떤 프로세스가 포트를 잡고 있는지 먼저 확인한다. 의외로 이전에 수동으로 띄운 Node.js 프로세스가 남아 있는 경우가 많다.

환경변수가 컨테이너 안에 안 들어갈 때

docker-compose.ymlenv_file: .env를 써놨어도 .env 파일이 서버에 없으면 조용히 무시된다. 로컬에서 .gitignore로 제외한 걸 서버에 옮기는 걸 잊는 경우다.

컨테이너가 뜬 뒤에 환경변수가 제대로 들어갔는지 확인하는 방법:

docker compose exec app env | grep DATABASE_URL

볼륨 마운트가 예상과 다르게 동작할 때

개발용 docker-compose.yml에 소스 코드를 통째로 마운트해두는 경우가 있다.

volumes:
  - .:/app

이걸 그대로 운영 서버에서 쓰면 서버의 빈 디렉토리가 컨테이너 안의 파일을 덮어써버린다. 개발용과 운영용 Compose 파일을 분리하거나, 운영에서는 볼륨 마운트를 데이터 디렉토리에만 써야 한다.

depends_on만으로는 부족하다

depends_on:
  - db

depends_on은 컨테이너가 "시작됐는지"만 보지, DB가 실제로 쿼리를 받을 준비가 됐는지는 보지 않는다. 앱 컨테이너가 DB보다 먼저 연결을 시도해서 에러가 나고 죽어버리는 상황이 생긴다.

간단한 해결책은 앱 쪽에 재시도 로직을 두거나, Compose의 healthcheckcondition: service_healthy를 조합하는 것이다.

depends_on:
  db:
    condition: service_healthy

결국 Compose 자체는 단순한데, 로컬과 서버 환경 차이를 제대로 안 따지면 이런 데서 시간을 버리게 된다.