簡體   English   中英

Dockerize 用於生產的 PHP 應用程序

[英]Dockerize PHP Application for Production

我們有一個 PHP(特別是 Laravel)應用程序,應該針對生產環境進行 dockerized。 但是與 Web 服務器和 PHP-FPM 容器共享應用程序源代碼存在問題。

Nginx 和 PHP-FPM 都應該可以訪問應用程序源代碼,所以這里是網絡上建議的解決方法:

  1. 有兩個獨立的 Nginx 和 PHP-FPM 容器,並在主機上安裝源代碼並創建一個卷。 然后,將此卷分配給這些容器。 這種解決方案是不可取的,因為每次應用程序代碼更改時,都應該重新構建整個堆棧並刷新創建的卷。 此外,這些任務應該在我們所有的服務器上執行,這可能會浪費很多時間。
  2. 在同一個容器上同時擁有 PHP-FPM 和 Nginx,並使用supervisorentrypoint腳本保持它們的進程運行。 在這個解決方案中,當源代碼發生變化時,我們構建一次映像,希望沒有要刷新的共享卷,因此這似乎是一個很好的解決方法。 但是,這個解決方案的主要問題是它違反了容器化背后的思想。 Docker在其文檔中說:

    每個容器應該有一個問題(或正在運行的進程)。

    但是在這里,我們有兩個正在運行的進程!

有沒有其他解決方案可以在生產環境中使用 我不得不提一下,我們將在不久的將來使用SwarmKubernetes

謝謝。

一般來說,在生產中應該避免這兩種方法,但是如果我比較卷安裝和每個容器的兩個進程,我會為每個容器選擇兩個進程,而不是將主機代碼安裝到容器,

在某些情況下,第一種方法會失敗,例如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
  • 使用像 supervisord 這樣的進程管理器。 這是一種中等重量級的方法,需要您將 supervisord 及其配置打包到您的映像中(或將您的映像基於一個包含 supervisord 的映像),以及它管理的不同應用程序。 然后您啟動 supervisord,它為您管理您的流程。 這是一個使用這種方法的 Dockerfile 示例,它假設預先編寫的 supervisord.conf、my_first_process 和 my_second_process 文件都與您的 Dockerfile 存在於同一目錄中。

但是,如果您正在尋找主管,您可以在其中一個程序被終止后檢查關閉主管,以及其他類似的方法來監控進程。

您可以創建兩個單獨的 Docker 鏡像,一個只包含您的靜態資產,另一個包含可運行的后端代碼。 靜態資產圖像可以最小化為

# Dockerfile.nginx
FROM nginx:latest
COPY . /usr/share/nginx/html

不要在任何地方綁定安裝任何東西。 讓你的 CI 系統構建兩個鏡像

TAG=20191214
docker build -t myname/myapp-php:$TAG .
docker build -t myname/myapp-nginx:$TAG -f Dockerfile.nginx .

現在,您可以運行兩個獨立的容器(不違反每個容器一個進程的准則),獨立擴展它們(3 個 nginx 但 30 個 PHP),而不必手動復制源代碼。

另一種有用的技術是將您的靜態資產發布到某個外部托管系統; 如果您無論如何都在 AWS 中運行,那么 S3 在這里運行良好。 您仍然需要某種代理來將請求轉發到資產商店或您的后端服務,但現在可以只是一個帶有自定義配置文件的 Nginx; 它不需要您的任何應用程序代碼。 (在 Kubernetes 中,您可以使用 Nginx 部署來運行它,該部署指向帶有nginx.conf文件的配置映射。)

設置 CI 系統時,絕對不應在構建或集成測試時將掛載代碼綁定到容器中。 測試您正在構建的容器中的實際內容,而不是源代碼的其他副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM