如何使用Docker安裝PHP依賴項和擴充套件

如何使用Docker安裝PHP依賴項和擴充套件

Docker 是一個用於開發、運輸和執行應用程式的流行開源平臺。它將應用程式及其依賴關係封裝在容器中,以促進不同環境間的一致性。這種一致性有助於防止與依賴衝突和 “在我的機器上也能執行” 的差異有關的問題。

使用 Docker,您可以使用 Dockerfile 定義必要的依賴關係和擴充套件。這意味著您的應用程式在一個可重現的隔離環境中擁有所有必需的庫和工具。

應用程式託管伺服器為自定義 Dockerfile 提供動態支援,使您能夠更好地控制應用程式的環境。有了 Dockerfile,你幾乎可以使用任何語言,而不必侷限於 Nixpacks 或 Buildpacks 所支援的語言。

本文將手把手教你如何在 Docker 中安裝和使用 PHP 依賴項和擴充套件。

為什麼使用 Docker 安裝依賴項?

使用 Docker 安裝依賴項有幾個好處:

  • 環境一致性 – Docker 允許您將應用程式、其依賴項和配置打包到一個容器中。這種方法可確保在不同的配置和系統(包括開發、測試和生產環境)中,應用程式的執行環境保持一致。
  • 易於設定和解決依賴性問題 – Docker 可讓你在任何支援應用程式的機器上設定應用程式的環境,只需指定其所需的所有依賴性和配置即可。因此,您可以避免相容性問題和手動安裝依賴項的麻煩。
  • 版本控制和隔離 – Docker 容器封裝了所有依賴項,包括容器內的特定版本。這意味著您可以對應用程式及其依賴項進行版本控制,從而提高可重複性並消除不同依賴項版本之間的衝突。

此外,Docker 容器還提供隔離功能,有助於消除在同一系統上執行的不同應用程式之間的依賴關係衝突。

在伺服器上設定應用程式

以Kinsta為例,在伺服器上設定您的應用程式非常簡單。訪問 MyKinsta 並按照註冊流程操作。註冊完成後,您就可以訪問功能強大的託管控制面板和一整套旨在優化效能和安全性的功能。

Kinsta 的應用程式託管支援一系列程式語言,包括 PHP、Python、Node.js 和 Ruby。這種廣泛的語言支援確保了與各種應用程式的相容性,使您能夠選擇最適合您專案要求的語言。

例如,如果您正在使用 PHP 開發動態網路應用程式,Kinsta 的優化託管環境可確保您基於 PHP 的專案具有高效能和高可靠性。或者,如果您使用 Node.js 構建 RESTful API,或使用 Python 構建資料驅動型網路應用程式,Kinsta 將為您的應用程式提供必要的基礎設施和支援。

要體驗如何在 Kinsta 上使用 Dockerfile 部署應用程式,請使用此應用程式,這是一個使用 MariaDB 儲存資料的基於 PHP 的基本身份驗證系統。該應用還利用了一些作曲包,包括用於輸入驗證的 respect/validation 和用於密碼雜湊的 ircmaxell/password-compat

準備 Docker 環境

Dockerfile 是一個文字檔案,其中包含構建所需映象所需的所有命令,並按照必要的順序排列。PHP 應用程式的基本 Dockerfile 是這樣的:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM php:8.3-cli
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
CMD [ "php", "./your-script.php" ]
FROM php:8.3-cli COPY . /usr/src/myapp WORKDIR /usr/src/myapp CMD [ "php", "./your-script.php" ]
FROM php:8.3-cli
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
CMD [ "php", "./your-script.php" ]

此 Dockerfile 可建立一個容器環境,用於從命令列介面(CLI)執行 PHP 指令碼。它首先使用帶有 CLI 變體的官方 PHP 映像,確保容器中只包含 PHP 執行時。

然後,它將包含 Dockerfile 的本地目錄內容複製到容器中的 /usr/src/myapp 目錄。將工作目錄設定為 /usr/src/myapp 後,它會使用 php 命令指定要執行的 PHP 指令碼,即 your-script.php

映像包含許多預編譯的 PHP 擴充套件。因此,首先執行 php -m 命令檢查是否安裝了所需的擴充套件。

如果基本映象中沒有你需要的擴充套件,Docker 會提供以下輔助指令碼,幫助你更輕鬆地安裝其他擴充套件:

  • docker-php-ext-configure
  • docker-php-ext-install
  • docker-php-ext-enable

