TL-DR
docker ps --no-trunc
和docker inspect CONTAINER
提供了启动容器的入口点及其命令,但可能会丢失某些部分,例如${ANY_VAR}
,因为容器环境变量不会作为解析结果打印出来。
为了克服这个问题,docker inspect CONTAINER
有一个优势,它还允许从Config.Env
属性中分别检索在容器中定义的环境变量及其值。
docker ps
和docker inspect
提供有关执行入口点及其命令的信息。通常,这是一个包装入口点脚本(.sh
)而不是容器启动的“真正”程序。要获取有关此信息的信息,请使用ps
或/proc/1/cmdline
请求进程信息。
1)docker ps --no-trunc
它打印所有正在运行的容器的入口点和所执行的命令。虽然它打印传递给入口点的命令(如果我们传递了它),但不显示Docker环境变量的值(例如$FOO
或${FOO}
)。
例如,运行alpine容器:
docker run --name alpine-example -e MY_VAR=/var alpine:latest sh -c 'ls $MY_VAR'
当使用像下面这样的docker -ps命令:
docker ps -a --filter name=alpine-example --no-trunc
它的输出为:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b064a6de6d8417... alpine:latest "sh -c 'ls $MY_VAR'" 2 minutes ago Exited (0) 2 minutes ago alpine-example
我们可以看到传递给entrypoint的命令:sh -c 'ls $MY_VAR'
,但是实际上$MY_VAR
没有被解析。
2)docker inspect CONTAINER
当我们检查alpine-example容器时:
docker inspect alpine-example | grep -4 Cmd
虽然有命令,但我们仍然看不到环境变量的值:
"Cmd": [
"sh",
"-c",
"ls $MY_VAR"
],
事实上,我们无法通过这些docker命令看到插值变量。
然而,作为一种权衡,我们可以使用docker inspect分别显示容器的命令和环境变量:
docker inspect alpine-example | grep -4 -E "Cmd|Env"
这将会打印:
"Env": [
"MY_VAR=/var",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"sh",
"-c",
"ls $MY_VAR"
]
更符合docker的方式是使用
docker inspect
命令的
--format
标志,它允许指定要呈现的JSON属性:
docker inspect --format '{{.Name}} {{.Config.Cmd}} {{ (.Config.Env) }}' alpine-example
这将输出:
/alpine-example [sh -c ls $MY_VAR] [MY_VAR=/var PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]
3) 对于正在运行的容器,从容器本身中检索启动的进程
Docker执行的入口点和命令可能有所帮助,但在某些情况下,这是不够的,因为这只是一个负责启动真正/核心进程的包装入口点脚本(.sh
)。
例如,当我运行Nexus容器时,执行并显示运行容器的命令是"sh -c ${SONATYPE_DIR}/start-nexus-repository-manager.sh"
。
对于PostgreSQL,它是"docker-entrypoint.sh postgres"
。
要获取更多信息,我们可以在运行的容器上执行docker exec CONTAINER ps aux
。
它可能会打印其他我们可能不感兴趣的进程。
为了缩小到入口点启动的初始进程,我们可以执行以下操作:
docker exec CONTAINER ps -1
我指定1
是因为entrypoint所执行的进程通常具有1
ID。
即使没有ps
,我们仍然可以在/proc/1/cmdline
中找到信息(在大多数Linux发行版中,但不是所有发行版都是如此)。例如:
docker exec CONTAINER cat /proc/1/cmdline | sed -e "s/\x00/ /g"; echo
如果我们可以访问启动容器的Docker主机,另一个获取entrypoint执行的进程完整命令的替代方法是:
执行 ps -PID
,其中PID是Docker守护程序创建的用于运行容器的本地进程,例如:
ps -$(docker container inspect --format '{{.State.Pid}}' CONTAINER)
使用docker ps实现易于理解的格式化
docker ps --no-trunc
并不总是易于阅读。指定要打印的列并以表格形式呈现可能会使其更好:
docker ps --no-trunc --format "table{{.Names}}\t{{.CreatedAt}}\t{{.Command}}"
创建别名可能会有所帮助:
alias dps='docker ps --no-trunc --format "table{{.Names}}\t{{.CreatedAt}}\t{{.Command}}"'