序章

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

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

前提条件

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

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

サーバーにDockerをインストールするには、CentOS 7の場合は、Ubuntu16.04の場合はのハウツーガイドに従うことができます。

Docker Webサイトにアクセスするか、公式のインストールドキュメントに従って、ローカルマシンにDockerをインストールできます。

ステップ1—Dockerfileの問題を解決する

問題が発生する可能性のある最も一般的な場所は、Dockerイメージを Dockerfile. 飛び込む前に、画像とコンテナの違いを明確にしましょう。

  • image は、と呼ばれる構成ファイルを使用して作成する読み取り専用リソースです。 Dockerfile. これは、 DockerHubまたはプライベートレジストリを介して出荷および共有するものです。
  • コンテナは、作成したイメージから作成した読み取りおよび書き込みインスタンスです。

これらの概念の詳細については、チュートリアル Dockerの説明:Dockerfilesを使用したイメージの構築の自動化を参照してください。

あなたが見るとき Dockerfile、Dockerがイメージを構築するために使用するステップバイステップのプロセスを明確に確認できます。これは、 Dockerfile プロセスのステップに対応します。 これは通常、特定のステップに到達した場合、前のすべてのステップが正常に完了したことを意味します。

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

  1. mkdir ~/docker_image
  2. nano ~/docker_image/Dockerfile

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

〜/ docker_image / Dockerfile
# base image
FROM debian:latest

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

このコードには意図的なタイプミスがあります。 見つけられますか? このファイルからイメージを作成して、Dockerが不正なコマンドをどのように処理するかを確認してください。 次のコマンドを使用してイメージを作成します。

  1. docker build -t my_image ~/docker_image

ターミナルに次のメッセージが表示され、エラーが示されます。

Output
Step 2 : RUN aapt-get install -qy nano ---> Running in 085fa10ffcc2 /bin/sh: 1: aapt-get: not found The command '/bin/sh -c aapt-get install -qy nano' returned a non-zero code: 127

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

を変更します Dockerfile 修正します:

Dockerfile

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

今実行します docker build もう一度コマンド:

  1. docker build -t my_image ~/docker_image

そして今、あなたは次の出力を見るでしょう:

Output
Sending 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... E: Unable to locate package nano The command '/bin/sh -c apt-get install -qy nano' returned a non-zero code: 100

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

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

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

  1. nano ~/docker_image/Dockerfile

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

〜/ 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

ファイルを保存して実行します docker build もう一度コマンド:

  1. docker build -t my_image ~/docker_image

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

Output
Sending 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

Python3とPostgreSQLドライバーをイメージに追加するとどうなるか見てみましょう。 を開きます Dockerfile また。

  1. nano ~/docker_image/Dockerfile

そして、Python3とPythonPostgreSQLドライバーをインストールするための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
RUN apt-get install -qy python3
RUN apt-get install -qy python3-psycopg2

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

  1. docker build -t my_image ~/docker_image

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

Output
Sending 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 Removing intermediate container d7d4376c9f0d Successfully built 978e0fa7afa7

:Dockerはビルドプロセスをキャッシュするため、ビルドで更新を実行し、Dockerがこの更新をキャッシュし、しばらくするとベースディストリビューションがソースを再度更新して、クリーンアップと更新を行っているにもかかわらず、古いソース Dockerfile. コンテナ内のパッケージのインストールまたは更新で問題が発生した場合は、 apt-get clean && apt-get update コンテナの内側。

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

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

ステップ2—コンテナの名前付けの問題を解決する

より多くのコンテナを起動すると、最終的に名前の衝突に遭遇します。 名前の衝突とは、システムにすでに存在するコンテナと同じ名前のコンテナを作成しようとすることです。 衝突を回避するために、コンテナの命名、名前変更、および削除を適切に処理する方法を調べてみましょう。

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

  1. docker run -ti my_image bash

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

実行中のコンテナができたので、どのような問題が発生する可能性があるかを見てみましょう。

名前を明示的に設定せずに、今行った方法でコンテナーを実行すると、Dockerはコンテナーにランダムな名前を割り当てます。 を実行すると、実行中のすべてのコンテナとそれに対応する名前を確認できます。 docker ps 実行中のコンテナーの外部にあるDockerホストでのコマンド。

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

  1. docker ps

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

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

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

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

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

  1. docker rename your_container_name python_box

次に、コンテナを一覧表示します。

  1. docker ps

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

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

コンテナを閉じるには、次のように入力します exit 実行中のコンテナを含むターミナルのプロンプトで:

  1. exit

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

  1. docker kill python_box

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

Output
python_box

確かめる python_box もう存在しません。実行中のすべてのコンテナーを再度リストします。

  1. docker ps

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

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

今、あなたはあなたがという名前の別のコンテナを起動できると思うかもしれません python_box、しかし、私たちが試してみると何が起こるか見てみましょう。

を使用します --name 今回はコンテナ名を設定するための引数:

  1. docker run --name python_box -ti my_image bash
