コンテナーは完全にビルドされますが、適切に起動しないにもかかわらず、コンテナーに問題がありました。原因は、Dockerfileに追加した回避策です(自己構成された/ etc/hostsルーティングを持つため)
RUN mkdir -p -- /lib-override /etc-override && cp /lib/libnss_files.so.2 /lib-override
ADD hosts.template /etc-override/hosts
RUN Perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override
明らかにそこにはいくつかのエラーがありますが、実行中にdockerが何をしているのかについてもっと情報を得るにはどうすればいいのでしょうか。たとえば、これは動作します:
$ docker run image ls
usr bin ...
しかし、これはしません:
$ docker run image ls -l
$
ログには何もないので、インタラクティブシェルを呼び出すこともできません。私は何が起こっているかを確認するためにstraceを使用できますが、もっと良い方法があることを望んでいました。
Dockerをより冗長に設定する方法はありますか?
[〜#〜] edit [〜#〜]:Andrew Dに感謝します。これで上記のコードの何が問題なのかがわかりました(彼の答えが理解できるように残しました)。今でも問題はどうやってこのようなものをデバッグするのか、なぜls -lが失敗したのか lsはしませんでした。
[〜#〜] edit [〜#〜]:-D = trueを指定すると、出力が増える可能性がありますが、私の場合はそうではありません...
Docker events
コマンドが役立つ場合があり、イメージの開始に失敗した後でも Docker logs コマンドでログを取得できます。
まず、バックグラウンドでdocker events
を起動して、状況を確認します。
docker events&
次に、失敗したdocker run ...
コマンドを実行します。次に、次のような画面が表示されます。
2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die
次に、前のメッセージまたはrunコマンドの出力からスタートアップ16進IDを取得できます。その後、logsコマンドで使用できます。
docker logs <copy the instance id from docker events messages on screen>
失敗したイメージの起動からの出力が表示されます。
@alexkbがコメントで示唆しているように:AWS ECSサービスなどからコンテナーが常に再起動されている場合、docker events&
は問題を引き起こす可能性があります。このシナリオでは、/var/log/ecs/ecs-agent.log.<DATE>
のログからコンテナの16進数IDを取得する方が簡単な場合があります。次にdocker logs <hex id>
を使用します。
まあ私がこれまでに見つけた中で最高のものは:
#stop the current demon and start it in debug modus
Sudo service docker stop
dockerd -D # --debug
新しいシェルからクライアントを起動するだけです。誤解は、クライアントが実際には何もしないと考えることでした...まあ、それは単にデーモンと通信しているだけなので、debugクライアントではなく、デーモン自体(通常)は使用したくありません。
私の場合、-a
(STDOUT/STDERRにアタッチ)フラグで十分です:
user@machine:~$ docker start -a server_name
Error: The directory named as part of the path /log/log_path/app.log does not exist.
For help, use /usr/bin/supervisord -h
起動エラーが表示されました(この場合、supervisord
で使用されるログパスがありません)。ほとんどのコンテナー起動エラーがここにも表示されると思います。
Docker出力をより完全にする方法に関するあなたの質問に答えることはできませんが、.soファイル内の文字列を置き換えるインプレース正規表現は少しおかしなことです:文字列には非常に多くのスペースが割り当てられているだけで、他のエントリのファイルオフセットを変更すると、elfファイルが破損します。コンテナーの外でPerlコマンド(LD_LIBRARY_PATHの変更前)を実行した後、.soファイルでobjdumpまたはreadelfを実行してみてください。
それが機能する理由 この悲しいことに必要なハック は、「tmp」と「etc」が同じ文字列長であるため、オフセットが変更されないためです。/tmpを使用しない場合は、/ dkrなどのディレクトリを検討してください。
このアプローチを取る必要があり、目的のパスが変更できない場合は、ライブラリを再構築して、ソース内の/ etc/hostsのデフォルトパスを変更します。または、変更されたlibnss_files.so
をビルドするときに、libnss_altfiles.so
のような名前に変更し、nsswitch.conf
を変更して、Dockerコンテナーの起動時にhosts: altfiles
を使用します(Dockerがバインドマウントされたnsswitch.confを除く)同様に、それを変更することはできません)。これにより、基本システムの通常のライブラリと並行してlibnss_altfiles.soを使用できます。 dockerがnsswitch.confをバインドマウントする場合は、再構築したlibnss_files.soのコピーを/ lib-overrideディレクトリに残して、LD_LIBRARY_PATHでロードできるようにします。
参考までに、suid/sgidバイナリはLD_LIBRARY_PATHとLD_PRELOADを無視するため、これらの変数を使用すると、いくつかの問題が発生します(参照:デフォルトの/ etc/hostsの使用に戻ります)。
場合によっては、dockerデーモンを実行しているノードにsshしてから次のようにすると、有用なエラーメッセージを見つけることができます。
$ tail -f /var/log/containers/* /var/log/docker.log 2>&1
Mac OSの「Docker Communityエディション」では、次のようにしてdocker vmに接続できます。
$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty