Что такое PID в хосте, процесс, выполняющийся внутри контейнера Docker?

Есть несколько процессов, выполняемых в контейнере Docker, их PID изолированы в пространстве имен контейнеров, есть ли способ выяснить, каковы их PID на хосте Docker?

Например, веб-сервер Apache работает внутри контейнера Docker (я использую Apache + PHP-образ из Docker Hub), а Apache при его запуске создает больше рабочих процессов внутри контейнера. Эти рабочие процессы фактически обрабатывают входящие запросы. Чтобы просмотреть эти процессы, я запускаю pstree внутри контейнера pstree:

# pstree -p 1
apache2(1)-+-apache2(8)
           |-apache2(9)
           |-apache2(10)
           |-apache2(11)
           |-apache2(12)
           '-apache2(20)

Родительский процесс Apache выполняется на PID 1 внутри пространства имен процессов контейнера. Однако с точки зрения хоста он также может быть доступен, но его PID на хосте отличается и может быть определен с помощью команды docker compose:

 $ docker inspect --format '{{.State.Pid}}' container
 17985

Из этого можно видеть, что PID 1 из пространства имен контейнерных процессов отображается на PID 17985 на хосте. Поэтому я могу запустить pstree на хосте, чтобы pstree процесса Apache:

$ pstree -p 17985
apache2(17985)─┬─apache2(18010)
               ├─apache2(18011)
               ├─apache2(18012)
               ├─apache2(18013)
               ├─apache2(18014)
               └─apache2(18164)

Из этого я предполагаю, что так же, как PID 1 в контейнере сопоставляется с PID 17985 на хосте, он также отображает:

  • PID 8 в контейнере до PID 18010 на хосте и
  • PID 9 - PID 18011;
  • PID 10 до PID 18012 и так далее...

(Это позволяет мне отлаживать процессы из контейнера докеров, используя инструменты, доступные только на хосте, а не в контейнере, например, strace)

Проблема в том, что я не знаю, насколько безопасно предположить, что pstree перечисляет процессы в том же порядке как в контейнере, так и в хосте.

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

Ответ 1

Вы можете посмотреть файл /proc/<pid>/status чтобы определить сопоставление между PID пространства имен и глобальным PID. Например, если в контейнере докера я запускаю несколько процессов sleep 900, например:

# docker run --rm -it alpine sh
/ # sleep 900 &
/ # sleep 900 &
/ # sleep 900 &

Я вижу, как они работают в контейнере:

/ # ps -fe
PID   USER     TIME   COMMAND
    1 root       0:00 sh
    7 root       0:00 sleep 900
    8 root       0:00 sleep 900
    9 root       0:00 sleep 900
   10 root       0:00 ps -fe

Я могу посмотреть на них на хосте:

# ps -fe | grep sleep
root     10394 10366  0 09:11 pts/10   00:00:00 sleep 900
root     10397 10366  0 09:12 pts/10   00:00:00 sleep 900
root     10398 10366  0 09:12 pts/10   00:00:00 sleep 900

И для любого из них я могу посмотреть файл status чтобы увидеть пространство имен pid:

# grep -i pid /proc/10394/status
Pid:    10394
PPid:   10366
TracerPid:  0
NSpid:  10394   7

Глядя на строку NSpid, я вижу, что в пространстве имен PID этот процесс имеет pid 7. И действительно, если я убью процесс 10394 на хосте:

# kill 10394

Затем в контейнере я вижу, что PID 7 больше не работает:

/ # ps -fe
PID   USER     TIME   COMMAND
    1 root       0:00 sh
    8 root       0:00 sleep 900
    9 root       0:00 sleep 900
   11 root       0:00 ps -fe