Infra

[Docker] bind-mount 설정 미반영 원인 force-recreate

jykim23 2026. 6. 25. 20:33
반응형

배포 스크립트가 새 태그를 체크아웃하고 docker compose up -d nginx로 nginx를 올린다. 호스트 디스크의 설정 파일은 분명히 새 내용으로 바뀌었는데, 실제 요청은 계속 404가 났다.

무슨 일이 있었나

설정은 bind-mount로 컨테이너에 연결돼 있었다. 디스크의 파일을 바꾸면 컨테이너 안에서도 같은 파일이 보이니, 당연히 반영될 거라고 생각했다.

그런데 docker compose up -d는 컨테이너 spec이 바뀌었을 때만 재생성한다. bind-mount된 파일의 내용이 바뀐 것은 spec 변경이 아니다. 이미지 태그도, 환경변수도, 볼륨 정의도 그대로니까 compose 입장에선 "바뀐 게 없는" 컨테이너다. 그래서 재기동을 건너뛰고, 실행 중이던 nginx 워커는 처음 켜질 때 읽은 설정을 그대로 들고 있었다.

확인

추측만으로는 답답해서 두 가지를 비교했다.

  • nginx가 켜진 시각보다 설정 파일 mtime이 더 나중이었다. 즉 파일이 바뀐 뒤로 재기동된 적이 없다.
  • nginx -T로 디스크의 설정을 덤프하면 바뀐 location이 보이는데, 실제로 동작하는 워커에는 그 location이 없었다.

디스크와 실행 중인 프로세스가 서로 다른 설정을 보고 있던 셈이다.

정리한 방식

배포 시 nginx만 강제로 재생성하도록 바꿨다.

# 변경 전
docker compose up -d --no-deps nginx

# 변경 후
docker compose up -d --no-deps --force-recreate nginx
docker compose exec -T nginx nginx -t   # 기동 후 설정 유효성 확인

--force-recreate는 컨테이너를 다시 만들면서 (1) 호스트 파일을 다시 바인딩하고 (2) entrypoint의 envsubst 같은 렌더링을 다시 돌리고 (3) 새 워커를 새 설정으로 띄운다.

설정의 일부(snippets)만 바뀐 경우라면 nginx -s reload로 graceful reload만 해도 된다. 다만 템플릿 + envsubst로 통째로 렌더되는 단일 파일이 바뀌는 경우엔 reload만으로는 부족해서, 경우를 나누지 않고 recreate로 통일했다. nginx는 무상태라 재생성해도 끊김이 1초 정도다.

정리

  • bind-mount 파일의 내용 변경은 docker compose up -d의 재생성 조건이 아니다
  • 설정을 바꿨는데 안 먹으면 --force-recreate로 컨테이너를 다시 만든다
  • 디스크 설정과 실제 적용 설정이 다른지 의심되면 nginx -T로 덤프해서 비교
  • 재기동 뒤 nginx -t로 설정 유효성을 한 번 확인

설정을 고친 게 반영됐는지는 파일이 아니라 실행 중인 프로세스를 기준으로 봐야 했다.

 
반응형