소개
Afterlight는 작은 커뮤니티 전시입니다. 방문자가 방명록 벽에 감상을 남기며, 애플리케이션을 교체해도 그 기여물이 사라지면 안 됩니다. 먼저 버려도 되는 복사본을 사용한 다음 실제 방명록의 기존 데이터를 다시 연결하여 새 메시지도 애플리케이션 교체 후 유지합니다.
기본적인 터미널 사용법만 알면 됩니다. Docker, Compose, 데이터 경로, 편집 및 HTTP는 필요할 때 설명합니다. 애플리케이션과 도구는 준비되어 있으며 데이터베이스 코드를 작성하지 않습니다. 방문자 정보는 모두 가상입니다.
명령은 Workstation, 실제 방명록은 Exhibition, 의도적인 데이터 손실 실험은 Practice Copy만 사용합니다. 두 웹사이트는 서로 다른 컨테이너와 포트를 사용합니다. 각 단원은 독립적으로 시작하며 웹사이트, 레이블과 출력은 영어로 유지됩니다.
방문자 데이터에 별도의 저장소 마련하기
이 단계에서는 전시를 이용하고, 버려도 되는 데이터의 손실을 관찰한 뒤 실제 방명록을 기존 기록에 연결합니다. Practice Copy에서 시작하세요. 실제 방문자가 없는 별도의 폐기 가능한 전시입니다.
정상적인 방문자 흐름 경험하기
About the exhibition을 열고 운영 시간을 읽은 뒤 The wall을 선택합니다. Leave a contribution을 선택하고 Your name에 Visitor, Your message에 A small practice note.를 입력한 뒤 Add to the wall을 선택합니다. 상세 페이지에 기여물이 표시됩니다. Back to the wall을 선택하면 카드가 보입니다. 상세 페이지와 양식은 보존해야 할 정상 업무 기능입니다.
컨테이너가 보존하지 않는 것 관찰하기
Workstation으로 전환합니다. 시작 디렉터리는 /home/labex/project/afterlight입니다. 경로는 파일이나 디렉터리를 가리킵니다. 이 절대 경로는 파일 시스템의 루트 /에서 시작합니다. pwd는 현재 디렉터리를 출력합니다.
pwd
Docker는 자체 파일 시스템 보기를 가진 프로세스인 컨테이너에서 애플리케이션을 실행합니다. 이미지는 준비된 애플리케이션 패키지입니다. afterlight:1 이미지에는 프로그램과 디자인이 있지만 나중에 방문자가 제출한 기여물은 없습니다. 컨테이너의 쓰기 가능한 계층에만 기록한 데이터는 그 컨테이너를 삭제하면 사라집니다.
폐기 가능한 연습 컨테이너만 제거합니다. docker rm은 컨테이너를 제거하며, 필요하면 -f가 먼저 중지합니다.
docker rm -f afterlight-scratch
docker run은 저장된 이미지에서 새 컨테이너를 생성합니다. -d는 백그라운드로 실행하고 --name은 이름을 지정합니다. 포트는 네트워크 서비스를 식별합니다. -p 8082:8081은 실습 환경의 포트 8082를 컨테이너 내부 애플리케이션 포트 8081로 전달합니다.
docker run -d --name afterlight-scratch -p 8082:8081 afterlight:1
긴 출력은 새 컨테이너 ID입니다. Practice Copy로 전환하고 The wall을 선택하여 새로 고칩니다. 연습 카드가 사라졌습니다. 이전 상세 URL을 계속 새로 고치지 마세요. 해당 기록은 더 이상 없습니다. 이 손실은 폐기 가능한 복사본에만 한정됩니다.
기존 방명록 데이터 연결하기
Exhibition으로 전환합니다. 빈 벽은 같은 애플리케이션을 사용하지만 현재 데이터 연결이 없습니다. 원래 방문자 Iris의 기록은 준비된 Docker 볼륨 afterlight_messages에 안전하게 보관되어 있습니다. 주요 작업은 이 데이터를 다시 연결하고 이후 기여물을 애플리케이션 교체 후에도 보존하는 것입니다.
이름 있는 볼륨은 특정 컨테이너 외부에서 Docker가 관리하는 저장소입니다. 마운트는 이 저장소를 애플리케이션 내부 경로에 연결합니다. 이 앱은 SQLite 데이터베이스를 /data/wall.sqlite3에 기록합니다. SQLite는 파일에 기록을 저장하므로 여기서는 SQL이나 애플리케이션 코드가 필요하지 않습니다.
Workstation으로 전환합니다. cat은 파일을 표시합니다.
cat compose.yaml
Compose는 이 YAML 설정을 읽어 서비스를 만듭니다. YAML은 공백 들여쓰기로 중첩 구조를 표현합니다. services는 애플리케이션을 묶고 wall은 이 서비스입니다. image, container_name, ports는 패키지, 이름과 네트워크 매핑을 설명합니다. environment는 애플리케이션 설정을 전달합니다. RELEASE는 표시 버전을 선택하며 두 버전의 데이터 형식은 같습니다.
마운트와 볼륨 선언을 추가합니다. messages:/data는 논리 볼륨 messages를 컨테이너 디렉터리 /data에 연결합니다. 최상위 선언은 기존 Docker 이름 afterlight_messages를 지정합니다. external: true는 새 볼륨을 만들지 않고 준비된 볼륨을 재사용하도록 Compose에 지시합니다. 이름이 틀리면 볼륨 없음 오류가 발생합니다. 이름을 수정하고 기존 볼륨을 삭제하거나 빈 대체 볼륨을 만들지 마세요. 저장소를 선언하기만 하고 서비스에 연결하지 않으면 데이터를 보호할 수 없습니다.
cat > compose.yaml은 이 설정을 교체합니다. 따옴표로 감싼 YAML은 here-document를 시작합니다. 마지막에 단독 줄로 있는 YAML까지 전체 블록을 붙여 넣으세요. 따옴표는 내용을 그대로 유지합니다. 공백은 예시와 동일하게 사용합니다.
cat > compose.yaml <<'YAML'
name: afterlight
services:
wall:
image: afterlight:1
container_name: afterlight-wall
ports:
- "8081:8081"
environment:
MODE: guestbook
RELEASE: "1"
volumes:
- messages:/data
volumes:
messages:
name: afterlight_messages
external: true
YAML
docker compose config -q는 설정을 조용히 검증합니다. 출력이 없으면 올바르게 해석한 것입니다. 오류가 나면 적용하기 전에 들여쓰기나 철자를 고치고 다시 확인합니다.
docker compose config -q
docker compose up -d는 파일에 맞게 서비스를 백그라운드에서 만들거나 교체합니다. 이름 있는 볼륨은 보존합니다. 명령이 끝날 때까지 기다리세요.
docker compose up -d
Exhibition으로 전환하고 The wall로 돌아가 새로 고칩니다. Iris의 **A beautiful place to pause.**가 보여야 합니다. Iris 카드를 열었다가 돌아옵니다. 실제 데이터베이스에서 기존 기록을 다시 연결한 것이며 시작할 때마다 새로 생성한 예시가 아닙니다.
새 기여물을 작성하고 저장 위치 확인하기
이 단계에서는 실제 기여물을 추가하고 화면 결과를 실제 마운트와 연결합니다. Exhibition에서 시작하며 Iris의 기존 카드를 보존합니다.
Leave a contribution을 선택합니다. Your name에 Mira, Your message에 정확히 The light stays with us.를 입력한 뒤 Add to the wall을 선택합니다. 상세 페이지에 두 값이 모두 표시되어야 합니다. Back to the wall을 선택하면 Iris와 Mira가 모두 있어야 합니다.
Workstation으로 전환합니다. docker inspect는 컨테이너의 실제 설정을 읽습니다. --format은 필드를 선택하고 작은따옴표는 중괄호를 그대로 전달합니다. 이 템플릿은 마운트 목록을 JSON으로 표시합니다.
docker inspect afterlight-wall --format '{{json .Mounts}}'
"Type":"volume", "Name":"afterlight_messages", "Destination":"/data", "RW":true를 찾습니다. RW는 읽기와 쓰기를 허용한다는 뜻입니다. 설정 파일의 이름은 의도를 나타낼 뿐이지만 여기에는 실행 중인 컨테이너의 실제 연결이 표시됩니다.
docker volume ls는 사용 가능한 볼륨을 나열합니다.
docker volume ls
다른 플랫폼 볼륨이 있을 수 있으므로 건드리지 마세요. 외부 볼륨 이름을 잘못 쓰면 Compose는 볼륨 없음 오류로 중지됩니다. 파일의 이름을 수정하여 다시 적용하고 빈 대체 볼륨은 만들지 마세요. 새 빈 볼륨을 실수로 연결했을 때 벽이 비었다고 해서 원래 기록이 삭제되었다는 뜻은 아닙니다. 기존 볼륨을 보존하고 compose.yaml의 이름을 afterlight_messages로 복원한 뒤 검증하여 다시 적용합니다. 볼륨 삭제를 문제 해결 지름길로 사용하지 마세요. docker compose down -v는 Compose가 관리하는 볼륨과 데이터를 삭제하지만 external: true로 선언된 볼륨은 보존합니다. 외부 볼륨을 수동으로 삭제해도 안전하다는 뜻은 아닙니다.
모든 데이터 종류 고려하기
하나의 기여물이 여러 디렉터리에 의존할 수 있습니다. 이 방명록은 /data에 텍스트를 저장합니다. 사진 벽은 업로드한 이미지 바이트를 /photos에도 저장하며 데이터베이스에는 각 설명과 연결된 파일 이름이 있습니다. 설명만 보존하면 이미지가 깨질 수 있습니다.
| 컨테이너 경로 | 내용 | 교체 후 보존 여부 |
|---|---|---|
/data |
방문자 기록 및 사진과 설명의 관계 | 보존 |
사진 벽의 /photos |
업로드한 사진 | 데이터베이스와 별도로 보존 |
/app |
이미지에 준비된 프로그램, 디자인 및 연습 샘플 | 제공된 이미지로 다시 생성 |
여러 데이터 디렉터리도 같은 마운트 구문을 사용합니다. 각 디렉터리마다 서비스 목록 항목과 볼륨 선언을 하나씩 추가합니다. 빈 볼륨을 /app에 마운트하면 프로그램이 가려지므로 하지 마세요. 캐시 파일이나 이미지에 포함된 파일이 자동으로 방문자 데이터가 되는 것은 아닙니다.
독립 챌린지는 사진 업로드 양식을 사용합니다. River와 Garden 링크는 제공된 PNG 연습 이미지를 컴퓨터로 다운로드합니다. 필요한 이미지를 저장하고 **Photograph (PNG)**에서 선택한 뒤 이름과 설명을 입력하여 Add to the wall을 제출합니다. 브라우저가 선택한 바이트를 보내므로 명령줄 업로드 도구는 필요하지 않습니다.
애플리케이션을 교체하고 전시 유지하기
이 단계에서는 애플리케이션을 edition 2로 교체하고 기존 두 기여물을 유지한 채 새 기여물을 받습니다. Workstation에서 시작합니다.
nano는 터미널 텍스트 편집기입니다. 설정을 엽니다.
nano compose.yaml
방향키로 RELEASE: "1"만 RELEASE: "2"로 바꿉니다. 마운트, 이미지 및 포트는 유지합니다. Ctrl+O, Enter로 저장하고 Ctrl+X로 종료합니다. 저장한 설정을 읽고 검증합니다.
cat compose.yaml
docker compose config -q
docker compose ps -q wall은 현재 컨테이너 ID를 출력합니다. 비교할 수 있도록 기억하거나 터미널 출력을 남기세요. 보고서는 필요하지 않습니다.
docker compose ps -q wall
버전 변경을 적용합니다. --force-recreate는 다른 설정이 같더라도 새 컨테이너를 요청합니다.
docker compose up -d --force-recreate
docker compose ps -q wall
ID는 달라야 합니다. 단순 재시작이 아니라 교체입니다. 시작이 실패하면 docker compose logs wall로 애플리케이션 메시지를 읽고 설정을 수정·검증한 뒤 up -d를 다시 실행합니다. 기존 볼륨을 보존하고 다른 컨테이너는 삭제하지 마세요.
Exhibition으로 전환하고 The wall을 선택해 새로 고칩니다. 바닥글에 Edition 2가 보여야 합니다. Iris와 Mira가 남아 있어야 합니다. 각 카드를 열었다가 돌아옵니다. 양식에 Leon과 정확히 Back for another look.를 입력하여 제출합니다. 벽으로 돌아오면 교체된 애플리케이션에서 세 기여물이 작동합니다.
데이터와 함께 서비스도 확인하기
Workstation으로 전환합니다. HTTP는 브라우저의 요청과 응답 프로토콜입니다. 상태 200은 성공한 응답, 404는 요청한 리소스를 찾지 못했음을 뜻합니다. 연결 실패는 서버 응답을 받지 못했다는 뜻입니다.
curl은 요청을 보냅니다. -sS는 진행률을 숨기지만 연결 오류는 표시하고, -o /dev/null은 응답 본문을 버립니다. -w는 따옴표 안의 형식을 출력합니다. %{http_code}는 상태이며 \n은 줄을 끝냅니다. Workstation에서 127.0.0.1은 이 실습 인스턴스이며 포트 8081은 Exhibition입니다. 실행합니다.
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/about
예상 결과는 200입니다. Exhibition에서 About the exhibition을 열어 운영 시간이 여전히 보이는지 확인한 뒤 The wall을 선택합니다. 성공 상태만으로 올바른 내용이나 기여물 보존을 입증할 수는 없습니다.
볼륨은 이번 컨테이너 교체로부터 데이터를 보호합니다. 독립 백업은 아니며 볼륨 삭제나 호스트 손실로부터 보호하지 않습니다. 애플리케이션 파일은 다시 만들 수 있게 유지하고 방문자 데이터는 별도로 저장하세요.
요약
버려도 되는 컨테이너 파일과 영구 방문자 데이터를 구분하고, 기존 이름 있는 볼륨을 연결하여 교체 후에도 기존 및 새 메시지를 보존했습니다. 새 기여물과 전시 페이지도 계속 작동합니다. 다음에는 같은 방법을 설명과 별도로 저장된 사진에 적용합니다.