例如,本教程的演示程式使用 MySQLi 擴充套件與 MariaDB 資料庫互動。該擴充套件預設未編譯到映像中,因此請在 Dockerfile 中使用以下命令安裝它:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
RUN docker-php-ext-install mysqli
RUN docker-php-ext-install mysqli
RUN docker-php-ext-install mysqli

要為演示程式編寫 Dockerfile,請在專案根資料夾中新建一個名為 Dockerfile 的檔案。在檔案中貼上以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM php:8.3-apache
# Install MySQL client, server, and other dependencies
RUN apt-get update && \
apt-get install -y \
default-mysql-client \
default-mysql-server \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install mysqli PHP extension for MySQL support
RUN docker-php-ext-install mysqli
FROM php:8.3-apache # Install MySQL client, server, and other dependencies RUN apt-get update && \ apt-get install -y \ default-mysql-client \ default-mysql-server \ git \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Install mysqli PHP extension for MySQL support RUN docker-php-ext-install mysqli
FROM php:8.3-apache
# Install MySQL client, server, and other dependencies
RUN apt-get update && \
apt-get install -y \
default-mysql-client \
default-mysql-server \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install mysqli PHP extension for MySQL support
RUN docker-php-ext-install mysqli

該程式碼指定了官方 PHP 映象(特別是 8.3 版),並安裝了 Apache 作為容器的基礎映像。該映象為使用 Apache 作為 Web 伺服器執行 PHP 應用程式提供了預配置環境。

然後,它將安裝演示應用程式所需的其他依賴項,包括 default-mysql-clientdefault-mysql-server,它們將建立 MariaDB 資料庫並與之互動。

最後,上面的程式碼段使用 docker-php-ext-install 安裝了 mysqli PHP 擴充套件,它允許演示程式在 MariaDB 資料庫上建立連線並執行操作。

用 Docker 管理依賴關係

使用 Docker 管理 PHP 的依賴關係需要使用 Composer,這是一種流行的 PHP 依賴關係管理器。通過在 Docker 容器中安裝 Composer,您可以簡化安裝、更新和管理 PHP 依賴項的過程,同時促進不同環境間的一致性和可重複性。

請按照以下步驟在演示應用程式中使用 Composer 進行依賴關係管理。將每個步驟中的程式碼新增到你的 Dockerfile 中。

  1. 使用以下命令在 Docker 映象中安裝 Composer:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Install Composer
    COPY --from=composer/composer:latest-bin /composer /usr/bin/composer
    # Install Composer COPY --from=composer/composer:latest-bin /composer /usr/bin/composer
    # Install Composer
    COPY --from=composer/composer:latest-bin /composer /usr/bin/composer

    該命令會將 Docker Hub 程式碼庫中預製的 Composer 二進位制檔案複製到你的映象中。--from=composer/composer:latest-bin 指定了從中拷貝檔案的源映象。

    源映象中的 /composer 路徑包含要複製的檔案,而你的 Docker 映象的 /usr/bin/composer 路徑則是這些檔案的目的地。

  2. 接下來,執行以下命令設定工作目錄:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Set working directory
    WORKDIR /var/www/html
    # Set working directory WORKDIR /var/www/html
    # Set working directory
    WORKDIR /var/www/html
  3. composer.jsoncomposer.lock 檔案複製到映象中。
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Copy composer.json and composer.lock
    COPY composer.json composer.lock ./
    # Copy composer.json and composer.lock COPY composer.json composer.lock ./
    # Copy composer.json and composer.lock
    COPY composer.json composer.lock ./
  4. 安裝 composer.json 中列出的 Composer 依賴項。
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Install Composer dependencies
    RUN composer install --no-dev --optimize-autoloader
    # Install Composer dependencies RUN composer install --no-dev --optimize-autoloader
    # Install Composer dependencies
    RUN composer install --no-dev --optimize-autoloader

    --no-dev 指示 Composer 跳過特定於開發的依賴項。 --optimize-autoloader (優化自動載入器)指示 Composer 優化自動載入器,以提高效能。

你可以根據需要修改 composer.json 檔案,新增新的依賴項,更新版本限制,刪除不再需要的依賴項,從而逐步更新和管理依賴項。

