Dockerfile 之 ENTRYPOINT
Posted 秋风小凉鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dockerfile 之 ENTRYPOINT相关的知识,希望对你有一定的参考价值。
ENTRYPOINT入口点有两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
(exec form, preferred)ENTRYPOINT command param1 param2
(shell form)
ENTRYPOINT 允许您配置将作为可执行文件运行的容器。
例如,下面将启动nginx的默认内容,监听端口80:
docker run -i -t --rm -p 80:80 nginx
docker run <image> 的命令行参数将追加到 exec form ENTRYPOINT中的所有元素之后,并将覆盖使用CMD指定的所有元素。这允许参数被传递到入口点,即 docker run <image> -d 将把-d参数传递给入口点。您可以使用 docker run --entrypoint 标志覆盖ENTRYPOINT指令。
shell form 可以防止使用任何CMD或run命令行参数,但是有一个缺点,即您的入口点将作为/bin/sh -c的子命令启动,该命令不传递信号。这意味着可执行文件不是容器的PID 1,也不会收到Unix信号,所以你的可执行文件不会收到来自docker stop <container>的SIGTERM。
只有Dockerfile中的最后一条ENTRYPOINT指令才会起作用。
一、exec form 的ENTRYPOINT 例子
您可以使用ENTRYPOINT的exec形式来设置相当稳定的默认命令和参数,然后使用CMD的任何一种形式来设置更可能更改的其他默认值。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
当你运行容器,你可以看到顶部是唯一的进程:
$ docker run -it --rm --name test top -H
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
要进一步检查结果,可以使用docker exec:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
您可以使用docker stop测试优雅地请求top关闭。
下面的Dockerfile展示了如何使用ENTRYPOINT在前台运行Apache(即, as PID 1):
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
如果需要为单个可执行文件编写启动脚本,可以使用exec和gosu命令确保最终可执行文件接收到Unix信号:
#!/usr/bin/env bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"
最后,如果您需要在关闭时做一些额外的清理(或与其他容器通信),或正在协调多个可执行文件,您可能需要确保ENTRYPOINT脚本接收到Unix信号,然后将它们传递下去,然后再做一些工作:
#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too
# USE the trap if you need to also do manual cleanup after the service is stopped,
# or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM
# start service in background here
/usr/sbin/apachectl start
echo "[hit enter key to exit] or run 'docker stop <container>'"
read
# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop
echo "exited $0"
如果你用docker run -it --rm -p 80:80 --name test apache
,来运行这个镜像,你可以用docker exec或docker top来检查容器的进程,然后让脚本停止apache:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
$ docker top test
PID USER COMMAND
10035 root run.sh /bin/sh /run.sh 123 cmd cmd2
10054 root /usr/sbin/apache2 -k start
10055 33 /usr/sbin/apache2 -k start
10056 33 /usr/sbin/apache2 -k start
$ /usr/bin/time docker stop test
test
real 0m 0.27s
user 0m 0.03s
sys 0m 0.03s
注意:您可以使用--entrypoint 覆盖ENTRYPOINT设置,但这只能将二进制设置为exec(不使用sh -c)。
二、 了解CMD和ENTRYPOINT是如何交互的
CMD和ENTRYPOINT指令都定义了在运行容器时执行什么命令。很少有规则描述他们的合作。
- Dockerfile应该指定至少一个CMD或ENTRYPOINT命令。
- 在将容器用作可执行文件时,应该定义ENTRYPOINT。
- CMD应该用作定义ENTRYPOINT命令的默认参数或在容器中执行特别命令的方法。
- 当运行带有可选参数的容器时,CMD将被覆盖。
下表显示了对不同的 ENTRYPOINT
/ CMD
组合执行什么命令:
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
以上是关于Dockerfile 之 ENTRYPOINT的主要内容,如果未能解决你的问题,请参考以下文章
Dockerfile 中的 CMD 和 ENTRYPOINT 有啥区别?
Dockerfile中CMD命令和ENTRYPOINT 命令的说明
Dockerfile 中 CMD 和ENTRYPOINT 的区别