Dockerize 用于生产的 PHP 应用程序

Erf*_*fun 7 php containers docker

我们有一个 PHP(特别是 Laravel)应用程序,应该针对生产环境进行 dockerized。但是与 Web 服务器和 PHP-FPM 容器共享应用程序源代码存在问题。

Nginx 和 PHP-FPM 都应该可以访问应用程序源代码,所以这里是网络上建议的解决方法:

  1. 有两个独立的 Nginx 和 PHP-FPM 容器,并在主机上安装源代码并创建一个卷。然后,将此卷分配给这些容器。这种解决方案是不可取的,因为每次应用程序代码更改时,都应该重新构建整个堆栈并刷新创建的卷。此外,这些任务应该在我们所有的服务器上执行,这可能会浪费很多时间。
  2. 将 PHP-FPM 和 Nginx 放在同一个容器上,并supervisor使用entrypoint脚本或脚本保持它们的进程运行。在这个解决方案中,当源代码发生变化时,我们构建一次映像,希望没有共享卷要刷新,所以这似乎是一个很好的解决方法。但是,这个解决方案的主要问题是它违反了容器化背后的思想。Docker在其文档中说:

    每个容器应该有一个问题(或正在运行的进程)。

    但是在这里,我们有两个正在运行的进程!

有没有其他解决方案可以在生产环境中使用?我不得不提一下,我们将在不久的将来使用SwarmKubernetes

谢谢。

Adi*_*iii 2

一般来说,在生产中应该避免这两种方法,但如果我比较卷安装和每个容器两个进程,我会选择每个容器两个进程,而不是将主机代码安装到容器,

在某些情况下,第一种方法会失败,例如Fargate的情况,其中没有属于无服务器的主机,那么在这种情况下,您肯定会为每个容器运行两个进程。

每个容器运行多个进程的主要问题是“如果 php-fpm 关闭而 Nginx 进程正在运行怎么办”。但你可以用多种方法处理这种情况,你可以通过 docker 文档查看建议的方法。

docker-multi-service_container

docker 文档使用自定义脚本或supervisord 介绍了这种情况。

如果您需要在容器内运行多个服务,可以通过几种不同的方式来完成此任务。

  • 将所有命令放入包装脚本中,并附上测试和调试信息。作为 CMD 运行包装器脚本。这是一个非常幼稚的例子。首先,包装脚本:
#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container exits with an error
# if it detects that either of the processes has exited.
# Otherwise it loops forever, waking up every 60 seconds

while sleep 60; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit 1
  fi
done
Run Code Online (Sandbox Code Playgroud)
  • 使用进程管理器,例如supervisord。这是一种中等重量级的方法,需要您将supervisord 及其配置打包到您的映像中(或将您的映像基于包含supervisord 的映像),以及它管理的不同应用程序。然后您启动supervisord,它会为您管理流程。以下是使用此方法的 Dockerfile 示例,它假设预先编写的supervisord.conf、my_first_process 和 my_second_process 文件都与 Dockerfile 存在于同一目录中。

但是,如果您正在寻找主管,则可以在其中一个程序被终止后检查关闭主管以及其他类似的方法来监视进程。

  • 感谢您的答复。我之前在 docker 文档中读过那篇文章。正如您所说,这些方法看起来都不适合生产。我的问题是**这样做的正确方法是什么?** (2认同)