CMD ENTRYPOINT 都有两种格式:数组类型, 列表类型(个人理解)
CMD ["executable","param1","param2"] ##数组模式
CMD command param1 param2 ##列表模式
ENTRYPOINT ["executable", "param1", "param2"] ##数组模式
ENTRYPOINT command param1 param2 ##列表模式
两种类型的区别是:数组类型会做为命令直接执行,作为容器中 PID=1 的主进程。而列表形式为进程号1的进程是 /bin/sh -c
的进程。
二者区别:
- 如果同时存在ENTRYPOINT和CMD,CMD中的参数会追加到 ENTRYPOINT 的参数之后,即:
ENTRYPOINT
的优先级比CMD
更高,而且与 dockerfile 文件中二者的编码顺序无关 -
ENTRYPOINT
出现多次,或者CMD
出现多次,dockerfile 编码顺序靠后的会覆盖前面的 - docker run 命令的参数(如:
docker run -it --rm ubuntu ps aux
的ps aux
参数)会覆盖掉 CMD 命令的所有参数(包括如果是列表模式的时候的/bin/sh -c
参数),如果没有 dockerfile 中没有CMD则会忽略掉 run 命令中的参数(前面实例中的ps aux
) - dockerfile FROM 应用的时候也适用前面规则
- 附加一条规则:ENTRYPOINT在数组模式的时候CMD的参数才有效,否则忽略。
举例
FROM ubuntu
ENTRYPOINT ["ps", "aux"]
执行 sudo docker build . -t test && sudo docker run --rm test
结果:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.0 0.0 25964 1212 ? Rs 18:37 0:00 ps aux
FROM ubuntu
CMD ["ps", "aux"]
执行docker build . -t test && sudo docker run --rm test
结果:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 25964 1212 ? Rs 18:40 0:00 ps aux
执行: docker build . -t test && sudo docker run --rm test -ef
结果
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:40 ? 00:00:00 ps -ef
FROM ubuntu
CMD ps aux
执行:sudo docker build . -t test && sudo docker run --rm test
结果
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4492 644 ? Ss 18:46 0:00 /bin/sh -c ps aux
root 5 0.0 0.0 34412 1432 ? R 18:46 0:00 ps aux
FROM ubuntu
ENTRYPOINT ["ps"]
CMD ["aux"]
执行:docker build . -t test && sudo docker run --rm test
结果
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 25964 1212 ? Rs 18:50 0:00 ps aux
执行:docker build . -t test && sudo docker run --rm test -ef
结果
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:52 ? 00:00:00 ps -ef
如果 ENTRYPOINT 使用列表模式拼接CMD格式例如 dockerfile 如下:
FROM ubuntu
ENTRYPOINT "ps" "aux"
CMD echo "hello"
执行 sudo docker build . -t test && sudo docker run --rm test
结果是:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4492 644 ? Ss 18:23 0:00 /bin/sh -c "ps" "aux" /bin/sh -c echo "hello"
root 5 0.0 0.0 34412 1432 ? R 18:23 0:00 ps aux
这时 CMD 的参数会被忽略。如果执行 sudo docker build . -t test && sudo docker run --rm test hello
结果是
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4492 644 ? Ss 18:26 0:00 /bin/sh -c "ps" "aux" hello
root 5 0.0 0.0 34412 1428 ? R 18:26 0:00 ps aux
这时 run 中的参数也会被忽略(注意/bin/sh -c
未出现)
总结就是:
- 只有在
ENTRYPOINT ["executable", "param1", "param2"]
数组模式的时候CMD的参数和docker run
后的参数才有效。
另外 数组模式的好处是到容器被关机的时候(docker stop …), 进程 PID=1 会获取到中断信号,应用可以做优雅的关机操作,而列表模式应用进程 PID!=1,无法获取到中断信号
最后建议 如果作为基础容器被其他容器 FROM 建议使用 CMD ,而不使用 ENTRYPOINT。 如果使用 ENTRYPOINT 则应该使用 数组模式,并使用CMD的数组模式。