Dockerの一般的な問題をデバッグおよび修正する方法

前書き

Dockerを使用すると、アプリケーションやサービスをコンテナに簡単にラップできるため、どこでも実行できます。 残念ながら、特にDockerの画像やコンテナを初めて使用する場合は、画像を構築してアプリに必要なすべてのレイヤーを統合するときに問題が発生する可能性があります。 タイプミス、ランタイムライブラリとモジュールの問題、名前の衝突、または他のコンテナと通信するときに問題が発生する場合があります。

Dockerを初めて使用するユーザー向けのこのトラブルシューティングガイドでは、Dockerイメージの構築時の問題のトラブルシューティング、コンテナーの実行時の名前の衝突の解決、コンテナー間の通信時の問題の修正を行います。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • サーバーまたはローカルマシンにインストールされたDocker。

サーバーにDockerをインストールするには、ハウツーガイドhttps://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-centos-7[for CentOS 7 ]またはhttps://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04[Ubuntu 16.04の場合]。

Docker Webサイトにアクセスするか、https://docs.docker.com/engine/installation/ [公式インストールドキュメント]に従ってローカルにDockerをインストールできます。機械。

ステップ1-Dockerfileの問題の解決

問題が発生する可能性のある最も一般的な場所は、 `+ Dockerfile +`からDockerイメージを構築するときです。 始める前に、画像とコンテナの違いを明確にしましょう。

  • _image_は、 `+ Dockerfile +`という設定ファイルを使用して作成する読み取り専用リソースです。 これは、http://dockerhub.com [Docker Hub]またはプライベートレジストリを通じて出荷および共有するものです。

  • _container_は、作成したイメージから作成する読み取りおよび書き込みインスタンスです。

これらの概念の詳細については、チュートリアルhttps://www.digitalocean.com/community/tutorials/docker-explained-using-dockerfiles-to-automate-building-of-images[Dockerの説明:Dockerfilesを使用してビルドを自動化する画像の]。

`+ Dockerfile `を見ると、 ` Dockerfile +`の各行がプロセスのステップに対応しているため、Dockerがイメージをビルドするステップバイステッププロセスを明確に見ることができます。 これは通常、特定のステップに到達した場合、前のステップがすべて正常に完了したことを意味します。

`+ Dockerfile`で発生する可能性のあるいくつかの問題を調査するための小さなプロジェクトを作成しましょう。 ホームディレクトリに `+ docker_image `ディレクトリを作成し、 ` nano `またはお気に入りのエディタを使用してそのフォルダに ` Dockerfile +`を作成します

mkdir ~/docker_image
nano ~/docker_image/Dockerfile

この新しいファイルに次のコンテンツを追加します。

〜/ docker_image / Dockerfile

# base image
FROM debian:latest

# install basic apps
RUN aapt-get install -qy nano

このコードには意図的なタイプミスがあります。 あなたはそれを見つけることができますか? このファイルからイメージを構築して、Dockerが不正なコマンドを処理する方法を確認してください。 次のコマンドでイメージを作成します。

docker build -t my_image ~/docker_image

エラーを示す次のメッセージが端末に表示されます。

OutputStep 2 : RUN aapt-get install -qy nano
 ---> Running in 085fa10ffcc2

最後のエラーメッセージは、ステップ2のコマンドに問題があったことを意味します。 この場合、意図的なタイプミスでした。「+ apt-get 」の代わりに「 aapt-get +」があります。 しかし、それはまた、前のステップが正しく実行されたことを意味しました。

`+ Dockerfile +`を修正して修正します。

Dockerfile

# install basic apps
RUN  install -qy nano

次に、 `+ docker build`コマンドを再度実行します。

docker build -t my_image ~/docker_image

そして、次の出力が表示されます。

OutputSending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
---> ddf73f48a05d
Step 2 : RUN apt-get install -qy nano
---> Running in 9679323b942f
Reading package lists...
Building dependency tree...

タイプミスを修正すると、Dockerはベースイメージを再ダウンロードするのではなく、最初のステップをキャッシュしたため、プロセスは少し速くなりました。 しかし、出力からわかるように、新しいエラーがあります。

