개요
Docker 컨테이너를 사용하다 보면 가끔 당황스러운 상황을 마주하게 됩니다. 열심히 저장했던 데이터가 컨테이너를 재시작한 후 사라져있거나, 로컬에서 찾을 수 없는 경우입니다. 왜 이런 현상이 발생하는 걸까요❓
이번 포스팅에서는 간단한 Node.js 애플리케이션을 통해 Docker 컨테이너의 파일 시스템 특성을 알아보고, 데이터가 사라지는 이유와 그 원리를 자세히 살펴보겠습니다.
특히 컨테이너와 이미지의 관계, 그리고 컨테이너가 왜 격리된 환경으로 동작해야 하는지를 이해할 수 있을 것입니다.
애플리케이션 세팅
이번 포스팅에서 사용할 간단한 애플리케이션은 다음과 같이 동작합니다.
웹 페이지에서 제목과 내용을 입력받아 텍스트 파일로 저장하는 Node.js 애플리케이션입니다. 제목은 파일명이 되고, 저장된 파일은 '/feedback/파일명.txt' 경로로 접근할 수 있습니다.
1. 이미지 생성
docker build -t feedback-node .
먼저 "docker build" 명령어를 사용하여 간단한 node 애플리케이션을 도커화 시켜보겠습니다.
태그를 지정하지 않았기 때문에 기본값인 "latest"가 태그로 자동으로 지정됩니다.
이제 이미지를 만들었으니 이 이미지를 기반으로 컨테이너를 시작할 수 있습니다.
2. 컨테이너 실행
docker run -p 3000:80 -d --name feedback-app --rm feedback-node
run 명령어로 컨테이너를 시작하고, 확인해보면 정상적으로 실행되었습니다.
도커 외부 포트를 3000번으로 지정했기 때문에 3000번 포트로 들어가보면 애플리케이션을 확인할 수 있습니다.
컨테이너의 파일 시스템 이해하기
먼저 애플리케이션의 동작을 테스트해보겠습니다. 웹 페이지에서 다음과 같이 데이터를 입력하고 저장해보겠습니다.
- Title : ZINU
- Document Text : My name is ZINU!
위와 같이 폼 데이터를 작성해고 "Save"버튼을 눌러 저장합니다.
제목이 파일명으로 저장되므로, "/feedback/zinu.txt" 경로로 접속하면 저장한 내용을 확인할 수 있습니다.
로컬 머신의 feedback 폴더를 보면 웹에서는 접근이 가능하던 zinu.txt 파일을 찾을 수 없습니다.
이는 Dockerfile의 COPY 명령어로 인한 결과입니다. COPY 명령어는 로컬 폴더를 이미지 내부로 복사하고, 컨테이너는 이 이미지를 기반으로 실행됩니다. 따라서 컨테이너는 자체적인 파일 시스템을 가지게 되며, 로컬 환경과는 완전히 격리됩니다.
이러한 격리성은 Docker의 핵심 특징입니다. 만약 컨테이너 내부에서 생성된 파일이 로컬 폴더에 직접 저장된다면, 이는 오히려 Docker의 격리 원칙에 위배됩니다.
컨테이너 생명주기와 데이터 지속성
이제 컨테이너의 생명주기에 따른 데이터 지속성을 살펴보겠습니다
먼저 --rm 옵션을 사용하여 컨테이너를 실행한 경우를 보겠습니다. 이 옵션은 컨테이너가 중지될 때 자동으로 삭제되도록 합니다. 컨테이너를 중지하고 다시 "/feedback/zinu.txt"에 접속해보면 파일이 존재하지 않는 것을 확인할 수 있습니다.
이번에는 --rm 명령어를 사용하지 않고 컨테이너를 시작해보겠습니다.
- Title : Park
- Document Text : Hello!
위와 같이 입력을 하고, 접속해보면 정상적으로 작동을 하고있습니다. 이제, stop 명령어로 컨테이너를 중지하고 다시 start해보겠습니다.
이번에는 컨테이너를 중지(stop)하고 다시 시작(start)해도 데이터가 그대로 유지됩니다. 이는 컨테이너를 중지만 했을 뿐 삭제하지는 않았기 때문입니다.
Docker의 읽기 전용 이미지와 컨테이너 레이어 구조
파일 시스템의 동작 방식을 더 자세히 살펴보겠습니다.
컨테이너는 중지했다가 다시 시작하면 이전 상태가 그대로 유지됩니다. 하지만 컨테이너를 완전히 제거(remove)하면 데이터가 모두 사라지게 됩니다. 이런 현상이 발생하는 이유는 Docker의 레이어 구조에 있습니다.
Docker 이미지는 읽기 전용(Read-only)으로 구성되어 있으며, 컨테이너가 실행될 때는 이 이미지 위에 읽기-쓰기(Read-write) 레이어가 추가됩니다.
이러한 구조로 인해, 컨테이너가 제거되면 변경되지 않은 이미지만 남게 됩니다. 새로운 컨테이너를 시작하면, 이전 컨테이너의 변경사항과 완전히 독립된 깨끗한 상태로 시작하게 됩니다. 이것이 바로 이 글에서 강조하고자 하는 핵심입니다.
"동일한 이미지에 기반한 다수의 컨테이너가 서로에게 완전히 격리된다."
즉, Docker에서 새로 생성되는 데이터는 읽기 전용인 이미지가 아닌 컨테이너의 읽기-쓰기 레이어에 저장됩니다. 그렇기 때문에 컨테이너를 삭제하면 이 읽기-쓰기 레이어도 함께 삭제되어 데이터가 사라지게 되는 것입니다.
이러한 구조는 Docker의 '격리성'이라는 핵심 원칙을 잘 보여주지만, 동시에 데이터 영속성 측면에서는 한계가 있습니다. 다음 포스팅에서는 이 문제를 해결할 수 있는 'Volume' 개념에 대해 알아보도록 하겠습니다.
'DevOps > Docker' 카테고리의 다른 글
[Docker] 도커 바인드 마운트란 무엇일까❓: 데이터 저장과 실시간 공유 (0) | 2025.01.07 |
---|---|
[Docker] Docker 컨테이너 데이터 관리: 익명 볼륨 vs 명명된 볼륨 (0) | 2025.01.06 |
[Docker] Docker에서 컨테이너와 이미지 식별을 위한 이름 및 태그 활용 알아보기 (0) | 2024.12.30 |
[Docker] Docker cp로 컨테이너 ↔ 로컬 간 파일 복사하기 (0) | 2024.12.29 |
[Docker] Docker 컨테이너의 실행 모드: Attach vs Detach (0) | 2024.12.26 |