docker容器中的前台程序和后台程序,为什么一定要前台运行

docker 容器默认会把容器内部第一个进程,也就是 pid=1 的程序作为docker容器是否正在运行的依据,如果docker容器中 pid = 1 的进程挂了,那么docker容器便会直接退出,也就是说Docker容器中必须有一个前台进程,否则认为容器已经挂掉。

为了验证这一点,我写了两个go程序并静态编译为可执行程序,common 和 daemon ,他们即可前台运行也可后台运行

前台运行

./common 
./daemon 

后台运行

./common serve -d 
./daemon -d 

我们通过这两个程序来构建镜像,看他们是如何运行的。

Dockerfile 文件内容:

FROM alpine

ADD daemon /data/www/
ADD common /data/www/
WORKDIR /data/www

CMD cd /data/www/ && ./daemon -d && ./common 

执行命令

docker build -t common .

docker run --name common -d common 

docker exec -it common sh 

ps -ef 
PID   USER     TIME  COMMAND
    1 root      0:00 ./common 
    9 root      0:00 ./daemon
   16 root      0:00 sh
   26 root      0:00 ps -ef

exit 
docker stop common 
docker rm common 
docker rmi common 

修改 Dockerfile 文件的 CMD 指令,重新构建,并运行

CMD cd /data/www/ && ./common -d && ./daemon
ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 ./daemon
    9 root      0:00 ./common
   16 root      0:00 sh
   21 root      0:00 ps -ef

再次修改 Dockerfile 文件的 CMD 指令,重新构建,并运行

CMD cd /data/www/ && ./common && ./daemon
ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 ./common && ./daemon
   16 root      0:00 sh
   20 root      0:00 ps -ef

由此可见docker容器运行后,会将CMD中的第一个前台进程作为pid=1的进程,而不管在它之前是否还有别的进程。
第一个前台进程后面无法再执行别的进程,因为前台进程会阻塞,所有后面的命令就成为了此进程的参数了。

所以,如果想在一个容器里面启动多个后台进程加一个前台进程,那么这个前台进程要写在最后面。

这也是为什么,Docker容器启动web服务时,都指定了前台运行的参数。
例如apache:

ENTRYPOINT [ "/usr/sbin/apache2" ]
CMD ["-D", "FOREGROUND"]

又例如nginx:

ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]

进入nginx容器,查看进程

ps -ef |grep nginx
root         1     0  0 Oct16 ?        00:00:00 nginx: master process nginx -g daemon off;
nginx       19     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       20     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       21     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       22     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       23     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       24     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       25     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       26     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       27     1  0 Oct16 ?        00:00:00 nginx: worker process
nginx       28     1  0 Oct16 ?        00:00:00 nginx: worker process

从这个意义上来讲,一个程序从宿主机迁到docker容器,程序是需要做一些调整的。

或者启动额外的进程来充当pid=1的前台进程,例如上面的 daemon 进程。

当然 linux 系统下也提供了一些阻塞的指令,比如:
tali -f xxx
或者
top

但是不管怎么样,pid=1的进程必须存在。

你可能感兴趣的:(docker)