Как я могу отладить инициализацию Docker-контейнера?

У меня была проблема с контейнером, хотя он прекрасно собирается, но не запускается должным образом. Причина - это обходной путь, который я добавил в 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 run image ls
usr bin ...

Но это не так:

$ docker run image ls -l
$

В логах ничего нет, и я не могу вызвать интерактивную оболочку. Я могу использовать strace, чтобы увидеть, что происходит, но я надеялся, что есть лучший способ.

Можно ли как-нибудь настроить docker на более подробный?

РЕДАКТИРОВАТЬ: Благодаря Эндрю Д. Теперь я знаю, что не так с кодом выше (я оставил его, чтобы его ответ можно было понять). Теперь проблема заключается в том, как я могу отладить что-то вроде этого или получить внутреннюю информацию о том, почему ls -l потерпел неудачу, почему ls не сделал.

РЕДАКТИРОВАТЬ: -D=true может дать больше вывода, но не в моем случае...

6 ответов

Решение

Докер events Команда может помочь, и команда Docker logs может извлечь журналы, даже если не удалось запустить образ.

Первый старт docker events на заднем плане, чтобы увидеть, что происходит.

docker events&

Затем запустите свой провал docker run ... команда. Тогда вы должны увидеть что-то вроде следующего на экране:

2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die

Затем вы можете получить шестнадцатеричный идентификатор запуска из предыдущего сообщения или выходных данных команды запуска. Затем вы можете использовать его с командой logs:

docker logs <copy the instance id from docker events messages on screen>

Теперь вы должны увидеть некоторые результаты неудачного запуска образа.

Как @alexkb предложил в комментарии: docker events& может быть неприятно, если ваш контейнер постоянно перезапускается из-за чего-то вроде сервиса AWS ECS. В этом случае может быть проще получить шестнадцатеричный идентификатор контейнера из журналов в /var/log/ecs/ecs-agent.log.<DATE>, Тогда используйте докер logs <hex id>,

Ну, лучшее, что я обнаружил, это:

#stop the current demon and start it in debug modus
sudo service docker stop
dockerd -D # --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 будет поврежден. Попробуйте запустить objdump или readelf для вашего.so файла после выполнения команды perl (до изменения LD_LIBRARY_PATH) вне контейнера - доллары, чтобы пончики теперь повреждены.

Причина, по которой он работает в этом крайне необходимом хаке, заключается в том, что "tmp" и "etc" имеют одинаковую длину строки, поэтому смещения не меняются. Рассмотрите каталог / dkr или аналогичный, если вы предпочитаете не использовать / tmp.

Если вы ДОЛЖНЫ использовать этот подход и ваши желаемые пути неизменны, пересоберите библиотеку и измените путь по умолчанию для / etc / hosts в исходном коде. Или лучше, когда собираешь свой модифицированный libnss_files.so переименуйте его в что-то вроде libnss_altfiles.so и изменить nsswitch.conf использовать hosts: altfiles при запуске вашего Docker-контейнера (кроме случаев, когда Docker также имеет привязанный монтированный файл nsswitch.conf, вы не можете его изменить). Это позволит вам иметь libnss_altfiles.so параллельно с вашими обычными библиотеками в базовой системе. Если docker выполняет bind-mount nsswitch.conf, оставьте копию вашего перестроенного libnss_files.so в каталоге / lib-override, готового для загрузки LD_LIBRARY_PATH.

Напротив, двоичные файлы suid/sgid игнорируют LD_LIBRARY_PATH и LD_PRELOAD, поэтому некоторые вещи могут сломаться (читай: вернитесь к использованию по умолчанию /etc/hosts), если вы используете эти переменные.

Иногда вы можете найти полезные сообщения об ошибках, запустив sshing в узел, на котором запущен демон docker, и затем выполните:

$ tail -f /var/log/containers/* /var/log/docker.log 2>&1

В "Docker Community Edition" в Mac OS вы можете подключиться к Docker vm, выполнив:

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

Когдаdocker logsне получится, поскольку контейнер еще не создан, его уже можно «присоединить» (с помощьюdocker run -aпереключатель) сообщение об ошибкеSTDERR(при этом придерживаясьSTDOUT), например:

      $ docker run -a STDERR -a STDOUT -i --rm --name ml-fs-db mirekphd/ml-fs-db:latest

Обратите внимание: если вы обычно запускаете контейнер в «отключенном» режиме (используя команду -dпереключатель, он не будет совместим с -a, отсюда и использование -iкак «интерактивный» здесь).

Другие вопросы по тегам