소스를 마운트했더니 컨테이너 안 node_modules가 사라진 이유
문제 발생
개발용으로 소스를 바인드 마운트했더니 컨테이너가 뜨자마자 죽었습니다.
services:
app:
volumes:
- .:/app # 호스트 소스를 컨테이너로Error: Cannot find module 'express'이미지 빌드 때 분명히 pnpm install을 했는데 /app/node_modules가 비어 있었습니다.
원인 분석
마운트는 덮어쓰는 게 아니라 가립니다. Docker 문서가 동작을 정확히 적습니다 — 비어 있지 않은 볼륨을 파일이 있는 컨테이너 디렉터리에 마운트하면 기존 파일들은 마운트에 의해 가려집니다(obscured).
호스트의 프로젝트 디렉터리에는 node_modules가 없거나(있어도 OS·아키텍처가 다를 수 있습니다) 다른 내용입니다. 그것이 /app을 통째로 덮으면서, 이미지 안에 설치해둔 node_modules가 보이지 않게 된 것입니다.
반대 방향의 동작도 문서에 있습니다 — 비어 있는 볼륨을 내용이 있는 디렉터리에 마운트하면 그 파일·디렉터리가 기본적으로 볼륨으로 전파(복사)됩니다. 이름 있는 볼륨을 쓰면 첫 실행 때 이미지의 내용으로 채워진다는 뜻이고, 이번 문제의 해법이 여기서 나옵니다.
두 방식의 성격 차이도 정리돼 있습니다 — 볼륨은 Docker가 관리하며 호스트 머신의 핵심 기능과 격리되고 /var/lib/docker/volumes/ 아래에 저장되는 반면, 바인드 마운트는 호스트의 디렉터리 구조와 OS에 의존합니다.
해결 방안
node_modules만 이름 있는 볼륨으로 덮습니다. 소스는 바인드 마운트로 즉시 반영하고, 의존성은 컨테이너 것을 씁니다.
services:
app:
volumes:
- .:/app
- app_node_modules:/app/node_modules
volumes:
app_node_modules:-
의존성이 바뀌면 그 볼륨을 지웁니다. 첫 생성 때 채워진 내용이 계속 남으므로,
package.json이 바뀌면docker compose down -v나 해당 볼륨 삭제가 필요합니다 — 이걸 모르면 "설치했는데 반영이 안 된다"로 이어집니다. -
용도로 둘을 나눠 씁니다. 문서 권고대로 컨테이너와 호스트 양쪽에서 파일에 접근해야 하면 바인드 마운트(개발 중 소스), 그 밖에는 볼륨(DB 데이터, 업로드 파일)이 기본입니다.
-
데이터 볼륨은 백업 경로를 정합니다. 문서가 볼륨의 장점으로 드는 것이 백업·이관의 용이함인데, 실제로 백업 절차를 만들어두지 않으면 이점이 아닙니다.
-
권한을 함께 봅니다. 비root로 실행하는 컨테이너가 마운트된 디렉터리에 쓰려면 UID/GID가 맞아야 합니다.
-
운영 이미지에는 소스를 마운트하지 않습니다. 이 구성은 개발 편의를 위한 것이고, 운영에서는 이미지 안의 내용이 곧 배포 산출물이어야 합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.