マウントした設定を保護する

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

はじめに

レポートサービスは設定を読み、文書を書き出す必要がありますが、現在の設定マウントは書き込みも許可しています。保守担当者として、レポート生成を壊さずに不要なアクセスを減らします。

まず正常なレポートを生成し、入力マウントを保護して、レポートコンテナだけを再作成します。基本的なターミナル操作ができれば十分です。Docker、マウント構文、編集操作は使用前に説明します。

正常なレポートを生成する

このステップでは、権限を変更する前に通常の業務処理を実行します。Harbor Books は小さなサービスで注文を集計し、文書を生成しています。顧客や数値はすべて研修用の合成データです。

Maintenance ターミナルを使用します。これは Docker の管理権限を持つ Linux ホストの保守用ロールです。Docker はコンテナ内でアプリケーションプロセスを起動します。各コンテナは独自のファイルシステムとプロセス一覧を参照しますが、ホストのカーネルを共有します。コンテナは別の VM ではありません。管理対象は report-renderer と /home/labex/project/report-desk のファイルだけです。

ターミナルはこのディレクトリから始まります。pwd は現在のディレクトリを表示します。

pwd

/home/labex/project/report-desk が表示されるはずです。移動していた場合は cd /home/labex/project/report-desk で戻ります。

アプリケーションはポート 8090 で待ち受けています。ポートはサービスを識別します。ここでの localhost は保守用ホストを意味し、Docker がそのポートをコンテナに転送します。curl は HTTP リクエストを送信し、-X POST は処理を依頼するリクエストを選択します。-fsS はエラーを表示し、成功時の出力を簡潔にします。基準となる文書を要求します。

curl -fsS -X POST http://localhost:8090/render/baseline
{"saved": "/output/baseline.json", "total": 37, "uid": 0}

サービスが入力を読み、実際のファイルを保存しました。cat はファイルを表示します。ホストではコンテナの /output がローカルの output ディレクトリとして見えます。

cat output/baseline.json

Report for Harbor Books: 37 orders を探してください。他のフィールドは入力の識別情報と稼働中のサービスインスタンスを記録しています。Document Desk を開いて更新すると、Stored documents に baseline.json が表示されます。このページは実際のファイル一覧であり、権限が安全であることの証明ではありません。

入力の起動定義を保護する

このステップでは、入力と出力のパスを対応付け、不要な書き込みを実演して起動定義を編集します。バインドマウントはホストのディレクトリをコンテナ内のパスに接続します。明示的に制限しなければ書き込み可能です。

cat launch.sh で用意された Bash 起動スクリプトを表示します。

cat launch.sh

バックスラッシュはコマンドを次の行へ継続します。sudo はホストの管理者権限で Docker を管理しますが、アプリケーションの実行ユーザーは決めません。docker run -d はコンテナをバックグラウンドで起動し、--name は名前を付け、--user 0:0 はユーザーとグループの ID を選びます。-p 8090:8090 はホストのポートをコンテナのポートに転送します。最後の引数は用意されたアプリケーションイメージ c12-renderer:1 です。

各 --mount のフィールドはカンマで区切ります。type=bind はホストのパスを接続し、src はそのホストパス、dst はコンテナ内のパスです。

ホストのディレクトリ コンテナのディレクトリ 必要なアクセス
report-desk/config /config バッチとテンプレートを読む
report-desk/output /output 生成した文書を書く

設定には、業務データを含まない使い捨てのサンプル probe.txt があります。docker exec は指定した稼働中のコンテナ内でコマンドを実行します。touch はサンプルのタイムスタンプを更新します。これは意図的に不要なアプリケーションアクセスを示す操作です。

sudo docker exec report-renderer touch /config/probe.txt

何も表示されなければ成功です。バッチやテンプレートを壊さずに、設定マウントが書き込み可能であることを確認できます。ホストの起動定義を変更すると、Docker が次に作成するコンテナに反映されます。現在のコンテナ内のファイルを編集しても、マウントモードは変わりません。

ターミナルエディター nano で定義を変更します。

nano launch.sh

矢印キーで移動します。dst=/config の行で、/config の直後、空白とバックスラッシュの前に ,readonly を追加します。/output は書き込み可能なままにしてください。Ctrl+O、Enter で保存し、Ctrl+X で終了します。設定のマウント行は次のようになります。

  --mount type=bind,src=/home/labex/project/report-desk/config,dst=/config,readonly \

再度 cat launch.sh を表示し、カンマやバックスラッシュの抜けを確認します。誤字は nano launch.sh を開き直して修正できます。稼働中のコンテナはまだ古いマウントを使っています。次のステップで置き換えます。

マウント境界を適用してテストする

このステップではレポートコンテナだけを置き換え、入力への書き込みを拒否しつつ出力が機能することを確認します。起動スクリプトを変えても既存コンテナは更新されません。

docker rm -f は指定コンテナを停止して削除します。バインドマウントされたホストのディレクトリは残ります。bash launch.sh は編集した定義を実行します。

sudo docker rm -f report-renderer
bash launch.sh

2 つ目のコマンドは新しいコンテナ ID を表示します。起動まで少し待ちます。構文やマウントのエラーが出たら、nano launch.sh で該当行を直し、同じ削除コマンドで新しく作られた report-renderer を削除して、スクリプトを再実行します。ホストのデータディレクトリは削除しないでください。

docker inspect は実際のコンテナ設定を読みます。--format はフィールドを選びます。シェルが中括弧を変更せず渡せるよう、シングルクォートを保ちます。

sudo docker inspect report-renderer --format '{{json .Mounts}}'

"Destination":"/config" に "RW":false、/output に "RW":true があることを確認します。RW は読み書きを意味します。同じサンプルで実際の境界を確認します。

sudo docker exec report-renderer touch /config/probe.txt
touch: /config/probe.txt: Read-only file system

このゼロ以外の終了は想定どおりです。ターミナルは引き続き使えるので、次のコマンドへ進みます。接続エラーやコンテナの不在は別の問題で、起動スクリプトの修正や再実行が必要です。

再作成したサービスに新しい文書を要求します。

curl -fsS -X POST http://localhost:8090/render/final
{"saved": "/output/final.json", "total": 37, "uid": 0}
cat output/final.json

文書には引き続き Report for Harbor Books: 37 orders が含まれます。Document Desk を更新して final.json を確認します。サービスは入力を読み、出力を書けますが、設定マウントへの書き込みは拒否されます。まだ root で動作しています。次の独立したラボで、その別の権限を扱います。

まとめ

実際のレポートを生成し、ホストとコンテナのパスを対応付け、入力マウントを読み取り専用にしてサービスを再作成しました。実際のマウント情報と書き込み拒否で保護を確認し、新しいレポートで正常な出力が維持されたことを確認しました。