시험 예약과 운영 예약 분리하기

DockerBeginner
지금 연습하기

소개

STILL STUDIO는 작은 도예 워크숍을 운영합니다. 참석자는 워크숍을 선택해 자리를 예약하고 명단에서 이름을 확인합니다. 팀은 Riverside Room의 운영 명단에 있는 자리를 차지하지 않고 Garden Room 회차를 시험하려 합니다. 동일한 앱에 별도의 스테이징 환경을 만들어 시험용임을 명확히 표시하고 예약 데이터를 분리합니다.

기본 터미널 사용에 익숙하면 충분합니다. Docker Compose, 설정, 경로, 포트와 데이터 볼륨은 여기서 설명합니다. 앱과 이미지는 제공되므로 앱 코드를 작성하거나 도구를 설치하지 않습니다. 모든 예약은 가상입니다. 이메일, 결제, 외부 계정이나 실제 개인 정보는 사용하지 않습니다.

포트 8081의 준비된 사이트는 Live Bookings, 포트 8082의 스테이징 사이트는 Preview Bookings, 명령은 Workstation을 사용합니다. Preview Bookings는 2단계에서 시작하기 전까지 사용할 수 없습니다. 이 단원은 독립적으로 시작합니다.

업무를 이해하고 미리 보기 설정하기

이 단계에서는 정상 예약 흐름을 이용한 다음 별도 설정값을 준비합니다. Live Bookings에서 시작하세요.

정상 서비스에서 자리 예약하기

스튜디오의 운영 워크숍

홈페이지는 도예 워크숍을 소개하며 LIVE BOOKINGS, Riverside Room, 4 of 6 places left를 표시합니다. Explore the clay workshop을 선택하세요. 워크숍 페이지에는 회차 설명과 Guest name 입력란이 있습니다. 가상 이름 Live guest를 입력한 다음 Reserve a place를 선택하세요.

브라우저가 Guest list를 열고 Maria, Jun, Live guest를 보여 줍니다. 남은 자리는 3 of 6 places left가 됩니다. 장식용 성공 메시지가 아니라 실제 데이터베이스 쓰기입니다. STILL STUDIO를 선택해 홈으로 돌아가세요. 세 예약을 모두 유지하세요.

같은 이름을 실수로 두 번 제출하면 사이트가 이미 예약되었다고 설명하며 두 번째 예약을 추가하지 않습니다. 자신의 이름을 잘못 입력했다면 Guest list를 열고 잘못 만든 자신의 예약 옆에서만 Cancel을 선택한 다음 Live guest로 다시 예약하세요. Maria나 Jun을 취소하거나 오타 하나를 고치려고 전체 명단을 비우지 마세요.

설정의 경계 읽기

이미 /home/labex/project/booking에 있는 Workstation으로 전환하세요. 경로는 파일이나 디렉터리를 나타냅니다. pwd는 현재 디렉터리를 출력하고 ls는 그 안의 항목을 나열합니다.

pwd
/home/labex/project/booking
ls

compose.yaml과 live.env가 보여야 합니다. cat은 텍스트 파일을 출력합니다.

cat live.env
PORT=8081
APP_ENV=live
VENUE=Riverside Room
CAPACITY=6
DATA_VOLUME=still-live-data

설정은 코드를 바꾸지 않고 앱에 선택값을 제공합니다. 이 KEY=value 행은 공개 포트, 환경 표시, 장소, 정원과 데이터 볼륨을 선택합니다. VENUE는 사이트 전체에 표시되는 실제 워크숍 장소를 바꿉니다. CAPACITY는 단순한 표시가 아니라 수락하는 예약 수를 제한합니다.

Docker는 저장된 이미지에서 만든 컨테이너 안에서 앱을 실행합니다. 두 사이트 모두 제공된 still-booking:1 이미지를 사용합니다. 각 컨테이너는 생성될 때 자신만의 환경 변수를 받습니다. 이름 있는 볼륨은 교체 가능한 컨테이너 밖에 데이터베이스를 저장합니다. 서로 다른 컨테이너가 볼륨을 공유할 수 있으므로 컨테이너 이름이 다르다는 사실만으로 기록이 분리되지는 않습니다.

