ENTRYPOINT有两种形式:
ENTRYPOINT [“executable”, “param1”, “param2”] [exec形式,首选]
ENTRYPOINT command param1 param2 [shell形式]
ENTRYPOINT指令用来配置创建容器时执行的容器命令。
例如,下面的示例将以默认页启动nginx,在80端口监听:
- docker run -i -t –rm -p 80:80 nginx
docker run [image]的命令行参数会附加到exec形式ENTRYPOINT所有元素的后面,且会覆盖使用CMD指定的所有元素。这允许命令行参数能够传递到entry point。如docker run [image] -d会传递-d参数到entry point。你可以你使用docker run –entrypoint标志来覆盖ENTRYPOINT指令。
shell形式的ENTRYPOINT能够阻止使用任何CMD或run命令行参数,不过不好的地方是ENTRYPOINT将以/bin/sh -c的子命令执行,且ENTRYPOINT收不到信号。意味着执行的命令的PID不是容器的PID 1 – 收不到来自主机的Unix信号 – 所以无法使用docker stop [container]停止容器。
仅是Dockerfile的最后一个ENTRYPOINT指令起作用。
exec形式ENTRYPOINT示例
你可以使用ENTRYPOINT的exec形式设置稳定的默认命令和参数,然后使用同样形式的CMD设置额外的可以修改的默认参数。
- FROM ubuntu
- ENTRYPOINT ["top", "-b"]
- CMD ["-c"]
当你运行容器,你会看到top是唯一的进程:
- $ 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
我们再看到top的具体参数:
- $ 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 test来停止这个容器。
下面的Dockerfile显示了使用ENTRYPOINT来在前台运行Apache[作为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信号:
- #!/bin/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 "$@"
最后,如果你需要在关闭或协调多个可执行程序时做些额外的清理工作,你需要确保ENTRPOINT脚本能够收到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来覆盖ENTRPOINT的设置,不过仅可以二进制到exec,如/usr/sbin/apache2 -k start[不仅调用sh -c执行]
shell形式ENTRYPOINT示例
可以为ENTRYPOINT指定一个纯字符串,它将运行在/bin/sh -c。这种形式将使用shell处理shell环境变量替换,将忽略任何的CMD或docker run命令行参数。为了确保docker stop能够正确发送信号到ENTRPOINT的可执行程序,记得使用exec执行:
- FROM ubuntu
- ENTRYPOINT exec top -b
运行这个镜像后,将会看到这个进程的PID为1:
- $ docker run -it –rm –name test top
- Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
- CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
- Load average: 0.08 0.03 0.05 2/98 6
- PID PPID USER STAT VSZ %VSZ %CPU COMMAND
- 1 0 root R 3164 0% 0% top -b
且可以使用docker stop停止进程:
- $ /usr/bin/time docker stop test
- test
- real 0m 0.20s
- user 0m 0.02s
- sys 0m 0.04s
如果忘记使用exec执行命令:
- FROM ubuntu
- ENTRYPOINT top -b
- CMD –ignored-param1
然后运行:
- $ docker run -it –name test top –ignored-param2
- Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
- CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq
- Load average: 0.01 0.02 0.05 2/101 7
- PID PPID USER STAT VSZ %VSZ %CPU COMMAND
- 1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2
- 7 1 root R 3164 0% 0% top -b
可以看到top进程的PID为是1了。
并且使用docker stop test不能停止进程:
- $ docker exec -it test ps aux
- PID USER COMMAND
- 1 root /bin/sh -c top -b cmd cmd2
- 7 root top -b
- 8 root ps aux
- $ /usr/bin/time docker stop test
- test
- real 0m 10.19s
- user 0m 0.04s
- sys 0m 0.03s
ENTRYPOINT和CMD使用建议
1.Dockerfile应该至少指定一个CMD或ENTRYPOINT指令。
2.当使用容器作为可执行程序时,应该定义ENTRYPOINT。
3.CMD应该用来设置ENTRYPOINT的默认参数。
4.当运行容器带有额外参数时,将会覆盖CMD的参数。