strace для мониторинга активности Dockerized приложений

Моя цель - отслеживать, какие порты открываются и закрываются многопроцессорным приложением. Мой план состоит в том, чтобы запустить приложение в контейнере Docker, чтобы изолировать его, а затем использовать strace для отчета об активности приложения.

Я пробовал с докеризированным сервером Apache:

strace -f -o /tmp/docker.out docker run -D -P apache

Я не вижу ни одной строки в файле отчета, показывающей, что приложение принимает соединение в сокете.

Может ли strace сообщать об активности процессов внутри контейнера?


person Guillaume Delafosse    schedule 23.06.2015    source источник


Ответы (5)


Проблема с вашей комбинацией command+strace заключается в том, что у docker есть модель клиент/сервер, а ваш docker run представляет клиентскую сторону транзакции REST API, чтобы попросить демона docker запустить контейнер Apache от вашего имени. . В зависимости от того, как настроен ваш клиент, этот контейнер может даже не работать в той же системе, в которой вы вводите команду docker run.

Однако в самом простом случае, когда клиент Docker и демон находятся в одной системе, вы можете использовать ps найти PID работающего сервера Apache и использовать strace для присоединения и отслеживания уже запущенного процесса, если этого достаточно. для ваших потребностей в отслеживании.

Учитывая, что мне пришлось отлаживать несколько проблем с ранним запуском с помощью «runc», исполнителя для контейнеров в версии докера 1.11 и выше, я также создал небольшую оболочку для docker-runc, которая strace является процессом контейнера с самого начала (извне системы, поэтому strace не требуется в файловой системе контейнера). Вы можете найти его здесь, на GitHub, хотя справедливо предупреждаю, что он несколько глючит для регулярного использования, так как я считаю, что вызов оболочки + strace мешает некоторой передаче сигналов между containerd и реальным docker-runc и связанными процессами. Более элегантным решением могло бы быть создание варианта runc, который знает, как добавить перед фактическим началом содержащегося процесса оболочку strace, а не перехватывать весь вызов runc в strace.

person Phil E    schedule 06.09.2016
comment
Префикс docker был удален из docker-runc. github.com/docker/for-linux/issues/486 Итак, если кто-то ищет файл для замены, вам нужно искать runc вместо docker-runc. - person Alex; 16.06.2020

Взгляните на решение, описанное в https://medium.com/@rothgar/how-to-debug-a-running-docker-container-from-a-separate-container-983f11740dc6, в котором рассказывается, как запустить контейнер с установленным strace, который находится в том же пространстве имен pid и network, что и контейнер/процесс, для которого вы хотите запустить strace.

Это хорошо, поскольку означает, что вам не нужно устанавливать strace в контейнере, который вы хотите отлаживать.

Суть его в том, что при отладке контейнера (caddy в приведенном ниже примере) вы запускаете док-контейнер под названием strace с установленными соответствующими инструментами:

docker run -t --pid=container:caddy \
  --net=container:caddy \
  --cap-add sys_admin \
  --cap-add sys_ptrace \
  strace

Предполагая, что вы сделаете это при сборке контейнера strace, у вас теперь будет оболочка с соответствующими инструментами, из которой вы сможете запустить ps и увидеть процесс в контейнере caddy, а также запустить против него strace.

Вы будете в другом контейнере с другой файловой системой, но вы можете видеть файловое пространство целевого контейнера в /prof/$PID/root.

person mc0e    schedule 11.03.2017

Мне только что удалось найти контейнер докеров, выполнив следующие действия:

  1. Выясните, на каком образе дистрибутива основан контейнер, затем получите двоичный файл strace из этого дистрибутива, например. установив соответствующий дистрибутив из контейнера, созданного для этой цели.

  2. Скопируйте двоичный файл strace в том, который вы можете подключить к контейнеру.

  3. Также создайте небольшой сценарий оболочки-оболочки с именем entry.sh, который содержит ваш вызов strace. В моем случае я написал это так:

    #!/bin/sh
    exec /path/to/strace -ff -o /path/to/dumps /bin/bash /original/entrypoint
    

    Предполагается, что исходная точка входа, которую вы читаете из Dockerfile образа, который хотите отладить, начинается с #!/bin/bash. Убедитесь, что вы установили бит выполнения этого скрипта и поместите его туда, где вы также разместили двоичный файл strace.

  4. Запустите докер с помощью такой команды:

    docker run -v $PWD/shared:/path/to \
               --entrypoint="/path/to/entry.sh" \
               --cap-add SYS_PTRACE \
               image-name
    

Смонтированный том сделает strace и entry.sh доступными внутри докера. Точка входа выполнит вызов strace перед вызовом фактической точки входа. Это потенциально может вызвать некоторые проблемы с тем, что strace сам станет pid 1 в контейнере и не сможет собрать дочерние элементы. Если это проблема, лучше использовать другой подход, подобный предложенному Филом. Наконец, эта добавленная возможность сообщает докеру, что можно начинать трассировку процессов. В противном случае вы получите сообщения об ошибках, например

strace: …: PTRACE_TRACEME doesn't work: Operation not permitted

На самом деле указание на эту настройку возможности является причиной, по которой я пишу свой ответ. Я уже сделал шаги, кроме этого флага, и, ища там решение, я нашел и этот вопрос здесь, и запись в блоге Джона Гулы, содержащая эту информацию. Для полноты картины я думаю, что здесь следует упомянуть и флаг. Еще не пробовал подход Фила, поэтому я определенно не утверждаю, что мой подход лучше того, что он предложил. Я предполагаю, что это может работать легче в системах, где вы не хотите связываться с демоном докера.

person MvG    schedule 09.12.2016

мы можем добавить параметр --security-opt=seccomp:unconfined

Я пробовал, работает хорошо!!

docker run -it   --security-opt=seccomp:unconfined  centos:7 /bin/bash

yum install strace
strace ls

execve("/usr/bin/ls", ["ls"], [/* 8 vars */]) = 0
brk(NULL)                               = 0x1d0a000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 
0) = 0x7ffb588da000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or 
directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

см.: http://johntellsall.blogspot.com/2016/10/tip-use-strace-to-debug-issues-inside.html

person Xu Dong    schedule 30.10.2018
comment
У меня не сработало: unknown flag: --security-opt. Версия Docker 18.06.1-ce, сборка e68fc7a. - person Christian Aichinger; 26.02.2019

попробуйте запустить Apache docker run -D -P apache и подключиться внутри docker exec -it container_id bash, а затем strace вашего процесса Apache.

person user2915097    schedule 23.06.2015
comment
Ваше предложение подразумевает, что strace должен быть установлен в образе Docker, который я хочу отслеживать, чего я не мог предположить. - person Guillaume Delafosse; 24.06.2015