소개
The Common Archive는 PostgreSQL에 이웃 지역의 기록 네 개를 보관합니다. 참조 사이트는 작동하지만 새 아카이브는 데이터베이스가 연결을 받을 수 있기 전에 카탈로그 가져오기를 시도했습니다. 실행 중인 컨테이너와 사용 가능한 데이터베이스를 구분하여 첫 시작을 안정적으로 만드세요.
기본 Docker, 컨테이너 로그, 공개 포트, 터미널 경로를 알고 있어야 합니다. 이 실습에서는 YAML 관계, 작은 Compose 파일, 데이터베이스 상태 검사, 의존성 조건을 배웁니다. SQL, PostgreSQL 관리, 애플리케이션 코딩은 필요하지 않습니다. 완성된 데이터베이스 이미지, importer, 웹사이트, 데이터가 제공됩니다.
Workstation, Reference Archive, Your Archive, Collection Notes를 사용하세요. 모든 자료는 합성한 교육용 기록입니다. 의도적인 데이터베이스 및 가져오기 지연은 시작 상태를 눈으로 볼 수 있게 하며 실제 운영 시간에 대한 주장이 아닙니다. 읽기와 일반적인 실수를 포함해 약 45분을 예상하세요. 이는 저자의 예상 시간입니다.
사용 가능한 데이터베이스 기다리기
이 단계에서는 작지만 완전한 애플리케이션의 의존성 하나를 수정합니다. 설정을 교체하기 전에 관찰 내용을 차례로 확인하세요.
정상 아카이브 사용하기
Reference Archive에서 시작하세요. Search the collection과 Search로 Market morning을 검색합니다. 같은 제목의 레코드 두 개가 있지만 서로 다른 이야기를 담고 있습니다. 둘 다 열어 ID, 연도, 분류를 확인하고 Download transcript를 사용하세요. Back to collection으로 돌아가 검색을 지우고 Ferry voices를 살펴봅니다. 다운로드는 완료 표시가 아닌 데이터베이스 레코드의 실제 텍스트입니다.
Your Archive로 전환하세요. 카탈로그가 실행 중이 아니라고 설명하며 참조 서비스를 빌려 쓰지 않습니다. Collection Notes는 환영 서비스가 데이터베이스 행을 읽지 않으므로 이미 작동합니다. 컨테이너가 Up이라고 해서 카탈로그가 완전하다고 볼 수는 없습니다.
실제 실패한 시작 읽기
참조 컬렉션에는 레코드 네 개가 있으며 Market morning 두 항목은 서로 다른 식별값을 가집니다.