イメージの基盤として使用したDebianディストリビューションでは、Debianパッケージリポジトリで利用できることがわかっていても、テキストエディタ「+ nano +」が見つかりませんでした。 基本イメージには、リポジトリや利用可能なパッケージのリストなどのキャッシュされたメタデータが付属しています。 データを取得しているライブリポジトリが変更されたときに、キャッシュの問題が発生することがあります。

これを修正するには、Dockerfileを変更して、新しいパッケージをインストールする前に、ソースのクリーンアップと更新を行います。 構成ファイルを再度開きます。

nano ~/docker_image/Dockerfile

次の強調表示された行をファイルに追加します。_above_コマンドで `+ nano +`をインストールします。

〜/ docker_image / Dockerfile

# base image
FROM debian:latest

# clean and update sources


# install basic apps
RUN apt-get install -qy nano

ファイルを保存し、 `+ docker build +`コマンドを再度実行します:

docker build -t my_image ~/docker_image

今回はプロセスが正常に完了します。

OutputSending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
---> a24c3183e910
Step 2 : RUN apt-get install -qy nano
---> Running in 2237d254f172
Reading package lists...
Building dependency tree...
Reading state information...
Suggested packages:
 spell
The following NEW packages will be installed:
 nano
...

---> 64ff1d3d71d6
Removing intermediate container 2237d254f172
Successfully built 64ff1d3d71d6

Python 3とPostgreSQLドライバーを画像に追加するとどうなるか見てみましょう。 もう一度 `+ Dockerfile +`を開きます。

nano ~/docker_image/Dockerfile

そして、Python 3とPython PostgreSQLドライバーをインストールするための2つの新しい手順を追加します。

〜/ docker_image / Dockerfile

# base image
FROM debian:latest

# clean and update sources
RUN apt-get clean && apt-get update

# install basic apps
RUN apt-get install -qy nano

# install Python and modules

ファイルを保存し、エディターを終了して、イメージを再度ビルドします。

docker build -t my_image ~/docker_image

出力からわかるように、パッケージは正しくインストールされます。 また、前の手順がキャッシュされたため、プロセスははるかに迅速に完了します。

OutputSending build context to Docker daemon 2.048 kB
Step 1 : FROM debian:latest
---> ddf73f48a05d
Step 2 : RUN apt-get clean && apt-get update
---> Using cache
---> 2c5013476fbf
Step 3 : RUN apt-get install -qy nano
---> Using cache
---> 4b77ac535cca
Step 4 : RUN apt-get install -qy python3
---> Running in 93f2d795fefc
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
 krb5-locales libgmp10 libgnutls-deb0-28 libgssapi-krb5-2 libhogweed2
 libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 libnettle4
 libp11-kit0 libpq5 libsasl2-2 libsasl2-modules libsasl2-modules-db
 libtasn1-6
Suggested packages:
 gnutls-bin krb5-doc krb5-user libsasl2-modules-otp libsasl2-modules-ldap
 libsasl2-modules-sql libsasl2-modules-gssapi-mit
 libsasl2-modules-gssapi-heimdal python-psycopg2-doc
The following NEW packages will be installed:
 krb5-locales libgmp10 libgnutls-deb0-28 libgssapi-krb5-2 libhogweed2
 libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libldap-2.4-2 libnettle4
 libp11-kit0 libpq5 libsasl2-2 libsasl2-modules libsasl2-modules-db
 libtasn1-6 python3-psycopg2
0 upgraded, 18 newly installed, 0 to remove and 0 not upgraded.
Need to get 5416 kB of archives.
After this operation, 10.4 MB of additional disk space will be used.

...

Processing triggers for libc-bin (2.19-18+deb8u6) ...
---> 978e0fa7afa7

Dockerの出力に細心の注意を払ってタイプミスの場所を特定し、ビルド時にコンテナ内で更新を実行して、キャッシュされたパッケージリストによって妨げられていないことを確認します。

構文エラーとキャッシュの問題は、Dockerでイメージを構築するときに発生する可能性のある最も一般的な問題です。 次に、これらのイメージからコンテナを実行するときに発生する可能性のある問題を見てみましょう。