Output
docker: 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. 実行されていませんが、再起動したい場合に備えて引き続き使用できます。 止めましたが、外しませんでした。 The docker ps コマンドは、実行中のコンテナーのみを表示し、すべてのコンテナーは表示しません。

Dockerコンテナのallを一覧表示するには、実行中およびそれ以外の場合は、 -a フラグ(エイリアス --all) に docker ps:

  1. docker ps -a

今私たちの python_box コンテナが出力に表示されます:

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

コンテナは Exited (137) ステータス。同じ名前の新しいコンテナを作成しようとしたときに、名前の問題が発生したのはそのためです。

コンテナを完全に削除したい場合は、 docker rm 指図。 端末で次のコマンドを実行します。

  1. docker rm python_box

もう一度、Dockerは削除されたばかりのコンテナの名前を出力します。

Output
python_box

警告:コンテナがまだ実行中の場合、このコマンドは失敗し、エラーメッセージが出力されるため、最初に停止または強制終了してください。

名前の付いた新しいコンテナを作成しましょう python_box 前のものを削除したので:

  1. docker run --name python_box -ti my_image bash

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

それでは、将来問題が発生しないように、コンテナを強制終了して削除しましょう。 Dockerホスト上の別のターミナルセッションから、コンテナーを強制終了し、次のコマンドで削除します。

  1. docker kill python_box && docker rm python_box

2つのコマンドをチェーン化したため、出力にはコンテナー名が2回表示されます。 最初の出力はコンテナを強制終了したことを確認し、もう1つの出力はコンテナを削除したことを確認します。

Output
python_box python_box

保つ docker ps -a 名前に問題が発生した場合は、同じ名前でコンテナを再作成する前に、コンテナが停止して削除されていることを確認してください。

コンテナに名前を付けると、インフラストラクチャの管理が容易になります。 次に説明するように、名前を使用すると、コンテナー間の通信も簡単になります。

ステップ3—コンテナ通信の問題を解決する

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

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

まず、PostgreSQLコンテナを作成しましょう。 このコンテナに名前を付けるには、 --name 他のコンテナとリンクするときに簡単に識別できるようにフラグを立てます。 それを呼びます postgres_box.

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

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

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

  1. docker run --name postgres_box --detach postgres

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

Output
Unable 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 f6609b9e96cc874be0852e400381db76a19ebfa4bd94fe326477b70b8f0aff65

コンテナを一覧表示して、この新しいコンテナが実行されていることを確認します。

  1. docker ps

出力は、 postgres_box コンテナはバックグラウンドで実行されており、ポートを公開しています 5432、PostgreSQLデータベースポート:

Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7a230b56cd64 postgres_box "/docker-entrypoint.s" Less than a second ago Up 2 seconds 5432/tcp postgres

それでは、Pythonコンテナを起動しましょう。 Pythonコンテナ内で実行されているプログラムが、 postgres_box コンテナの場合、Pythonコンテナを手動でリンクする必要があります postgres_box を使用してコンテナ --link 口論。 リンクを作成するには、コンテナの名前を指定し、その後にリンクの名前を指定します。 リンク名を使用して、 postgres_box Pythonコンテナ内からのコンテナ。

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

  1. docker run --name python_box --link postgres_box:postgres -ti my_image bash

それでは、内部からPostgreSQLに接続してみましょう。 python_box 容器。

以前にインストールしました nano の内側 python_box コンテナなので、これを使用して、PostgreSQLへの接続をテストするための簡単なPythonスクリプトを作成しましょう。 のターミナルで python_box コンテナ、次のコマンドを実行します。

  1. nano pg_test.py

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

pg_test.py
"""Test PostgreSQL connection."""
import psycopg2

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

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

  1. python3 pg_test.py

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

Output
Traceback (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: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

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

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

  1. cat /etc/hosts

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

Output
127.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.2 postgres f6609b9e96cc postgres_box 172.17.0.3 3053f74c8c13

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

  1. nano pg_test.py

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

/pg_test.py
"""Test PostgreSQL connection."""
import psycopg2

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

ファイルを保存してから、スクリプトを再実行してください。

  1. python3 pg_test.py

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

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

他のコンテナのサービスに接続するときは、コンテナ名を覚えておいてください。アプリケーションのクレデンシャルを編集して、それらのコンテナのリンクされた名前を参照してください。

結論

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

Dockerには --debug 主にDocker開発者を対象としたフラグ。 ただし、Dockerの内部について詳しく知りたい場合は、Dockerコマンドをデバッグモードで実行して、より詳細な出力を試してください。

  1. docker -D [command] [arguments]

ソフトウェアのコンテナはしばらく前から存在していましたが、Docker自体は3年しか存在しておらず、非常に複雑になる可能性があります。 時間をかけて用語とエコシステムに慣れてください。最初は少し異質だったいくつかの概念が、すぐに意味をなすようになることがわかります。