준비된 자원은 다음과 같습니다.

자원 용도
still-live-data Maria와 Jun의 원래 예약이 있는 운영 데이터베이스
still-trial-data 이번 미리 보기를 위해 준비한 빈 데이터베이스 자원

볼륨 이름은 실제 저장소를 선택합니다. 시험 예약에 운영 볼륨을 선택하지 마세요.

작은 Compose 파일 이해하기

Docker Compose는 관련 컨테이너를 YAML 파일로 설명합니다. YAML은 들여쓰기로 설정을 묶습니다. 제공된 간격을 유지하고 탭 대신 공백을 사용하세요. 제공된 파일을 읽습니다.

cat compose.yaml

services 아래의 booking은 still-booking:1을 사용합니다. environment 부분은 앱에 값을 전달합니다. ${VENUE}는 컨테이너를 만들기 전에 Compose가 VENUE라는 값을 대입한다는 뜻입니다. 환경 파일은 이 대입의 입력이며 이미 실행 중인 프로세스를 자동으로 바꾸지는 않습니다.

ports는 ${PORT}:8000을 연결합니다. 콜론 앞은 실습 인스턴스의 공개 포트이고, 8000은 컨테이너 안에서 앱이 수신하는 포트입니다. 두 사이트에는 서로 다른 공개 포트가 필요합니다.

서비스는 앱이 데이터베이스를 저장하는 /data에 booking-data를 마운트합니다. 최상위 볼륨 항목은 이 별칭을 ${DATA_VOLUME}으로 해석합니다. external: true는 볼륨이 이미 존재하며 Compose가 바로 그 자원을 사용해야 한다는 뜻입니다. 프로젝트 이름은 Compose 컨테이너를 묶지만 명시적으로 선택한 외부 볼륨의 이름을 바꾸지 않습니다.

미리 보기 값을 작성하고 해석하기

live.env는 그대로 두세요. 아래 값으로 preview.env를 만듭니다. cat > preview.env는 해당 파일을 교체합니다. 따옴표로 감싼 ENV는 here-document의 시작입니다. 마지막 ENV가 단독으로 놓인 줄까지 전체 블록을 붙여 넣으세요. 따옴표는 내용을 문자 그대로 보존합니다.

cat > preview.env <<'ENV'
PORT=8082
APP_ENV=staging
VENUE=Garden Room
CAPACITY=3
DATA_VOLUME=still-trial-data
ENV

포트는 네트워크 서비스를 식별합니다. 여기서 8082는 Preview Bookings이며 8081은 계속 Live Bookings입니다. APP_ENV=staging은 눈에 띄는 시험 표시를 켭니다. 이 값 자체가 별도 저장소를 고르지는 않습니다. 저장소 선택은 DATA_VOLUME의 역할입니다.

--env-file preview.env는 Compose가 대입할 값을 지정합니다. -p still-preview는 프로젝트를 선택합니다. config는 컨테이너를 시작하거나 바꾸지 않고 해석된 설정을 출력합니다.

docker compose --env-file preview.env -p still-preview config

APP_ENV: staging, VENUE: Garden Room, 정원 3, 공개 포트 8082, 볼륨 이름 still-trial-data를 찾으세요. 형식은 Compose 버전에 따라 다릅니다. 명령의 정상 종료만이 아니라 해석된 값이 근거입니다.

Compose가 변수나 파일이 없다고 하면 pwd와 cat preview.env를 확인하고 전체 here-document를 다시 실행해 철자를 고친 다음 config를 반복하세요. 셸이 VENUE 같은 변수를 이미 내보냈다면 그 값이 파일보다 우선할 수 있습니다. unset VENUE는 해당 셸 재정의를 제거합니다. 자신이 의도적으로 내보낸 충돌 키에만 같은 방법을 쓰세요. 해석된 값이 올바르기 전에는 미리 보기를 시작하지 마세요.

미리 보기를 시작하고 실제 정원 시험하기

이 단계에서는 스테이징 복사본을 시작하고 예약이 별도 명단을 사용함을 확인합니다. Workstation에서 시작하세요.

설정한 앱 시작하기

