Как я могу отладить инициализацию 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
как «интерактивный» здесь).