ステップ2-コンテナの命名問題の解決

コンテナをさらに起動すると、最終的に名前の衝突に遭遇します。 ネーミング衝突は、システムにすでに存在するコンテナと同じ名前を持つコンテナを作成しようとする場所です。 衝突を回避するために、コンテナの命名、名前変更、削除を適切に処理する方法を調べてみましょう。

前のセクションで作成したイメージからコンテナーを起動しましょう。 このコンテナ内でインタラクティブなbashインタープリターを実行して、テストします。 次のコマンドを実行してください。

docker run -ti my_image bash

コンテナが起動すると、指示を待っているルートプロンプトが表示されます。

コンテナが実行されたので、どのような問題に遭遇する可能性があるのか​​見てみましょう。

明示的に名前を設定せずに、コンテナを上記の方法で実行すると、Dockerはコンテナにランダムな名前を割り当てます。 実行中のコンテナの外で、Dockerホストで `+ docker ps +`コマンドを実行することで、実行中のすべてのコンテナとそれらに対応する名前を表示できます。

Dockerホストで新しいターミナルを開き、次のコマンドを実行します。

docker ps

このコマンドは、次の例に示すように、名前とともに実行中のコンテナのリストを出力します。

OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              22 seconds ago      Up 28 seconds

前の出力の名前「+ loving_brahmagupta +」は、前の例でDockerがコンテナに自動的に割り当てた名前です。あなたの名前は別の名前になります。 Dockerにコンテナに名前を割り当てさせることは非常に単純な場合には問題ありませんが、重大な問題を引き起こす可能性があります。デプロイするときは、コンテナに一貫した名前を付けて、それらを参照して簡単に自動化できるようにする必要があります。

コンテナの名前を指定するには、コンテナを起動するときに引数「+-name +」を使用するか、実行中のコンテナをよりわかりやすい名前に変更します。

Dockerホストのターミナルから次のコマンドを実行します。

docker rename  python_box

次に、コンテナーをリストします。

docker ps

出力に `+ python_box +`コンテナが表示され、コンテナの名前が正常に変更されたことを確認します。

OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              24 minutes ago      Up 24 minutes                           python_box

コンテナを閉じるには、実行中のコンテナを含むターミナルのプロンプトで「+ exit +」と入力します。

exit

それがオプションではない場合、次のコマンドを使用して、Dockerホスト上の別のターミナルからコンテナを強制終了できます。

docker kill python_box

この方法でコンテナを強制終了すると、Dockerは強制終了されたばかりのコンテナの名前を返します。

Outputpython_box

`+ python_box +`がもう存在しないことを確認するには、実行中のすべてのコンテナを再度リストします。

docker ps

予想どおり、コンテナーはリストされなくなりました。

OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

これで、 `+ python_box +`という名前の別のコンテナを起動できると思うかもしれませんが、試してみるとどうなるか見てみましょう。

今回は、コンテナの名前を設定するために `+-name +`引数を使用します。

docker run  -ti my_image bash
Outputdocker: Error response from daemon: Conflict. The name "/python_box" is already in use by container 80a0ca58d6ecc80b305463aff2a68c4cbe36f7bda15e680651830fc5f9dda772. You have to remove (or rename) that container to be able to reuse that name..
See 'docker run --help'.

画像を作成して既存の画像の名前を再利用すると、既に見たように、既存の画像は上書きされます。 既に存在するコンテナを上書きできないため、コンテナはもう少し複雑です。

Dockerには、「+ python_box 」は既に削除されているにもかかわらず、すでに存在しており、「 docker ps 」でリストされていないということです。 実行されていませんが、再度起動する場合に備えて利用可能です。 停止しましたが、削除しませんでした。 ` docker ps +`コマンドは、_all_コンテナではなく、_running_コンテナのみを表示します。

実行中のDockerコンテナの_all_を一覧表示するには、 `+ -a `フラグ( `-all `のエイリアス)を ` docker ps +`に渡します。

docker ps -a

これで、 `+ python_box +`コンテナが出力に表示されます:

OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
80a0ca58d6ec        my_image            "bash"              12 minutes ago      Exited (137) 6 minutes ago

コンテナは `+ Exited(137)+`ステータスで存在します。これが、同じ名前の新しいコンテナを作成しようとしたときにネーミングの問題に遭遇した理由です。

コンテナを完全に削除したい場合は、 `+ docker rm +`コマンドを使用します。 ターミナルで次のコマンドを実行します。

docker rm python_box

再び、Dockerは削除されたばかりのコンテナーの名前を出力します。

Outputpython_box

前のコンテナを削除したので、 `+ python_box +`という名前の新しいコンテナを作成しましょう。

docker run --name python_box -ti my_image bash

プロセスが完了し、ルートシェルが再び表示されます。

コンテナを強制終了して削除して、将来の問題を回避しましょう。 Dockerホスト上の別のターミナルセッションから、次のコマンドを使用してコンテナを強制終了して削除します。

docker kill python_box && docker rm python_box

2つのコマンドを連鎖させたため、出力にはコンテナ名が2回表示されます。 最初の出力では、コンテナが削除されたことを確認し、もう1つの出力では、コンテナが削除されたことを確認します。

Outputpython_box
python_box

名前に関する問題が発生した場合は、「+ docker ps -a +」を念頭に置き、同じ名前でコンテナを再作成する前に、コンテナが停止および削除されていることを確認してください。

コンテナに名前を付けると、インフラストラクチャを管理しやすくなります。 また、名前を使用すると、次のようにコンテナ間で簡単に通信できます。

ステップ3-コンテナー通信の問題の解決

Dockerを使用すると、複数のコンテナを簡単にインスタンス化できるため、各コンテナで異なるサービスや冗長なサービスを実行できます。 サービスに障害が発生した場合、またはサービスが危険にさらされた場合は、インフラストラクチャの残りの部分を損なわずに、新しいサービスに置き換えることができます。 ただし、これらのコンテナが相互に通信する問題に遭遇する可能性があります。

潜在的な通信の問題を調査できるように、通信する2つのコンテナーを作成しましょう。 既存のイメージを使用してPythonを実行する1つのコンテナーと、PostgreSQLのインスタンスを実行する別のコンテナーを作成します。 そのコンテナには、http://dockerhub.com [Docker Hub]から入手できる公式のPostgreSQLイメージを使用します。

最初にPostgreSQLコンテナを作成しましょう。 `-name +`フラグを使用してこのコンテナに名前を付けて、他のコンテナとリンクするときに簡単に識別できるようにします。 これを「 postgres_box +」と呼びます。

以前は、コンテナを起動すると、フォアグラウンドで実行され、ターミナルを引き継ぎました。 PostgreSQLデータベースコンテナをバックグラウンドで起動します。これは、 `+-detach +`フラグで実行できます。

最後に、 `+ bash `を実行する代わりに、コンテナ内でPostgreSQLデータベースサーバーを起動する ` postgres +`コマンドを実行します。

次のコマンドを実行して、コンテナを起動します。

docker run --name postgres_box --detach postgres

DockerはDocker Hubからイメージをダウンロードし、コンテナーを作成します。 次に、バックグラウンドで実行されているコンテナの完全なIDを返します。

OutputUnable to find image 'postgres:latest' locally
latest: Pulling from library/postgres
6a5a5368e0c2: Already exists
193f770cec44: Pull complete
...
484ac0d6f901: Pull complete
Digest: sha256:924650288891ce2e603c4bbe8491e7fa28d43a3fc792e302222a938ff4e6a349
Status: Downloaded newer image for postgres:latest

コンテナをリストして、この新しいコンテナが実行されていることを確認します。

docker ps

出力は、 `+ postgres_box `コンテナがバックグラウンドで実行されていることを確認し、PostgreSQLデータベースポートであるポート ` 5432 +`を公開します。

OutputCONTAINER ID        IMAGE               COMMAND                  CREATED                  STATUS              PORTS               NAMES
7a230b56cd64                    "/docker-entrypoint.s"   Less than a second ago   Up 2 seconds

