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.yml에 env_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의 healthcheck와 condition: service_healthy를 조합하는 것이다.
depends_on:
db:
condition: service_healthy
결국 Compose 자체는 단순한데, 로컬과 서버 환경 차이를 제대로 안 따지면 이런 데서 시간을 버리게 된다.