up은 프로젝트의 컨테이너를 만들거나 업데이트합니다. -d는 터미널을 사용할 수 있도록 백그라운드에서 계속 실행합니다.

docker compose --env-file preview.env -p still-preview up -d

출력에는 생성된 컨테이너 이름이 나옵니다. ps는 프로젝트의 실제 상태와 공개 포트를 보여 줍니다.

docker compose --env-file preview.env -p still-preview ps

실행 중인 booking 서비스와 8000에 연결된 포트 8082를 찾으세요. 시작이 실패하면 logs가 앱 메시지를 출력합니다.

docker compose --env-file preview.env -p still-preview logs

외부 볼륨을 사용할 수 없다는 오류는 대개 자원 이름의 오타입니다. preview.env를 고치고 config, up -d를 다시 실행하세요. 잘못된 대상을 숨기려고 대체 볼륨을 만들지 마세요. 포트 충돌은 대개 운영 포트를 선택했다는 뜻입니다. 8081을 보존하고 이번 미리 보기에는 8082를 사용하세요.

시험 예약하기

Preview Bookings로 전환하고 필요하면 새로 고침하세요. 홈페이지에는 STAGING · TEST BOOKINGS ONLY, Garden Room, 3 of 3 places left가 보여야 합니다. Explore the clay workshop을 선택하고 Trial guest를 입력한 다음 Reserve a place를 누르세요. Guest list에는 이제 Trial guest만 있고 2 of 3 places left가 표시됩니다.

Live Bookings로 전환해 Guest list를 선택하고 새로 고침하세요. 여전히 Maria, Jun, Live guest가 있고 3 of 6 places left여야 합니다. 시험 데이터가 여기 나타나면 시험 예약을 중단하세요. Workstation에서 미리 보기 볼륨을 고쳐 up -d를 적용한 다음 운영 명단에서 명확히 식별되는 자신의 시험 기록만 취소하세요. 정상 운영 예약은 모두 보존하세요. 분리를 고친 뒤 Preview Bookings를 열어 그곳에 Trial guest를 만드세요.

독립적인 미리 보기 참석자 명단

이 비교는 환경 표시보다 중요합니다. staging 표시가 있어도 데이터베이스를 공유하면 실제 자리를 차지합니다.

더 작은 정원 시험하기

Preview Bookings에 머무르세요. Back to the workshop을 따라 Capacity A를 예약합니다. 다시 워크숍으로 돌아가 Capacity B를 예약합니다. 이제 명단에 세 명이 있고 0 of 3 places left가 표시됩니다.

Overflow guest를 하나 더 예약해 보세요. 페이지에 **Every place is taken.**과 **No booking was added.**가 나타나야 합니다. View the guest list에서 Overflow guest가 없는지 확인하세요. 작은 정원이 실제 앱 동작을 바꾼 것입니다.

Capacity A와 Capacity B만 취소하고 Trial guest는 보존하세요. 미리 보기는 2 of 3 places left로 돌아옵니다. 이름을 잘못 입력했다면 그 시험 기록만 취소하고 반복하세요. 데이터베이스를 비울 필요는 없습니다. Live Bookings로 돌아가 운영 명단과 남은 자리가 그대로인지 확인하세요.

기계가 읽을 수 있는 결과 비교하기

Workstation으로 전환하세요. HTTP는 브라우저가 사용하는 요청과 응답 프로토콜입니다. curl은 요청을 보내고 -sS는 진행 표시를 숨기되 연결 오류는 보여 줍니다. Workstation에서 127.0.0.1은 이 실습 인스턴스입니다. URL은 프로토콜, 주소, 포트와 자원 경로로 구성됩니다. /api/info는 실제 설정과 데이터베이스 명단을 구조화된 텍스트 형식인 JSON으로 반환합니다. 데이터베이스 질의 언어는 필요하지 않습니다.

curl -sS http://127.0.0.1:8081/api/info

live, Riverside Room, 정원 6, 남은 자리 3과 운영 참석자 세 명의 이름을 읽으세요. ID는 달라질 수 있습니다.

curl -sS http://127.0.0.1:8082/api/info

staging, Garden Room, 정원 3, 남은 자리 2와 유일한 Trial guest를 읽으세요. 같은 명단에 붙인 두 표시가 아니라 서로 다른 엔드포인트입니다.

