Короткий ответ
Обычный docker exec sh не сработает, так как shell отсутствует; можно извлечь файлы через docker cp, либо запустить отдельный debug-контейнер (например, на базе busybox), разделяющий сетевые и/или PID namespaces с целевым контейнером через --network container:ID и --pid container:ID.
Как это работает подробнее
docker run --network=container:TARGET --pid=container:TARGET busybox sh создаёт новый, полноценный контейнер с инструментами внутри, но подключает его к тем же namespaces, что у целевого — в результате из debug-контейнера видно те же процессы (ps aux покажет процессы целевого контейнера) и ту же сетевую конфигурацию (можно сделать curl localhost:PORT, как если бы запрос шёл из самого целевого контейнера).
Пример кода
Пример конфигурации
$ docker run -it --rm --network=container:app --pid=container:app busybox sh
/ # ps aux
PID USER COMMAND
1 65532 /app
/ # wget -qO- http://localhost:8080/health
{"status":"ok"}Что использовать на практике
- Практика. такой подход позволяет диагностировать сетевые проблемы (слушает ли приложение порт, отвечает ли локально) и процессный статус, не устанавливая никаких дополнительных инструментов в сам production-образ и не раздувая его ради редких случаев отладки. Файловую систему целевого контейнера при этом так просмотреть не получится — для конкретных файлов используют
docker cp CONTAINER:/path ./local-path.
Подводные камни
- Риск. пытаются временно пересобрать и задеплоить debug-версию образа с установленным shell прямо в production ради одной диагностики, что рискованно и медленно; забывают, что
docker cpработает и для остановленных (но не удалённых) контейнеров, и пытаются искать более сложные пути для простого извлечения файла.