最初のコンテナを立ち上げる
このラボは本物のVM上で動きます
この環境はPodではなく、KubeVirtが起動した仮想マシンです。Linuxカーネルが別に動き、systemdが実際にサービスを管理し、dockerは模倣ではなく本物のDockerエンジンです。docker runで起動したコンテナは実際にプロセスになり、docker execもdocker logsもそのまま動作します。
以前はこのラボがPodの中で動いていました。カーネル権限をすべて落とした環境だったため、コンテナを起動するステップが塞がれており、イメージアーカイブを自分で展開してみるという回り道で学んでいました。もう回り道は必要ありません。
知っておくべきことが2つあります。
- 最初の起動に1分ほどかかります。VMが起動してDockerをインストールするためです。Podのラボ(通常40秒)より遅くなります。
- ブラウザープレビューはありません。VMへの接続は、採点用のポート1つしか開いていません。Webサーバーを起動した場合は、VMの中で
curlを使って確認してください。
目標
イメージとコンテナを手で操作しながら、タグがイメージをコピーしないことと、コンテナの内側と外側では見えるファイルツリーが違うことを自分で確認します。
なぜ重要なのか
コンテナに初めて触れると、ほとんどの人はコマンドを暗記しようとします。しかし実務でつまずくのはコマンドではなく、モデルです。「イメージを削除したのにコンテナが生きている」「タグを変えたのに容量が減らない」「コンテナ内にはファイルがあるのにホストにはない」。これらはすべて、イメージは読み取り専用のレイヤーの山であり、コンテナはその上の書き込みレイヤー+プロセスであるという1つの文で説明できます。そのため、このラボはコマンドを覚えるのではなく、その文を目で確かめる過程です。
ステップ
/root/dk1ディレクトリを作成し、この環境で使えるイメージの一覧を/root/dk1/images.txtとして保存します。リポジトリとタグが一緒に見える必要があります。docker imagesはこの環境では動作しません。代わりに、/opt/images/*.tarの中のindex.jsonから.manifests[0].annotations["org.opencontainers.image.ref.name"]を読むと、docker.io/library/alpine:3.20のような名前:タグがそのまま得られます。docker imagesのRepositoryとTagの2列がどこから来るのかを、1段下の層から見ることになります。alpine:3.20イメージでdk-helloという名前のコンテナを作成してhello-labhubを出力させ、終了後もコンテナを残しておきます。nginx:1.27-alpineをdk-webという名前でバックグラウンド実行します。nginx:1.27-alpineコンテナから見える/etc/os-releaseを読み、/root/dk1/web-os.txtとして保存します。docker exec dk-web cat /etc/os-releaseで読みます。このVMの/etc/os-releaseをそのまま読むとUbuntuが表示されて失敗します。その違いこそが、マウントネームスペースの働きです。dk-webのコンテナIPアドレスを調べ、/root/dk1/web-ip.txtにIPv4アドレスを1行だけ保存します。alpine:3.20にlabhub/base:v1という名前をもう1つ付けます。dk-helloコンテナを削除します。dk-webはそのままにします。/root/dk1/report.txtに、次の3行を実際の値で埋めて書き込みます。
image=<dk-web 이 쓰는 이미지 이름:태그>
container=dk-web
state=<dk-web 의 현재 상태>
(プレースホルダーは、dk-webが使うイメージの名前:タグと、dk-webの現在の状態です)
参考
docker images --format '{{.Repository}}:{{.Tag}}'で、必要な列だけを取り出せます。docker inspect <이름> | jq -r '.[0].State.Status'のようにJSONを直接掘り下げるほうが確実です(プレースホルダーはコンテナ名です)。- よくある間違い1: ステップ2で
--rmを付けると、コンテナがすぐに消えてしまい、採点する対象がなくなります。 - よくある間違い2: ステップ4でホストの
/etc/os-releaseを読むと、Ubuntuが表示されます。コンテナの内部で読む必要があります。
イメージ一覧を保存する
/root/dk1ディレクトリを作成し、この環境で使えるイメージの一覧を/root/dk1/images.txtとして保存します。リポジトリとタグが一緒に見える必要があります。
docker imagesはこの環境では動作しません。代わりに、/opt/images/*.tarの中のindex.jsonから.manifests[0].annotations["org.opencontainers.image.ref.name"]を読むと、docker.io/library/alpine:3.20のような名前:タグがそのまま得られます。docker imagesのRepositoryとTagの2列がどこから来るのかを、1段下の層から見ることになります。
イメージの一覧を表示するサブコマンドがあります。出力を画面で読むだけで終わらせず、リダイレクトでファイルに残してください。リポジトリ名だけでなく、タグの列まで一緒に残す必要があります。
1回実行して終わるコンテナ
alpine:3.20イメージでdk-helloという名前のコンテナを作成してhello-labhubを出力させ、終了後もコンテナを残しておきます。
名前を付けておくと、あとで探しやすくなります。--rmを付けると終わった直後に削除され、採点する対象がなくなる点に注意してください。
バックグラウンドで動き続けるコンテナ
nginx:1.27-alpineをdk-webという名前でバックグラウンド実行します。
フォアグラウンドで起動すると、ターミナルが占有されてしまいます。コンテナを切り離して起動するフラグがあります。nginxは終了せず、動き続けているのが正常です。
実行中のコンテナ内でコマンドを実行する
nginx:1.27-alpineコンテナから見える/etc/os-releaseを読み、/root/dk1/web-os.txtとして保存します。
docker exec dk-web cat /etc/os-releaseで読みます。このVMの/etc/os-releaseをそのまま読むとUbuntuが表示されて失敗します。その違いこそが、マウントネームスペースの働きです。
ホストで/etc/os-releaseを読むと、Ubuntuが表示されます。コンテナのマウントネームスペースの中で読むと、Alpineが表示されます。
コンテナのIPを調べる
dk-webのコンテナIPアドレスを調べ、/root/dk1/web-ip.txtにIPv4アドレスを1行だけ保存します。
inspectの出力はJSONです。jqで掘り下げるか、--formatテンプレートを使ってください。ファイルにはIPアドレスだけを残す必要があります。
イメージに別の名前を付ける
alpine:3.20にlabhub/base:v1という名前をもう1つ付けます。
タグはイメージをコピーしません。新しい名前を付けたあと、2つの名前のイメージIDを比べてみてください。
終了したコンテナだけを片付ける
dk-helloコンテナを削除します。dk-webはそのままにします。
終了したコンテナも、書き込みレイヤーを保持し続けます。実行中のものは残し、終わったものだけを削除する必要があります。
現在の状態をレポートにする
/root/dk1/report.txtに、次の3行を実際の値で埋めて書き込みます。
3行とも、実際のinspectの値と照合されます。推測で書かず、コマンドで確認した値を書いてください。