進行必要的修改後,在 Docker 容器中執行 composer installcomposer update,安裝或更新相應的依賴項。

應用最終配置

在應用程式使用 Docker 之前,必須建立資料庫和資料庫使用者、設定環境變數,並將專案檔案複製到 Docker 映象中。

為此,請按照以下步驟操作,並將每個程式碼段複製到 Docker 檔案中。

  1. 設定 PHP 應用程式用來連線 MariaDB 資料庫的環境變數。你可以用自己喜歡的憑證替換 DB_USERDB_PASSWORDDB_NAME
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Set environment variables
    ENV DB_HOST=localhost \
    DB_USER=kinsta_user \
    DB_PASSWORD=your_password_here \
    DB_NAME=kinsta_docker_auth \
    # Path to the Unix socket file used for connecting to the MariaDB server.
    DB_SOCKET=/var/run/mysqld/mysqld.sock
    # Set environment variables ENV DB_HOST=localhost \ DB_USER=kinsta_user \ DB_PASSWORD=your_password_here \ DB_NAME=kinsta_docker_auth \ # Path to the Unix socket file used for connecting to the MariaDB server. DB_SOCKET=/var/run/mysqld/mysqld.sock
    # Set environment variables
    ENV DB_HOST=localhost \
    DB_USER=kinsta_user \
    DB_PASSWORD=your_password_here \
    DB_NAME=kinsta_docker_auth \
    # Path to the Unix socket file used for connecting to the MariaDB server.
    DB_SOCKET=/var/run/mysqld/mysqld.sock
  2. 將 PHP 應用程式檔案複製到 Docker 映象中:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Copy PHP application files into the image
    COPY . .
    # Copy PHP application files into the image COPY . .
    # Copy PHP application files into the image
    COPY . .
  3. 將啟動指令碼複製到影象中:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Copy the startup script
    COPY scripts/start.sh /usr/local/bin/start.sh
    # Copy the startup script COPY scripts/start.sh /usr/local/bin/start.sh
    # Copy the startup script
    COPY scripts/start.sh /usr/local/bin/start.sh

    該指令碼在容器啟動時執行,負責啟動資料庫伺服器、建立資料庫、表和使用者以及啟動 Apache 伺服器。稍後您將建立此指令碼。

  4. 使用 chmod 命令使指令碼可執行:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Make the script executable
    RUN chmod +x /usr/local/bin/start.sh
    # Make the script executable RUN chmod +x /usr/local/bin/start.sh
    # Make the script executable
    RUN chmod +x /usr/local/bin/start.sh
  5. 最後,使用下面的命令執行指令碼:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Execute the startup script
    CMD ["/usr/local/bin/start.sh"]
    # Execute the startup script CMD ["/usr/local/bin/start.sh"]
    # Execute the startup script
    CMD ["/usr/local/bin/start.sh"]

現在 Dockerfile 已經完成,可以建立前面討論過的啟動指令碼了。

在專案根資料夾中新建一個名為 scripts/start.sh 的檔案,並新增以下程式碼。確保使用在 Dockerfile 中定義的資料庫憑據。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#!/bin/bash
# Start MariaDB server
service mariadb start
# Wait for MariaDB to be fully initialized (retry up to 30 times, waiting 1 second between each attempt)
attempt=0
while [ $attempt -lt 30 ]; do
if mysqladmin ping &>/dev/null; then
echo "MariaDB is up and running."
break
else
echo "MariaDB is not yet available. Retrying..."
attempt=$((attempt+1))
sleep 1
Fi
done
# If MariaDB failed to start within the specified attempts, exit with an error
if [ $attempt -eq 30 ]; then
echo "Error: MariaDB failed to start within the specified time."
exit 1
fi
# Set the database name, username, and password
dbname="kinsta_docker_auth"
dbuser="kinsta_user"
dbpassword="your_password_here"
# Create the database if it does not exist
mysql -u root -e "CREATE DATABASE IF NOT EXISTS $dbname;"
# Create a database user and assign privileges to the database
mysql -u root -e "CREATE USER '$dbuser'@'localhost' IDENTIFIED BY '$dbpassword';"
mysql -u root -e "GRANT ALL PRIVILEGES ON $dbname.* TO '$dbuser'@'localhost';"
mysql -u root -e "FLUSH PRIVILEGES;"
# Create users table if it does not exist
mysql -u root -e "USE $dbname; CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL
);"
# Start Apache server
apache2ctl -D FOREGROUND
#!/bin/bash # Start MariaDB server service mariadb start # Wait for MariaDB to be fully initialized (retry up to 30 times, waiting 1 second between each attempt) attempt=0 while [ $attempt -lt 30 ]; do if mysqladmin ping &>/dev/null; then echo "MariaDB is up and running." break else echo "MariaDB is not yet available. Retrying..." attempt=$((attempt+1)) sleep 1 Fi done # If MariaDB failed to start within the specified attempts, exit with an error if [ $attempt -eq 30 ]; then echo "Error: MariaDB failed to start within the specified time." exit 1 fi # Set the database name, username, and password dbname="kinsta_docker_auth" dbuser="kinsta_user" dbpassword="your_password_here" # Create the database if it does not exist mysql -u root -e "CREATE DATABASE IF NOT EXISTS $dbname;" # Create a database user and assign privileges to the database mysql -u root -e "CREATE USER '$dbuser'@'localhost' IDENTIFIED BY '$dbpassword';" mysql -u root -e "GRANT ALL PRIVILEGES ON $dbname.* TO '$dbuser'@'localhost';" mysql -u root -e "FLUSH PRIVILEGES;" # Create users table if it does not exist mysql -u root -e "USE $dbname; CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(20) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL );" # Start Apache server apache2ctl -D FOREGROUND
#!/bin/bash
# Start MariaDB server
service mariadb start
# Wait for MariaDB to be fully initialized (retry up to 30 times, waiting 1  second between each attempt)
attempt=0
while [ $attempt -lt 30 ]; do
if mysqladmin ping &>/dev/null; then
echo "MariaDB is up and running."
break
else
echo "MariaDB is not yet available. Retrying..."
attempt=$((attempt+1))
sleep 1
Fi
done
# If MariaDB failed to start within the specified attempts, exit with an error
if [ $attempt -eq 30 ]; then
echo "Error: MariaDB failed to start within the specified time."
exit 1
fi
# Set the database name, username, and password
dbname="kinsta_docker_auth"
dbuser="kinsta_user"
dbpassword="your_password_here"
# Create the database if it does not exist
mysql -u root -e "CREATE DATABASE IF NOT EXISTS $dbname;"
# Create a database user and assign privileges to the database
mysql -u root -e "CREATE USER '$dbuser'@'localhost' IDENTIFIED BY '$dbpassword';"
mysql -u root -e "GRANT ALL PRIVILEGES ON $dbname.* TO '$dbuser'@'localhost';"
mysql -u root -e "FLUSH PRIVILEGES;"
# Create users table if it does not exist
mysql -u root -e "USE $dbname; CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL
);"
# Start Apache server
apache2ctl -D FOREGROUND

這個 Bash 指令碼會啟動 MariaDB 伺服器。然後,當伺服器完全初始化後,它會建立一個資料庫、一個具有適當許可權的使用者以及資料庫中的一個表。最後,啟動 Apache 伺服器。

在伺服器上部署

在將應用程式部署到 Kinsta 之前,您必須為 Apache 伺服器配置一些配置。Kinsta 的應用程式託管服務開放了 80443 埠,但如果您的應用程式暴露了任何埠,我們建議您使用 8080 埠。

預設情況下,Apache 伺服器監聽埠 80 上的連線,因此必須將其配置為監聽埠 8080 上的連線。為此,請按照以下步驟操作:

  1. 在專案根資料夾中建立名為 apache-conf 的資料夾。
  2. 在新建立的資料夾中,建立名為 apache-config.conf 的檔案。新增以下程式碼,配置 Apache 監聽 8080 埠上的連線:
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <VirtualHost *:8080>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    <VirtualHost *:8080> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
    <VirtualHost *:8080>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
  3. apache-conf 資料夾中新建一個名為 apache-ports.conf 的檔案,並新增以下程式碼。
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Change the Listen directive to listen on port 8080
    Listen 8080
    # Keep the existing configuration for port 443
    <IfModule ssl_module>
    Listen 443
    </IfModule>
    <IfModule mod_gnutls.c>
    Listen 443
    </IfModule>
    # Change the Listen directive to listen on port 8080 Listen 8080 # Keep the existing configuration for port 443 <IfModule ssl_module> Listen 443 </IfModule> <IfModule mod_gnutls.c> Listen 443 </IfModule>
    # Change the Listen directive to listen on port 8080
    Listen 8080
    # Keep the existing configuration for port 443
    <IfModule ssl_module>
    Listen 443
    </IfModule>
    <IfModule mod_gnutls.c>
    Listen 443
    </IfModule>

    Listen 8080 指令指示 Apache 監聽 8080 埠上的傳入連線。

  4. 現在,你需要修改 Dockerfile,將此配置應用到 Apache 伺服器。在 Dockerfile 中,在設定工作目錄( WORKDIR /var/www/html )的命令之後新增這些命令。這些命令負責將自定義配置檔案複製到相應的目錄中。
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    # Set up Apache virtual host
    COPY apache-conf/apache-config.conf /etc/apache2/sites-available/000-default.conf
    # Set up Apache ports
    COPY apache-conf/apache-ports.conf /etc/apache2/ports.conf
    # Set up Apache virtual host COPY apache-conf/apache-config.conf /etc/apache2/sites-available/000-default.conf # Set up Apache ports COPY apache-conf/apache-ports.conf /etc/apache2/ports.conf
    # Set up Apache virtual host
    COPY apache-conf/apache-config.conf /etc/apache2/sites-available/000-default.conf
    # Set up Apache ports
    COPY apache-conf/apache-ports.conf /etc/apache2/ports.conf
  5. 最後,在專案根資料夾中建立一個 .dockerignore 檔案。該檔案列出了不應複製到 Docker 映象中的資料夾和檔案。新增 vendor 以排除 vendor 資料夾。

完成所有配置後,就可以部署到 Kinsta 了。將專案檔案上傳到首選的 Git 提供商(Bitbucket、GitHub 或 GitLab),然後按照以下步驟操作。

  1. MyKinsta 面板中,選擇側邊欄上的 Applications,然後單擊 Add application 按鈕。
  2. 在 “Add application” 頁面,選擇 Git 倉庫和分支,提供應用程式名稱,選擇資料中心位置,然後單擊 “Continue“。
  3. 在 “Build environment” 頁面,選擇 “Use Dockerfile to set up container image“。提供 “Dockerfile “作為 Dockerfile path,並提供句號(”.”)作為 Context。單擊 Continue。新增應用程式表單中的 “構建環境” 部分:新增應用程式表單中的 "構建環境" 部分
  4. 將所有內容保留在 “Set up your processes” 頁面,然後單擊 “Continue“。注意:重新啟動或重新部署應用程式時,資料庫將丟失資料。如果需要解決這個問題,請檢視 Kinsta 的持久儲存並在此頁面上應用。本指南將不審查持久儲存的設定。
  5. 在 “Summary ” 頁面上確認付款詳細資訊,然後單擊 “Deploy now“。
  6. 部署完成後,開啟應用程式的域檢視實時網站。下圖為實時網站上的登入頁面:實時網站上的登入頁面註冊一個賬戶,使用您的詳細資訊登入,然後檢查您是否可以訪問受保護的頁面,以及是否一切正常。下圖為登入後的應用程式主頁:登入後的應用程式主頁

監控和優化您的應用程式

一旦您的應用程式在伺服器上啟動並執行,監控和優化其效能至關重要。它能確保您的應用程式順利執行並有效利用資源。

優化應用程式的效能對於提供快速響應的使用者體驗至關重要。

通過監控工具,幫助您跟蹤各種效能指標,包括頻寬、總構建時間、CPU 使用率、記憶體消耗、網路流量和響應時間。

如果遇到問題或意外的應用程式行為,您可以導航到伺服器管理對應的日誌部分。該部分詳細概述了應用程式的效能和行為,包括錯誤和訪問日誌。

通過仔細檢視這些日誌,您可以深入瞭解可能導致問題的原因,如錯誤訊息、堆疊跟蹤或異常行為模式。這些資訊可以幫助您診斷問題的根本原因,並採取適當措施加以解決。

此外,您還可以在 Docker 環境中利用效能優化技術,例如優化 Docker 映像以及實施應用架構和程式碼優化的最佳實踐。

小結

無論底層基礎架構如何,Docker 的輕量級和可移植容器都能輕鬆打包和部署包含所有所需依賴項的應用程式。通過將應用程式及其依賴項容器化,您可以在不同環境中提高一致性,簡化設定流程,並獲得更好的版本控制。

評論留言