예약을 잃지 않고 미리 보기 교체하기

이 단계에서는 미리 보기 컨테이너를 교체하고 별도 데이터가 유지되는지 확인합니다. Workstation에서 시작하세요.

실제 저장소 마운트 점검하기

ps -q는 프로젝트의 컨테이너 ID만 출력합니다. docker inspect는 컨테이너의 실제 설정을 읽습니다. --format은 필드 하나를 선택하며 따옴표 안의 템플릿은 마운트 목록을 JSON으로 바꿉니다. 셸 표현식 $(...)는 안쪽 명령을 실행하고 출력을 컨테이너 인수로 넣습니다.

docker inspect $(docker compose --env-file preview.env -p still-preview ps -q booking) --format '{{json .Mounts}}'

종류가 volume, 이름이 still-trial-data, 대상이 /data인 마운트를 찾으세요. 이 마운트가 still-live-data라면 프로젝트 이름이 달라도 운영 데이터가 보호되지 않습니다.

미리 보기 컨테이너만 다시 만들기

--force-recreate는 설정이 바뀌지 않아도 컨테이너를 교체하도록 up에 지시합니다. 마운트한 이름 있는 볼륨은 유지됩니다. 설정이 새 프로세스에 전달되는 방식도 보여 줍니다. 환경 파일만 편집해서는 실행 중인 컨테이너가 업데이트되지 않습니다.

docker compose --env-file preview.env -p still-preview up -d --force-recreate

ps에 실행 중인 서비스가 나타날 때까지 기다리세요.

docker compose --env-file preview.env -p still-preview ps

Preview Bookings로 전환해 Guest list를 새로 고침하세요. Garden Room에 Trial guest가 남고 2 of 3 places left여야 합니다. Live Bookings로 전환해 명단을 새로 고침하세요. Riverside Room에 Maria, Jun, Live guest가 남고 3 of 6 places left여야 합니다. 컨테이너 교체나 시험 예약 때문에 다른 환경이 비워져서는 안 됩니다.

복구 방법으로 볼륨 삭제나 down -v를 사용하지 마세요. 미리 보기가 시작되지 않으면 같은 프로젝트의 logs를 읽고 값을 고쳐 up -d를 다시 적용하세요. 준비된 운영 환경은 변경 범위 밖입니다.

페이지와 응답을 함께 확인하기

Preview Bookings에서 STILL STUDIO를 선택하고 워크숍과 Guest list를 차례로 여세요. 로컬 삽화, 상세 내용과 탐색이 계속 작동해야 합니다. 홈페이지 하나가 정상이라고 전체 예약 서비스가 정상인 것은 아닙니다.

Workstation으로 전환하세요. HTTP 상태 200은 정상 응답, 404는 요청한 경로가 없다는 뜻입니다. -o /dev/null은 응답 본문을 버리고 -w는 따옴표 안 형식을 출력합니다. %{http_code}는 HTTP 상태이며 \n은 출력 줄을 끝냅니다.

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/bookings

200을 예상하고 브라우저에서도 올바른 명단을 확인하세요. 잘못된 페이지가 담긴 200은 성공이 아닙니다.

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/workshop

200을 예상하세요. 운영 워크숍을 계속 사용할 수 있습니다. 연결 실패는 HTTP 오류 응답과 다릅니다. 서버 응답이 없으면 ps와 logs를 점검하세요. 이제 앱 이미지 하나, 독립적으로 설정한 프로세스 두 개와 지속되는 별도 명단 두 개가 있습니다. 단일 인스턴스 훈련용 분리이며 Docker 접근 권한을 가진 관리자에 대한 보안 경계는 아닙니다.

요약

동일한 예약 앱의 스테이징 복사본을 설정하고 시작했으며 별도 이름 있는 볼륨을 선택해 실제 정원을 시험하고 두 명단을 비교했습니다. 미리 보기를 다시 만들어도 예약이 유지되었고 운영 서비스는 원래 참석자를 보존했습니다. 다른 표시나 Compose 프로젝트는 정리에 도움이 되었으며 실제 데이터 대상이 분리를 만들었습니다.