最近在测试应用通过docker容器部署时发现,容器启动后无法自动启动NGINX和PHP程序,需要进入到容器内部来完成nginx和php的启动。
具体的指令就是:
docker exec -it 容器ID /bin/bash
/usr/local/nginx/sbin/nginx #启动nginx
/usr/local/php7/sbin/php-fpm #启动php
ps -ef | grep 'nginx'
ps -ef | grep 'php'
通过以上指令才能完成容器内部的程序启动,那有没有办法在启动docker容器时自动启动内部程序运行呢?
当然有!
通过运行shell脚本的方式:
我们在Dockerfile的同级目录下创建一个shell脚本,名字为start.sh
编写start.sh文件
#!/bin/bash
/usr/local/php7/sbin/php-fpm
/usr/local/nginx/sbin/nginx
然后我们重新编写Dockerfile文件
# base image
FROM ci:latest
# MAINTAINER
MAINTAINER sangshuaidong <sangshuaidong@comleader.com.cn>
# COPY
COPY ci.localhost.com* /www/
COPY ["start.sh", "/root/start.sh"]
RUN chmod -R 777 /www/
WORKDIR /root
#CMD
CMD ["/bin/bash","./start.sh"]
注释:COPY脚本文件start.sh到我们容器内部的root目录下,然后设置工作目录为root,然后通过CMD命令来运行start.sh文件.
我们先来看下CMD命令是用来做什么的?类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
COMMAND为docker容器的默认启动命令,查看容器镜像的Dockerfile,一般体现为 CMD ["命令"] ,如 CMD ["/bin/bash"]
每个容器都会有一个 pid 为 1 的进程,如果这个进程执行结束了,容器也就 close 了;
COMMAND 为 /bin/bash, 说明这个容器的初始进程就是 bash 进程;
默认情况下,docker logs <container_id> 也只会打印 pid 为 1 进程的输出
现在我们打包镜像,运行一下容器看看是否可以正常启动php和nginx服务
docker build -t ci:v3 .
docker iamges
启动容器:
docker run -dit -p 8080:80 -p 443:443 -p 9000:9000 --privileged=true --name=civ3 ci:v3
docker ps
我们发现容器没有启动成功,这是为什么呢?
我们分析下:
container 刚起来的时候,用户可以通过 dockerfile 中的 CMD,ENTRYPOINT,或者直接在 docker run 后面接 comand,来指定 container 启动时执行的程序。如果指定的程序只是一个短暂的任务,比如 echo sorry。那么,sorry,container 在输出 “sorry” 之后,就退出了。可以通过 docker inspect 看到,container 状态变成了 Exited。
docker build Dockerfile后,采用docker run –name xxx -d 运行容器,发现start.sh执行后容器就退出了,根本无法启动nginx和php。
分析了一下docker的机制,一个docker容器同时只能管理一个进程,这个进程退出后,容器也就退出了。这并不意味着一个容器里只能同时运行一个进程(那样太浪费了),只是最后一个运行的进程不能退出。
start.sh总结总结:
容器中最后一个守护进程一定要用前台方式运行,否则start.sh退出,容器退出,所有的服务就白启动
解决方法
可以利用tail -f /dev/null让容器一直处于runing状态,用CMD 执行一个脚本,在脚本中启动多个服务。
例如我们要执行start.sh这个脚本,利用这个脚本启动主服务,并执行tail -f /dev/null:
我们重新编写start.sh文件 只需要在末尾加上tail -f /dev/null
#!/bin/bash
/usr/local/php7/sbin/php-fpm
/usr/local/nginx/sbin/nginx
tail -f /dev/null
然后我们重新按照上面流程打包镜像,启动容器即可!
发现 php和nginx程序都是运行状态!
那除了shell脚本方式运行 还有其他方式么?待更....
评论