ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 컨테이너에 있던 파일이 볼륨을 연결하자 사라진 이유
    Programming 2026. 10. 2. 07:49
    728x90
    반응형

    이미지 안 파일 위로 호스트 폴더가 연결되어 원래 경로를 가리는 층 그림
    bind mount가 이미지의 파일을 가리는 관계입니다. 삭제나 실제 파일 상태를 나타내는 화면은 아닙니다.

    Docker 이미지 안에는 분명 설정 파일이 있는데, ./workspace:/app을 연결한 뒤 /app이 비어 보입니다. 먼저 컨테이너의 Mounts에서 /app이 어느 호스트 경로를 가리키는지 확인하세요. 빈 호스트 폴더가 이미지 안의 파일을 가리고 있을 수 있습니다.

    /app에서 보이는 대상이 바뀝니다

    이미지를 만들 때 /app/config/default.json을 넣었다고 가정해 보겠습니다. 마운트 없이 시작한 컨테이너는 이미지의 그 경로를 읽습니다. 여기에 호스트의 빈 workspace 디렉터리를 /app으로 bind mount하면, 컨테이너가 /app에서 보는 내용은 workspace의 내용이 됩니다.

    기존 파일을 지우고 빈 폴더로 교체하는 복사 작업이 아닙니다. 마운트한 동안 원래 내용이 가려집니다. Docker 문서는 가려진 파일을 다시 확인하는 방법으로 해당 마운트 없이 컨테이너를 새로 만드는 방식을 안내합니다. 기존 데이터 위에 bind mount하기

    따라서 파일이 안 보인다는 이유로 이미지를 다시 빌드하기 전에 실행 설정부터 봐야 합니다. 새 이미지에도 똑같이 /app 마운트를 걸면 새로 넣은 파일 역시 가려집니다.

    아래 설명은 이 상황을 좁혀 보는 가상 예시입니다. 실행 중인 컨테이너를 지우거나 재생성하는 명령은 포함하지 않았습니다.

    실제 연결을 docker inspect로 읽습니다

    Compose 파일에 적힌 값만 보지 말고, 현재 컨테이너에 적용된 마운트를 확인합니다. 다음 명령의 my-app은 실제 컨테이너 이름으로 바꾸세요.

    docker inspect my-app \
      --format '{{json .Mounts}}'
    

    출력에서 우선 볼 값은 세 가지입니다.

    항목 이번 사례에서 확인할 값
    Type bind인지 volume인지
    Source 실제로 연결된 호스트 경로
    Destination 가려진 경로인 /app인지

    Source가 생각했던 프로젝트 폴더와 다르다면, 그 경로에 무엇이 있는지부터 확인합니다. 상대 경로가 다른 위치로 해석됐거나 잘못된 디렉터리를 연결했을 수 있습니다. 파일이 보여야 하는 위치를 찾는 데에는 “볼륨을 쓴다”는 설명보다 이 실제 경로가 더 유용합니다.

    원격 Docker daemon을 사용한다면 Source는 CLI를 실행한 노트북이 아니라 daemon이 있는 호스트의 경로입니다. Docker Desktop은 호스트 파일을 VM의 컨테이너와 공유하는 장치를 제공하지만, 임의의 원격 서버에 연결한 경우까지 같은 방식이라고 생각하면 안 됩니다. bind mount의 호스트 제약

    이미지와 연결 폴더를 따로 확인합니다

    이미지에 파일이 들어갔는지 확인하려면 같은 이미지로 마운트 없는 별도 검사 컨테이너를 만들 수 있습니다. 예를 들어 이미지에 /bin/sh와 ls가 들어 있는 경우 아래 형태로 살펴봅니다.

    docker run --rm --network none \
      --entrypoint /bin/sh \
      my-app:review \
      -c 'ls -la /app/config'
    

    my-app:review는 확인하려는 로컬 이미지로 바꿉니다. 이 명령은 별도 컨테이너에서 목록을 보고 그 검사 컨테이너만 정리합니다. 셸이 없는 이미지라면 이 예시를 그대로 실행할 수 없습니다. 검사 도구가 있는 이미지인지 먼저 확인해야 합니다.

    비교할 결과는 단순합니다. 마운트 없는 검사에서 파일이 있고, 실행 중인 컨테이너의 /app은 빈 호스트 폴더와 연결돼 있다면, 이미지 빌드 누락보다 마운트 구성을 고칠 근거가 됩니다. 반대로 검사 컨테이너에도 파일이 없다면 Dockerfile의 복사 대상이나 사용한 이미지 태그를 다시 살펴봐야 합니다.

    컨테이너 실행 중 따로 만든 파일은 이미지에 들어 있지 않을 수 있습니다. 이 검사는 이미지에 포함된 파일을 확인하는 과정입니다. 실행 중 생성한 데이터를 찾는 작업이라면 해당 컨테이너의 쓰기 계층과 기존 마운트 위치를 먼저 보존해야 합니다.

    전체 앱 대신 바뀌어야 하는 경로만 연결합니다

    가상 앱이 이미지의 /app에서 프로그램과 기본 설정을 읽고, 사용자가 수정하는 문서는 /workspace에서 읽도록 설계됐다고 합시다. 그렇다면 문서용 호스트 폴더를 /app에 연결할 이유가 없습니다.

    services:
      app:
        image: my-app:review
        volumes:
          - type: bind
            source: ./workspace
            target: /workspace
            read_only: true
    

    이 구성에서는 /app의 이미지 파일을 유지하고, 문서만 별도 경로에서 읽도록 앱 설정도 맞춥니다. 문서를 수정해야 하는 앱이라면 read_only 사용 여부는 달라집니다. 중요한 것은 데이터를 놓을 위치를 프로그램 위치와 구분하는 일입니다.

    기존 설정 파일 하나만 바꿔야 할 때에도 /app 전체를 가리는 대신, 앱이 지원하는 설정 경로에 필요한 파일만 연결하는 방식을 검토할 수 있습니다. 파일 마운트에서는 호스트 쪽 대상이 실제 파일인지도 확인하세요. 경로가 없을 때 -v가 디렉터리를 만들어 버리는 동작 때문에 파일을 기대한 자리에 디렉터리가 생길 수 있습니다. --mount는 기본적으로 없는 source 경로에 오류를 냅니다. 마운트 문법과 경로 생성 차이

    이름 있는 volume은 초기 동작이 다릅니다

    Compose의 volumes 항목 아래 있다고 모두 같은 저장 방식은 아닙니다. ./workspace:/app은 bind mount이고, app-data:/app 같은 이름 있는 volume은 Docker가 관리하는 저장 공간입니다.

    빈 volume을 기존 파일이 있는 컨테이너 경로에 처음 연결하면, 기본 동작으로 그 내용이 volume에 복사될 수 있습니다. volume-nocopy는 이 복사를 막는 옵션입니다. 이미 내용이 있는 volume을 연결하면 이미지 안 내용이 가려지는 점도 구분해야 합니다. volume의 기존 데이터와 초기 복사

    “빈 volume으로 바꾸면 해결”이라고 바로 결론내리면 초기 복사와 이후 데이터 보존 정책까지 바뀝니다. 지금 필요한 것이 호스트 파일 공유인지, 컨테이너 데이터의 영속 저장인지 먼저 정해야 합니다.

    파일이 사라졌다는 보고를 받으면 이미지 → 현재 Mounts → 실제 Source 순으로 대조해 보세요. 가려진 파일인지, 잘못된 이미지인지, 실행 중 다른 저장소에 만든 파일인지 구분한 다음에 실행 구성을 바꾸면 됩니다.

    자료 확인: 2026년 9월 28일, Docker 공식 문서. 본문 명령과 Compose 구성은 진단 방법을 설명하는 예시입니다.

    728x90
    반응형
Designed by Tistory.