Workstation으로 전환하세요. 시작 위치는 /home/labex/project/archive-startup입니다. 필요하면 cd로 그 폴더로 돌아갑니다. cat은 파일을 표시합니다.
cd /home/labex/project/archive-startup
cat compose.yaml
Compose는 YAML을 읽습니다. 들여쓰기는 각 서비스의 속성을 묶습니다. 탭이 아닌 공백을 사용하세요. services: 아래의 네 항목은 다음과 같습니다.
| 서비스 | 실제 작업 | 성공 상태 |
|---|---|---|
db |
PostgreSQL이 레코드를 저장 | 실행 중이며 TCP 연결을 수락 |
importer |
단일 트랜잭션으로 제공된 CSV를 가져옴 | 상태 0으로 종료 |
catalog |
레코드와 녹취록 검색 및 제공 | 가져오기 성공 후 실행 |
welcome |
데이터베이스를 읽지 않고 Collection Notes를 제공 | 가져오기 전에 실행 가능 |
image는 준비된 이미지를 선택합니다. entrypoint는 제공된 프로그램을 시작하며 수정하지 않습니다. environment는 프로그램에 이름 있는 설정을 전달합니다. PGHOST, PGUSER, PGPASSWORD, PGDATABASE는 클라이언트에 사용할 데이터베이스와 교육용 계정을 알려 줍니다. 이 제한된 범위의 자격 증명은 실습용으로 제공됩니다. POSTGRES_*는 새 데이터 저장소에 그 계정을 준비합니다. 인증을 변경하거나 다른 데이터베이스로 대체하지 마세요.
data 볼륨은 이 프로젝트의 데이터베이스 파일을 보관합니다. 상대 경로 ./scenario는 제공된 입력 폴더를 importer에 읽기 전용으로 바인드하며 :ro가 이를 표시합니다. 데이터베이스도 제공된 첫 시작용 교육 지연 스크립트를 읽습니다. 공개 포트 8090:8080은 Your Archive를 catalog에 연결합니다. 환영 페이지는 별도 포트를 사용합니다. Compose 프로젝트는 리소스를 묶으며, 아래의 -p archive는 항상 학습자 아카이브를 대상으로 합니다. 참조 서비스는 다른 프로젝트와 볼륨을 사용합니다.
ps -a는 중지되었거나 한 번도 시작하지 않은 컨테이너도 포함합니다. logs는 실제 출력을 읽습니다.
docker compose -p archive ps -a
docker compose -p archive logs db importer
데이터베이스는 결국 준비되었다고 하지만 importer는 이미 연결에 실패했습니다. 데이터베이스가 나중에 준비되어도 실패한 가져오기가 자동으로 다시 실행되지는 않습니다. catalog는 제공된 의존성이 이미 importer의 성공을 기다리므로 시작되지 않은 상태로 남습니다.
PostgreSQL은 최종 TCP 리스너를 시작하기 전에 잠시 임시 초기화 서버를 사용합니다. 로컬 Unix 소켓만 검사하면 다른 컨테이너가 사용하기에는 너무 일찍 준비되었다고 판단할 수 있습니다. pg_isready는 서버가 연결을 받는지 알려 주지만 자격 증명이나 카탈로그 내용의 정확성은 증명하지 않습니다.
다음 읽기 전용 프로브는 의도적으로 잘못된 TCP 포트를 사용합니다. exec는 db에서 프로브를 실행하고, -T는 터미널 할당을 끄며, -h는 주소, -p는 포트, -U/-d는 제공된 사용자/데이터베이스를 지정합니다. 포트 6543에는 서버가 없으므로 no response가 표시되고 프로브 명령 자체가 종료 상태 2를 반환할 것으로 예상하세요.
docker compose -p archive exec -T db pg_isready -h 127.0.0.1 -p 6543 -U archivist -d archive
이는 프로브 실패이며 카탈로그 데이터 손실이 아닙니다. 최종 데이터베이스는 일반 TCP 포트 5432에서 수신합니다. 상태 검사는 그 실제 서비스를 대상으로 해야 합니다.
준비 상태 표현 및 새 데이터로 시작하기
애플리케이션 설정과 제공된 파일을 변경하지 마세요. db에 실제 healthcheck를 추가하고 importer의 데이터베이스 조건을 service_started에서 service_healthy로 바꾸세요. test는 Docker가 데이터베이스 컨테이너 내부에서 실행하는 명령입니다. JSON 형태의 배열은 CMD로 셸 없이 지정한 프로그램을 직접 실행합니다. -h 127.0.0.1은 최종 TCP 리스너를 선택하며 기본 포트는 5432입니다. interval: 1s, timeout: 2s, retries: 40은 준비되었다고 가정하는 고정 대기가 아니라 제한 시간이 있는 반복 프로브를 제공합니다.
catalog의 service_completed_successfully 조건은 유지됩니다. 성공한 일회성 가져오기는 0으로 종료하며 Running 상태를 유지할 필요가 없습니다. 실패하면 catalog를 차단해야 합니다. 환영 페이지는 가져온 데이터가 필요하지 않으므로 가져오기 의존성이 없습니다.
다음 리터럴 히어 도큐먼트는 들여쓰기를 재현할 수 있도록 전체 설정을 씁니다. cat은 줄을 제공하고, >는 compose.yaml만 교체하며, 따옴표로 감싼 COMPOSE 표시는 닫는 줄까지 셸 확장을 막습니다. 다른 애플리케이션 설정은 모두 보존합니다.
cat > compose.yaml <<'COMPOSE'
services:
db:
image: dk04-postgres:16
environment:
POSTGRES_USER: archivist
POSTGRES_PASSWORD: training-archive
POSTGRES_DB: archive
TRAINING_DB_DELAY: "8"
volumes:
- data:/var/lib/postgresql/data
- ./scenario/slow-init.sh:/docker-entrypoint-initdb.d/10-training-delay.sh:ro
healthcheck:
test: ["CMD", "pg_isready", "-h", "127.0.0.1", "-U", "archivist", "-d", "archive"]
interval: 1s
timeout: 2s
retries: 40
importer:
image: dk04-archive:1
entrypoint: ["python3", "-B", "/app/importer.py"]
environment:
PGHOST: db
PGUSER: archivist
PGPASSWORD: training-archive
PGDATABASE: archive
TRAINING_IMPORT_DELAY: "6"
volumes:
- ./scenario:/scenario:ro
depends_on:
db:
condition: service_healthy
catalog:
image: dk04-archive:1
entrypoint: ["python3", "-B", "/app/archive.py", "catalog"]
environment:
PGHOST: db
PGUSER: archivist
PGPASSWORD: training-archive
PGDATABASE: archive
ARCHIVE_TITLE: "The Common Archive"
ports:
- "8090:8080"
depends_on:
importer:
condition: service_completed_successfully
welcome:
image: dk04-archive:1
entrypoint: ["python3", "-B", "/app/archive.py", "notes"]
environment:
ARCHIVE_TITLE: "The Common Archive"
ports:
- "8091:8080"
volumes:
data:
labels:
labex.course: dk04
COMPOSE
런타임 리소스를 변경하기 전에 설정을 해석해 보세요.
docker compose -p archive config
YAML이 실패하면 보고된 줄을 읽고 공백을 사용하여 표시된 블록을 복원한 뒤 다시 해석하세요. 잘못된 파일을 반복해서 재시작하지 마세요.
이제 빈 과정 데이터 저장소로 첫 시작을 테스트합니다. 이는 소스 CSV나 참조 아카이브가 아닌, 본인의 일회용 교육 데이터베이스만 의도적으로 삭제합니다. 먼저 실제 볼륨 라벨을 확인하세요.
docker volume inspect archive_data --format '{{json .Labels}}'
com.docker.compose.project가 archive이고 labex.course가 dk04인지 확인하세요. 하나라도 다르면 다른 리소스를 삭제하지 말고 멈춰서 프로젝트를 확인합니다. down --volumes는 이름으로 지정한 이 Compose 프로젝트의 컨테이너, 네트워크, 선언된 데이터 볼륨만 제거합니다.
docker compose -p archive down --volumes
up -d는 서비스를 백그라운드에서 시작합니다. --pull never는 준비된 이미지를 사용하고 --no-build는 새 빌드로 대체하는 것을 방지합니다.
docker compose -p archive up -d --pull never --no-build
docker compose -p archive ps -a
docker compose -p archive logs importer
healthy 데이터베이스, Exited 0인 importer, Running 상태인 catalog와 환영 페이지를 예상하세요. 제공된 첫 시작 지연과 가져오기 지연은 명시적인 교육용입니다. Compose 파일의 고정 sleep은 실제 준비 상태나 가져오기 성공을 대체하지 못합니다. 이전 시도가 실패한 컨테이너를 남겼다면 로그를 확인하고 설정을 수정하고 과정 볼륨 라벨을 확인한 뒤 이 범위의 새 데이터 시작을 반복하세요.
완성된 카탈로그 사용하기
Your Archive로 전환하여 새로고침합니다. Market morning을 검색하면 ID, 연도, 분류, 이야기가 서로 다른 두 레코드가 나와야 합니다. 각각 열어 Download transcript를 사용하고 Back to collection으로 돌아오세요. Ferry를 검색하고 Ferry voices를 열어 녹취록을 다운로드합니다. 검색을 지워 네 레코드 전체를 표시하세요. The shared garden과 그 다운로드도 살펴봅니다. 알 수 없는 레코드 URL은 연결 실패나 사용할 수 없는 카탈로그와 구별되는 Record not found를 표시해야 합니다.
Collection Notes로 전환하세요. 독립적인 환영 페이지가 계속 이용 가능해야 합니다. Reference Archive도 원래의 전체 컬렉션을 계속 제공해야 합니다. 최종 아카이브를 실행해 두세요. 검사는 먼저 실제 데이터베이스, 완료된 가져오기, 전체 업무 결과를 관찰합니다. 그다음 공개된 교육 지연 값을 다르게 하고 잘못된 가져오기 샘플을 사용하여 별도의 일회용 새 데이터 저장소에서 변경하지 않은 상태/의존성 선택을 실행합니다. 이 fixture들은 실제 아카이브를 초기화하거나 수정하지 않습니다. 별도의 격리 테스트는 데이터베이스 서버가 전혀 없는 상태에서 변경하지 않은 상태 명령도 실행합니다. 이 명령은 사용할 수 없는 엔드포인트를 거부해야 합니다.
요약
데이터베이스 컨테이너의 시작과 최종 TCP 준비 상태를 구분하고, 실제 상태 검사를 설정하여 importer가 이를 기다리도록 했습니다. 새 데이터 저장소에는 소비 서비스가 열리기 전에 전체 카탈로그가 들어갔으며 독립적인 안내 페이지는 계속 사용할 수 있었습니다.



