如何在Docker容器中默认启动php-fpm?

27

我有这个Docker镜像 -

FROM centos:7
MAINTAINER Me <me.me>
RUN yum update -y
RUN yum install -y git https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

RUN yum install -y ansible
RUN git clone https://github.com/.../dockerAnsible.git
RUN ansible-playbook dockerFileBootstrap.yml
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

VOLUME [ "/sys/fs/cgroup" ]
EXPOSE 80 443 3306

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

基本上,我想让php-fpm在docker容器启动时开始运行。如果我手动进入容器并使用/usr/sbin/php-fpm打开它,那么php-fpm可以正常工作。

我尝试在我的ansible文件中使用此命令(它没有起作用)。我还尝试使用服务模块,但没有成功。

 - name: Start php fpm
   command: /usr/sbin/php-fpm

我该如何让php-fpm与apache同时运行?


要添加 RUN /usr/sbin/php-fpm 吗? - Shanoor
1
不行。使用此方法启动容器后,它仍然无法启动。 - J. Doe
7个回答

27

我来到这里是为了寻找如何在Docker容器中将php-fpm运行在前台,使其成为PID 1。解决方案为:

我来到这里是为了寻找如何在Docker容器中将php-fpm运行在前台,使其成为PID 1。解决方案为

php-fpm -F -R

说明

我们可以使用php-fpm --help命令来查看可用选项。

-F, --nodaemonize 
      force to stay in foreground, and ignore daemonize option from config file
如果您在Docker容器中运行php-fpm,那么很有可能您是以root用户身份运行该进程的。如果要以root用户身份启动php-fpm,则需要使用额外的标志:

如果您在Docker容器中运行php-fpm,那么很有可能您是以root用户身份运行该进程的。如果要以root用户身份启动php-fpm,则需要使用额外的标志:

  -R, --allow-to-run-as-root
        Allow pool to run as root (disabled by default)

3
嗨,将php-fpm以root用户身份运行安全吗?我有些担心。 - Dylan B
2
此答案仅适用于在容器化环境中运行php-fpm。如果您没有使用docker或其他容器,以root身份运行php-fpm会大大增加黑客攻击的风险。 - ckeeney
2
这个命令在 Dockerfile 中不起作用,而这个答案的使用情况就是针对 Dockerfile 的。 - Andrew Koster
我在bash启动脚本的末尾使用了这个命令,以便进行大量自定义配置。但是-R选项有点可怕。如果您正在使用官方基础镜像,则应将其作为www-data运行。 - Throttlehead

27

您应该使用supervisor来启动多个服务。

在您的dockerfile中,安装supervisor,然后启动。

COPY ./docker/supervisord.conf /etc/supervisord.conf
....
CMD ["/usr/bin/supervisord", "-n"]

你的 docker/supervisord.conf 文件包含了所有你想要启动的服务,因此你可以像这样设置:

[program:php-fpm]
  command=/opt/remi/php70/root/usr/sbin/php-fpm -c /etc/php-fpm.conf
  ;command=/usr/sbin/php70-fpm -c /etc/php-fpm.d
  stdout_logfile=/dev/stdout
  stdout_logfile_maxbytes=0
  stderr_logfile=/dev/stderr
  stderr_logfile_maxbytes=0

[program:nginx]
  command=/usr/sbin/nginx
  stdout_logfile=/dev/stdout
  stdout_logfile_maxbytes=0
  stderr_logfile=/dev/stderr
  stderr_logfile_maxbytes=0

当然,您应该根据您的路径、php-fpm版本和服务 (例如 nginx、apache 等) 进行适应,但基本上 supervisor 是管理从一个启动点开始启动多个服务的最佳方法。

在这里,您可以找到 Docker 官方关于 supervisor 的文档。

https://docs.docker.com/engine/admin/using_supervisord/


2
虽然这种方法似乎可以工作,但对于我需要启动的仅一个额外服务来说,它似乎有些过度。是否可能像链接我的CMD一样,或在Docker容器初始化时启动它? - J. Doe
1
另一个选择是在另一个容器中运行php-fpm,并将这两个容器放在同一个网络上。然后将php-fpm httpd配置指向另一个容器。 - Matt
4
我并不觉得这个方法过于繁琐,supervisor 是处理多处理器管理的普遍方式,也是Docker推荐的方式,只需要稍微更改一下你的Docker文件和一个配置文件。如果你想在以后添加一些服务,你的容器会变得更加灵活。但是如果你发现了一种更简单的“合法”方法,请告诉我们,我很感兴趣。 - olibiaz
建议增加另一层复杂性并不是一个好答案。我会将其投下反对票。 - zeros-and-ones
1
我们应该考虑现在的容器确实是为单个服务而设计的。从这个角度来看,这个答案是合法的。 - fschuindt
显示剩余2条评论

18

我最近需要类似的东西。对于 alpine Linux 镜像,只需将 php-fpm 和 Web 服务器作为容器命令运行即可。在 Dockerfile 中定义如下:

CMD /usr/bin/php-fpm -D; nginx

例如,将 php-fpm 守护进程化,然后在前台运行 nginx

ubuntu/debian 镜像中,还需要通过运行以下 Dockerfile RUN 命令来允许启动最近安装的软件包:

RUN echo "exit 0" > /usr/sbin/policy-rc.d

然后在 CMD 命令中重启 php-fpm

CMD /etc/init.d/php7.0-fpm restart && nginx -g "daemon off;"

关于 policy-rc.d 的更多信息可以在这个 askubuntu 问题中找到。


1
我的朴实无华的朋友,第三个方案完美解决了问题。谢谢。 :-) - We are Borg
第一行就像魔法一样好用,谢谢,省去了我使用主管的麻烦。 - Eman

3

如果您想在同一个容器中运行php-fpmApache(通常使用MPM事件),则可能会发现此配置很有用:

[supervisord]

[program:php-fpm]
command=php-fpm -F -R
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:apachectl]
command=apachectl -D "FOREGROUND" -k start
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

2

在运行nginx和php-fpm的Ubuntu 20.04上,我在Docker上成功运行了此操作。

CMD /etc/init.d/php7.4-fpm start -F && nginx -g "daemon off;"

不需要监督员或定时任务。


我还建议您创建一个 ARG phpver=7.4,然后将其更通用化,如下所示:RUN cp /etc/init.d/php${phpver}-fpm /etc/init.d/php-fpm。然后添加 CMD /etc/init.d/php-fpm start -F && nginx -g "daemon off;"。以后您可以从 ARG 行更改 PHP 版本。 - Dimitar Atanasov

1

1

我使用rc.local来启动容器内的服务,然后在容器内运行一个命令来执行rc.local。以下是一个示例运行命令:

sudo docker run --restart=always -itd --name mycontainer -p 80:80 -p 443:443 myimage/name /bin/bash -c "/etc/rc.local && while true; do echo hello world; sleep 100; done"

这是来自 /etc 的 rc.local 文件之一。

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sleep 5
service mysql start
sleep 5
service php5-fpm start
sleep 5
service nginx start
exit 0

这个命令会启动一个名为"mycontainer"的容器,使用镜像"myimage/name",并暴露80和443端口。启动后,它会依次调用mysql、php5-fpm和nginx来启动,每个服务之间暂停5秒钟。通过这种方式,您可以在容器中运行任何想要运行的服务。请记得为这些服务添加开放的端口。
此运行命令还会将"Hello World"附加到日志文件中,每100秒作为"脉冲",让您知道何时运行和停止。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接