それでは、Pythonコンテナを起動しましょう。 Pythonコンテナ内で実行されているプログラムが `+ postgres_box `コンテナ内のサービスを「見る」ためには、 `-link `引数を使用してPythonコンテナを ` postgres_box `コンテナに手動でリンクする必要があります。 リンクを作成するには、コンテナの名前を指定し、その後にリンクの名前を指定します。 リンク名を使用して、Pythonコンテナー内から ` postgres_box +`コンテナーを参照します。

次のコマンドを発行して、Pythonコンテナーを開始します。

docker run --name python_box --link  -ti my_image bash

では、 `+ python_box +`コンテナ内からPostgreSQLに接続してみましょう。

以前に `+ python_box `コンテナ内に ` nano `をインストールしたので、それを使用して単純なPythonスクリプトを作成し、PostgreSQLへの接続をテストします。 ` python_box +`コンテナのターミナルで、次のコマンドを実行します:

nano pg_test.py

次に、次のPythonスクリプトをファイルに追加します。

pg_test.py

"""Test PostgreSQL connection."""
import psycopg2

conn = psycopg2.connect(user='postgres')
print(conn)

ファイルを保存し、エディターを終了します。 スクリプトからデータベースに接続しようとするとどうなるか見てみましょう。 コンテナでスクリプトを実行します。

python3 pg_test.py

表示される出力は、データベースへの接続に問題があることを示しています。

OutputTraceback (most recent call last):
 File "pg_test.py", line 5, in <module>
   conn = psycopg2.connect(database="test", user="postgres", password="secret")
 File "/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 164, in connect
   conn = _connect(dsn, connection_factory=connection_factory, async=async)
psycopg2.OperationalError:

`+ postgres_box `コンテナが実行されていることを確認し、それを ` python_box +`コンテナにリンクしました。それではどうなりましたか? 接続しようとしたときにデータベースホストを指定したことがないため、Pythonはローカルで実行されているデータベースに接続しようとしますが、サービスがローカルで実行されていないため、動作しません。別のコンピューター上にありました。

リンクを作成したときに設定した名前を使用して、リンクされたコンテナにアクセスできます。 この場合、データベースサーバーを実行している `+ postgres_box `コンテナを参照するために ` postgres `を使用します。 これを確認するには、 ` python_box `コンテナ内の ` / etc / hosts +`ファイルを表示します。

cat /etc/hosts

使用可能なすべてのホストとその名前とIPアドレスが表示されます。 `+ postgres +`サーバーがはっきりと見えます。

Output127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

172.17.0.3      3053f74c8c13

それでは、Pythonスクリプトを変更してホスト名を追加しましょう。 ファイルを開きます。

nano pg_test.py

次に、接続文字列でホストを指定します。

/pg_test.py

"""Test PostgreSQL connection."""
import psycopg2

conn = psycopg2.connect( user='postgres')
print(conn)

ファイルを保存してから、スクリプトを再度実行します。

python3 pg_test.py

今回はエラーなしでスクリプトが完了します。

Output<connection object at 0x7f64caec69d8; dsn: 'user=postgres host=7a230b56cd64', closed: 0>

他のコンテナのサービスに接続しようとするときはコンテナ名を覚えておいて、アプリケーション資格情報を編集してそれらのコンテナのリンク名を参照してください。

結論

イメージの構築からコンテナのネットワークの展開まで、Dockerコンテナを使用する際に発生する可能性のある最も一般的な問題について説明しました。

Dockerには、主にDocker開発者向けの `+-debug +`フラグがあります。 ただし、Docker内部について詳しく知りたい場合は、デバッグモードでDockerコマンドを実行して、より詳細な出力を取得してください。

docker -D [command] [arguments]

ソフトウェアのコンテナはしばらく前から存在していましたが、Docker自体はわずか3年しか存在せず、非常に複雑になる可能性があります。 時間とhttps://www.digitalocean.com/community/tutorial_series/the-docker-ecosystem[the ecosystem]に慣れると、最初は少し異質だったいくつかの概念がどのようになるかがわかります。すぐに多くの意味をなします。

Related