試用予約を本番予約から分離する

DockerBeginner
オンラインで実践に進む

はじめに

STILL STUDIO は小さな陶芸ワークショップを開いています。参加者は講座を選んで枠を予約し、名簿で自分の名前を確認します。チームは Riverside Room の本番名簿の枠を使わずに、Garden Room の回を試したいと考えています。同じアプリに独立したステージング環境を用意します。試用であることを明示し、予約データを別に保存する Web サイトです。

基本的なターミナル操作ができれば十分です。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 を選んでホームに戻り、3 件の予約を保持してください。

同じ名前を誤って 2 回送ると、予約済みであることが示され、2 件目は追加されません。自分の名前を間違えた場合は Guest list を開き、誤った自分の予約の横だけで Cancel を選び、Live guest で予約し直します。Maria や Jun を取り消したり、1 つの誤字のために名簿全体を空にしたりしないでください。

設定の境界を読む

Workstation に切り替えます。既に /home/labex/project/booking にいます。パスはファイルやディレクトリを指定します。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 イメージを使います。各コンテナは作成時に独自の環境変数を受け取ります。名前付きボリュームは交換可能なコンテナの外にデータベースを保存します。異なるコンテナで 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 はアプリがコンテナ内で待ち受けるポートです。両サイトには別々の公開ポートが必要です。

サービスは booking-data を /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 のバージョンで異なります。コマンドの正常終了だけでなく、解決された値が証拠になります。

変数やファイルがないと表示されたら、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 を予約します。名簿は 3 人になり、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、本番の 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 を調べます。これで、1 つのアプリイメージ、独立設定の 2 つのプロセス、永続的に分離された 2 つの名簿が揃いました。これは単一インスタンスの訓練上の分離であり、Docker にアクセスできる管理者に対するセキュリティ境界ではありません。

まとめ

同じ予約アプリのステージングコピーを設定して起動し、別の名前付きボリュームを選び、実際の定員を試して両方の名簿を比較しました。試用コンテナを再作成しても予約が保たれ、本番の元の参加者も維持されました。別ラベルや Compose プロジェクトは整理に役立ち、実際のデータ保存先が分離を成立させました。