Compose 파일을 다른 폴더로 옮긴 뒤 서비스가 처음 설치한 것처럼 보인다면, 데이터를 삭제했다고 결론 내리기 전에 현재 컨테이너가 연결한 볼륨 이름부터 확인하세요. 파일 내용이 같아도 프로젝트 이름이 달라지면 다른 named volume을 만들 수 있습니다. 반대로 볼륨 이름을 명시했거나 bind mount를 사용했다면 원인을 다르게 조사해야 합니다.
폴더 이름과 데이터의 관계는 프로젝트 이름을 거칩니다
Compose 프로젝트 이름은 여러 서비스와 네트워크·볼륨을 묶는 기준입니다. 명령의 -p, COMPOSE_PROJECT_NAME, Compose 최상위 name, 프로젝트 디렉터리 이름 등의 순서로 정해집니다. 기본 디렉터리는 첫 Compose 파일 위치이며 --project-directory로 달라질 수 있습니다. 따라서 폴더를 옮겼다는 사실만으로 프로젝트 이름이 바뀌었다고 단정하지 말고 실제 실행 옵션부터 확인해야 합니다.
기본 named volume 선언이 data:라면 이번 실험에서는 프로젝트에 따라 followup-a_data와 followup-b_data가 만들어졌습니다. 컨테이너 안의 경로는 둘 다 /data였습니다. 애플리케이션이 보는 경로가 같다는 사실은 같은 저장소라는 증거가 아닙니다.
두 프로젝트와 더미 파일로 확인했습니다
2026-09-13, 운영 서버와 다른 Linux 개발 호스트에서 Docker Engine 28.3.3, Compose 2.39.4, BusyBox 1.37.0을 사용했습니다. 전용 Docker daemon, 외부 네트워크 없는 컨테이너, 새 실험 볼륨만 사용했습니다. 폴더 이동 자체를 실행한 시험은 아닙니다. -p로 프로젝트 이름만 바꿔서 다른 저장소가 연결되는 원인을 분리했습니다.
services:
app:
image: busybox:1.37.0
network_mode: none
command: ["sleep", "300"]
volumes: ["data:/data"]
volumes:
data: {}
다음 명령은 더미 데이터만 있는 별도 실험 환경에서 사용하는 순서입니다. 운영 프로젝트나 이미 쓰는 이름을 대상으로 실행하지 마세요. 표준 Docker CLI 표기로 정리했으며 실제 실행 기록은 전용 socket을 지정한 실행기를 사용했습니다.
docker compose -p followup-a up -d
docker compose -p followup-b up -d
docker compose -p followup-a exec -T app sh -c 'printf synthetic-marker > /data/marker'
docker compose -p followup-a exec -T app cat /data/marker
docker compose -p followup-b exec -T app cat /data/marker
docker volume inspect followup-a_data
docker volume inspect followup-b_data
docker compose -p followup-a exec -T app cat /data/marker
| 확인 | 실제 결과 | 해석 |
|---|---|---|
| A에서 읽기 | 종료 0, synthetic-marker | A 볼륨에 파일이 있음 |
| B에서 같은 경로 읽기 | 종료 1, 파일 없음 | B 볼륨에는 그 파일이 없음 |
| 실제 Mounts | A: followup-a_data, B: followup-b_data | 연결한 저장소 이름이 다름 |
| Compose project label | followup-a / followup-b | 각 볼륨의 프로젝트 소속이 다름 |
| A에서 다시 읽기 | 종료 0, synthetic-marker | B의 실패가 A 데이터 삭제를 뜻하지 않음 |
B의 읽기 실패는 예상한 관찰이며 실험을 성공한 것처럼 숨기지 않았습니다. B에서 파일이 안 보이는 동안에도 A는 같은 파일을 읽었습니다. 이 결과는 다른 볼륨 연결 사례를 보여 주지만 실제 DB 손상이나 앱 초기화, 권한 오류까지 구분한 시험은 아닙니다.
운영에서는 만들기 전에 연결 대상을 읽습니다
처음 보는 빈 볼륨에 앱이 새 데이터를 쓰기 시작했다면 조사를 서두르면서 양쪽 데이터를 섞지 마세요. 먼저 실제 컨테이너 ID와 볼륨 이름, 생성 시점, 이전 실행 옵션을 비공개로 기록합니다. 아래는 조회 명령이며 ACTUAL_CONTAINER_ID와 ACTUAL_VOLUME_NAME을 확인된 값으로 바꿉니다.
docker inspect ACTUAL_CONTAINER_ID --format '{{json .Mounts}}'
docker volume inspect ACTUAL_VOLUME_NAME --format '{{json .Labels}}'
docker compose ls
Mounts의 Type, Name, Source, Destination을 함께 봅니다. 경로와 라벨에도 내부 정보가 있을 수 있으므로 전체 출력을 공개하지 않습니다. 이전 볼륨이 발견돼도 운영 DB를 두 컨테이너에 동시에 연결하지 마세요. 쓰기를 멈출 수 있는 시간, 앱 버전 호환성, 백업과 실제 복원 가능성을 먼저 확인한 뒤 원래 연결로 되돌릴지 데이터를 옮길지 결정합니다.
모든 볼륨이 폴더 이름에 묶이는 것은 아닙니다
볼륨에 명시적인 name:을 지정하면 그 이름은 프로젝트 접두사 없이 사용됩니다. external: true인 볼륨은 Compose가 외부에서 준비된 볼륨을 참조하며, 없으면 오류를 냅니다. bind mount는 호스트 경로를 연결하므로 상대 경로의 기준이 바뀌었는지 조사해야 합니다. 이런 예외는 공식 문서와 대조한 범위이며 이번 A/B 실험에서 모두 재현한 것은 아닙니다.
프로젝트 이름을 고정하는 것만으로 데이터 복원이 끝나지 않습니다. 프로젝트가 바뀌면 네트워크나 컨테이너 이름도 달라질 수 있고, 새 볼륨에 이미 쓴 데이터는 이전 볼륨에 자동 합쳐지지 않습니다. 무엇이 남아 있고 무엇이 새로 생겼는지 확인한 뒤 해당 서비스의 정상 절차로 조치해야 합니다.
실험 후에는 A/B 컨테이너를 내리고, 이번에 만든 두 더미 볼륨만 이름을 지정해 제거했습니다. 운영 볼륨이나 전체 정리 명령은 사용하지 않았습니다. 실제 서비스에서 볼륨 삭제는 진단 단계가 아닙니다. 데이터가 사라져 보일 때의 첫 질문은 “지웠는가”보다 “지금 어디를 읽는가”입니다.
근거와 확인 범위
Docker 프로젝트 이름 우선순위, Compose volume name·external을 2026-09-13 대조했습니다. A/B의 값과 종료 코드는 별도 개발 환경에서 실제 실행한 결과입니다. 실제 DB 복구, 기본 폴더 이름 변경, bind mount와 외부 볼륨 조합은 미실험입니다.