
배포 스크립트가 새 태그를 체크아웃하고 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로 설정 유효성을 한 번 확인
설정을 고친 게 반영됐는지는 파일이 아니라 실행 중인 프로세스를 기준으로 봐야 했다.
'Infra' 카테고리의 다른 글
| [Prometheus] Docker 컨테이너 자원 cgroup v2 직독 cAdvisor 대체 (0) | 2026.06.25 |
|---|---|
| [nginx] OpenResty 채택 이유 유효 API 키 rate-limit 면제 (0) | 2026.06.25 |
| [Grafana] 무트래픽 구간 spanNulls 보간 제거 rate 0 채움 (0) | 2026.06.25 |
| [Langfuse] Self-Hosted v3: ClickHouse 서버 리소스 최적화 (0) | 2026.02.09 |
| [Proxmox] 랜섬웨어 방어 및 재해 복구(DR) 전략 (0) | 2025.11.29 |