はじめに
この実験では、docker debugコマンドや関連技術を使用して Docker コンテナとイメージを効果的にデバッグする方法を探求します。まず、シェルが存在しないスリムなコンテナのデバッグというチャレンジに取り組み、その環境内で直接コマンドを実行する方法を実演します。
続いて、コンテナとして実行される前のスリムイメージを直接デバッグする方法を学びます。また、デバッグ目的で実行中のコンテナ内のファイルを修正する方法や、installおよびuninstallコマンドを使用してデバッグツールボックスを管理する方法についても解説します。最後に、entrypointコマンドを活用してコンテナのエントリーポイントをより深く理解します。
シェルなしスリムコンテナのデバッグ
このステップでは、シェルがインストールされていないスリムコンテナをデバッグする方法を学びます。スリムコンテナはイメージサイズと攻撃対象領域を削減するためによく使用されますが、問題が発生した際のデバッグが難しい場合があります。
まず、メッセージを表示して終了する単純なスリムコンテナを実行してみましょう。非常に小さな Linux ディストリビューションであるalpineイメージを使用します。
docker run alpine echo "Hello from Alpine!"
ターミナルにHello from Alpine!と表示されるはずです。これでコンテナが正常に実行されたことが確認できます。
次に、docker execを使用してこのコンテナ内でコマンドを実行してみましょう。一般的なシェルである/bin/shを実行してみます。
docker run -d --name slim-container alpine sleep 3600
docker exec -it slim-container /bin/sh
/bin/shが見つからないというエラーメッセージが表示されるでしょう。これはデフォルト設定のalpineイメージにはbashやshのようなシェルが含まれていないためです。これはスリムコンテナの一般的な特徴です。
シェルなしのコンテナをデバッグするには、docker execコマンドを使用してコンテナ環境内で特定のコマンドを直接実行できます。シェルがないため、コマンドを直接実行する必要があります。
コンテナのルートディレクトリにあるファイルをリストしてみましょう。最小限の環境でも通常利用可能なlsコマンドを使用します。
docker exec -it slim-container ls /
bin、etc、libなど、コンテナのファイルシステムルートにあるディレクトリとファイルのリストが表示されるはずです。これはシェルがなくてもコンテナ内で直接コマンドを実行できることを示しています。
最後に、作成したコンテナをクリーンアップしましょう。
docker stop slim-container
docker rm slim-container
このステップでは、docker execを使用してシェルなしのスリムコンテナと直接コマンドを実行して対話する方法を学びました。次のステップでは、他のデバッグ技術を探求します。
スリムイメージの直接デバッグ
前のステップでは、実行中のスリムコンテナと対話する方法を学びました。しかし、コンテナとして実行する前やコンテナの起動に失敗した場合に、スリムイメージの内容を検査する必要が生じることがあります。このステップでは、スリムイメージを直接デバッグする方法を探求します。
Docker はdocker runコマンドでイメージのデフォルトエントリーポイントやコマンドを上書きする機能を提供しています。これにより、イメージから作成した一時的なコンテナ内で別のコマンドを実行し、その内容を検査することが可能です。
再びalpineイメージを使用してみましょう。これはスリムイメージで、デフォルトではシェルが含まれていません。docker runを使用してls /のようなコマンドをイメージ上で直接実行できます。
docker run --rm alpine ls /
--rmフラグにより、コマンド終了後に一時コンテナが自動的に削除されます。前のステップで実行中のコンテナでls /を実行した時と同じ出力が得られるはずです。これでイメージのファイルシステムを直接検査できることが確認できました。
次に、イメージ内に特定のコマンドが存在するか確認してみましょう。例えばpingコマンドの有無を確認します。
docker run --rm alpine which ping
おそらくwhich: not foundのようなエラーメッセージが表示されるでしょう。これはデフォルトのalpineイメージにpingコマンドが含まれていないことを示しています。これはスリムイメージのもう一つの特徴で、必要最小限のツールしか含まれていないことが多いのです。
今度は存在が確実なcatコマンドを試してみましょう。
docker run --rm alpine which cat
今度は/bin/catという出力が得られ、イメージ内にcatコマンドが存在することが確認できます。
このdocker run --rm <image> <command>の手法は、イメージの内容を素早く確認したり、特定のファイルやコマンドの存在を検証したり、長期間実行するコンテナや新しいイメージを構築することなくイメージの構造を理解するのに非常に有用です。
実行中のコンテナ内ファイルの編集
このステップでは、実行中のコンテナ内のファイルを変更する方法を学びます。これは、設定ファイルの変更や、既に実行中のコンテナに一時的なスクリプトを追加するなど、デバッグ目的で役立ちます。
まず、alpineよりも機能が豊富でシェルや一般的なユーティリティを含むubuntuイメージを基にしたシンプルなコンテナを実行します。
docker run -d --name my-ubuntu ubuntu sleep 3600
このコマンドは Ubuntu コンテナをデタッチモード (-d) で実行し、sleep 3600コマンドを使用して 1 時間実行し続けます。参照しやすいようにコンテナにmy-ubuntuという名前を付けました。
次に、docker execを使用して実行中のコンテナ内でシェルを取得します。
docker exec -it my-ubuntu /bin/bash
これでmy-ubuntuコンテナの bash シェル内に入ります。プロンプトが変化し、コンテナ内にいることがわかります。
コンテナ内で、/tmpディレクトリに新しいファイルを作成しましょう。
echo "This is a test file." > /tmp/test_file.txt
ファイルが作成され、正しい内容が含まれていることを確認します。
cat /tmp/test_file.txt
This is a test file.という出力が表示されるはずです。これで実行中のコンテナ内でファイルを作成し、書き込むことができたことが確認できました。
コンテナのシェルから出るには、単にexitと入力します。
exit
これで LabEx VM のターミナルに戻ります。
docker cpコマンドを使用して、実行中のコンテナとの間でファイルをコピーすることもできます。LabEx VM 上にファイルを作成し、コンテナ内にコピーしてみましょう。
まず、~/projectディレクトリにlocal_file.txtというファイルを作成します。
echo "This file is from the host." > ~/project/local_file.txt
このファイルをmy-ubuntuコンテナの/tmpディレクトリにコピーします。
docker cp ~/project/local_file.txt my-ubuntu:/tmp/
docker cpの形式はdocker cp <source_path> <container_name>:<destination_path>またはdocker cp <container_name>:<source_path> <destination_path>です。
ファイルがコンテナ内にコピーされたことを確認するため、再度コンテナのシェルに入ります。
docker exec -it my-ubuntu /bin/bash
コンテナ内で、/tmpにlocal_file.txtが存在するか確認します。
ls /tmp/
test_file.txtとともにlocal_file.txtが表示されるはずです。
コンテナ内でlocal_file.txtの内容を表示してみましょう。
cat /tmp/local_file.txt
This file is from the host.という出力が表示されます。
再度コンテナのシェルから出ます。
exit
最後に、コンテナをクリーンアップします。
docker stop my-ubuntu
docker rm my-ubuntu
このステップでは、docker execを使用してシェルを取得し標準的な Linux コマンドで実行中のコンテナ内のファイルを変更する方法と、docker cpを使用してホストとコンテナ間でファイルをコピーする方法を実演しました。
デバッグツールボックスのインストールとアンインストール管理
このステップでは、実行中のコンテナ内でデバッグツールを追加・削除する方法を探ります。本番環境のコンテナイメージは最小限に保つのが一般的に推奨されますが、デバッグ目的で一時的にツールをインストールする必要が生じる場合があります。
ソフトウェアのインストールが容易なパッケージマネージャ (apt) を備えたubuntuイメージを再度使用します。
まず、新しい Ubuntu コンテナをデタッチモードで実行します。
docker run -d --name debug-ubuntu ubuntu sleep 3600
次に、コンテナ内でシェルを取得します。
docker exec -it debug-ubuntu /bin/bash
コンテナ内で、デフォルトではインストールされていないpingコマンドを使用してみます。
ping google.com
「command not found」エラーが表示されるでしょう。
pingやその他のネットワークユーティリティをインストールするには、aptパッケージマネージャを使用します。まず、パッケージリストを更新するのが良いプラクティスです。
apt update
このコマンドは、リポジトリから利用可能なパッケージに関する最新情報を取得します。
次に、pingコマンドを提供するiputils-pingパッケージをインストールします。
apt install -y iputils-ping
-yフラグは、確認プロンプトなしでインストールを自動的に承認します。
インストールが完了したら、pingコマンドが使用できるはずです。
ping -c 4 google.com
ping コマンドの出力が表示され、コンテナ内で利用可能かつ機能していることが確認できます。
デバッグが終了したら、コンテナをクリーンに保ち、新しいイメージとしてコミットする場合のサイズを小さくするため (ただし、本番環境で実行中のコンテナを変更することは一般的に推奨されません)、インストールしたツールを削除するのが良いでしょう。
iputils-pingパッケージを削除するには、apt removeを使用します。
apt remove -y iputils-ping
pingが利用できなくなったことを確認できます。
ping google.com
再び「command not found」エラーが表示されるはずです。
コンテナのシェルから出ます。
exit
最後に、コンテナをクリーンアップします。
docker stop debug-ubuntu
docker rm debug-ubuntu
このステップでは、実行中のコンテナ内でパッケージマネージャを使用してデバッグツールを一時的にインストール・アンインストールする方法を実演しました。これは、ベースイメージに必要なツールが含まれていないコンテナの問題をトラブルシューティングする強力なテクニックです。
entrypoint コマンドによるコンテナエントリーポイントの理解
このステップでは、Dockerfile のENTRYPOINT命令と、それがコンテナの実行方法にどのように影響するかを学びます。ENTRYPOINTはコンテナ起動時に実行されるコマンドを定義し、コンテナのメイン実行ファイルを設定するためによく使用されます。
まず、ENTRYPOINTを使用するシンプルな Dockerfile を作成しましょう。~/projectディレクトリに以下の内容でDockerfileというファイルを作成します:
FROM alpine
ENTRYPOINT ["echo", "Hello from the entrypoint!"]
CMD ["default", "command"]
この Dockerfile はベースイメージとしてalpineを使用しています。ENTRYPOINTは["echo", "Hello from the entrypoint!"]に設定され、CMDは["default", "command"]に設定されています。ENTRYPOINTとCMDの両方が指定されている場合、CMDの引数はENTRYPOINTコマンドへの引数として渡されます。
この Dockerfile からイメージをビルドしましょう。
docker build -t my-entrypoint-image ~/project
このコマンドは~/projectディレクトリの Dockerfile からmy-entrypoint-imageという名前のイメージをビルドします。
追加コマンドを指定せずにこのイメージからコンテナを実行します。
docker run my-entrypoint-image
Hello from the entrypoint! default commandという出力が表示されるはずです。これはENTRYPOINTコマンド (echo) が実行され、CMDの引数 (default command) が渡されたことを示しています。
次に、docker runコマンドラインで異なるコマンドを指定してコンテナを実行します。docker runでコマンドを指定すると、Dockerfile のCMD命令は上書きされますが、ENTRYPOINTは指定されたコマンドを引数として実行されます。
docker run my-entrypoint-image "override command"
Hello from the entrypoint! override commandという出力が表示されるはずです。これはENTRYPOINTが実行されましたが、docker runコマンドの引数 (override command) がCMDの引数を置き換えたことを示しています。
ENTRYPOINTを完全に無視して別のコマンドを実行したい場合はどうすればよいでしょうか?docker runで--entrypointフラグを使用できます。
docker run --entrypoint /bin/echo my-entrypoint-image "Running a different command"
Running a different commandという出力が表示されるはずです。この場合、--entrypointフラグが Dockerfile で指定されたENTRYPOINTを上書きし、指定されたコマンド (/bin/echo) が引数 (Running a different command) 付きで実行されました。
ENTRYPOINTとCMDを理解することは、Docker イメージの構築とデバッグにおいて重要です。ENTRYPOINTはコア実行ファイルを定義し、CMDはその実行ファイルへのデフォルト引数を提供するか、ENTRYPOINTが設定されていない場合はデフォルトコマンドを提供します。
まとめ
この実験では、docker debugコマンドと関連技術を使用して Docker コンテナとイメージをデバッグする方法を学びました。まず、シェルが存在しないスリムなコンテナのデバッグ方法を探り、bashやshのような従来のシェルがなくてもdocker execを使用してコンテナ環境内で直接コマンドを実行できることを実証しました。これは最小限のコンテナイメージをトラブルシューティングするための重要な技術です。
提供された内容は最初のステップのみをカバーしていますが、実験の全体構造から、続くステップではスリムイメージの直接デバッグ、実行中のコンテナ内でのファイル変更、インストール/アンインストールコマンドによるデバッグツールボックスの管理、entrypointコマンドを使用したコンテナエントリーポイントの理解などについて掘り下げることが示唆されています。これらのステップを通じて、Docker 化されたアプリケーションやイメージ内の問題を診断・解決する能力をさらに強化できるでしょう。



