版本提醒:這篇記錄 2024 年以 Bitnami 映像部署 WordPress 的流程。下列 bitnami/wordpress:6、bitnami/mariadb:11.4 等設定現在已過時,重新部署請依官方映像目錄變更公告及WordPress 映像說明選擇可維護的版本;bitnamilegacy 僅適合暫時遷移,不再提供更新。

這篇文章記錄以 Docker Compose 組合 WordPress 與 MariaDB,再使用 Bitnami 預先整理的映像設定環境變數及資料目錄。除了服務配置,也會說明 non-root 容器對主機掛載目錄權限的要求,以及安裝時遇到的問題與處理方式。

A. Bitnami、Wordpress、Docker是什麼

1. 什麼是Bitnami?

Bitnami 將應用程式及其相依元件整理成可部署的套件或映像,減少逐項安裝的工作。這裡使用容器映像建立環境,環境變數、資料目錄與更新管道仍須依所選版本確認,預先配置的映像也需要持續維護。

2. 什麼是WordPress?

WordPress 是開源內容管理系統,可用來建立網站與部落格,並透過佈景主題及外掛擴充功能。部署時除了 WordPress 程式,也需要資料庫保存文章、設定及使用者資料;媒體與自訂檔案則需要相應的持久化目錄。

3. 什麼是Docker?

Docker 透過映像與容器封裝應用程式及執行環境,方便在支援的主機與架構上部署相同設定。容器可以減少環境差異,但主機架構、儲存、權限及外部服務仍然會影響行為,並不是任意系統都能毫無條件地取得相同結果。

4. 這個組合的好處

這個組合把應用程式、資料庫及執行設定分開管理,WordPress 與 MariaDB 各自使用映像,Compose 描述它們的連線與掛載方式。更新時仍要確認映像支援狀態及資料相容性;本文的價值在於理解這些設定如何配合,而不是保證某個舊 tag 永遠提供最新環境。

B. Bitnami的Wordpress套件

Bitnami官方提供了一個即用型的WordPress Image,搭配官方Github中的環境變數配置說明文件,讓我們可以透過Docker快速客製化建立我們自己的Wordpress伺服器。以下是Bitnami的一些優點:

1. 即時更新

Bitnami 會將上游變更整理到對應的映像版本,更新時仍要確認取得管道與維護狀態。尤其是已移入 legacy 倉庫的版本,不會再取得後續修補。

2. 一致性與靈活性

Bitnami容器、虛擬機和雲端映像都使用相同的元件和配置方式,可以根據項目的需求在不同格式之間輕鬆切換,減少相容性的問題。

3. 基於minideb

這裡使用的 Debian 系列映像採用精簡基底,例如 minideb,以減少不必要的系統元件。若選用其他映像或 tag,作業系統、目錄位置與預先安裝的工具仍應以其 Dockerfile 及說明文件為準。

4. 影像完整性

映像完整性應依特定倉庫公布的簽章、驗證方式及 digest 確認。若版本提供 Notation 等簽章,可以依相應流程驗證,但不能僅因為映像出現在 Docker Hub,就認定每個歷史 tag 都具有相同的簽章與信任條件。

5. 定期發佈更新

固定映像 tag 方便辨識與重建部署環境,但不代表該版本仍受到維護;更新時要同時考慮應用程式、資料庫版本與持久化資料的相容性。

理解映像預設值、設定介面及維護來源之後,才能決定如何部署與更新 WordPress;這些資訊也能用來評估改用其他維護中的映像時,需要轉換哪些資料與設定。

C. 編寫docker-compose.yml

為了建構一個功能完整的WordPress網站,我們需要同時部署資料庫和WordPress系統。在這個範例中,使用Bitnami提供的Docker Image來搭建MariaDB和WordPress的環境。通過編寫docker-compose.yml文件,對應用堆疊進行定義和管理。

1. MariaDB

services:
  mariadb:
    image: docker.io/bitnami/mariadb:11.4
    volumes:
      - /path/to/mariadb-persistence:/bitnami/mariadb
    environment:
      # ALLOW_EMPTY_PASSWORD is recommended only for development.
      - ALLOW_EMPTY_PASSWORD=yes
      - MARIADB_USER=bn_wordpress
      - MARIADB_DATABASE=bitnami_wordpress

請把 /path/to/mariadb-persistence 換成主機上專供這個資料庫使用的目錄。這是 bind mount,資料存放在容器外,刪除容器本身不會自動刪除主機目錄,但也不等於有備份,誤刪主機資料或變更到錯誤掛載位置仍會影響資料。

其中為了方便開發測試,允許不使用密碼(ALLOW_EMPTY_PASSWORD=yes),強烈建議不管是不是開發測試環境,都幫資料庫設置密碼,基本的環境變數請參考下表:

NameDescriptionDefault Value
ALLOW_EMPTY_PASSWORDAllow MariaDB access without any password.no
MARIADB_ROOT_USERMariaDB database root user.root
MARIADB_ROOT_PASSWORDMariaDB database root user password.nil
MARIADB_USERMariaDB database user to create during the first initialization.nil
MARIADB_PASSWORDPassword for the MariaDB database user to create during the first initialization.nil
MARIADB_DATABASEMariaDB database to create during the first initialization.nil

下表列出這裡使用的 MariaDB 複寫環境變數,名稱沿用該版本的 Master/Slave 用語;選用其他版本時,應確認對應欄位與行為:

NameDescriptionDefault Value
MARIADB_MASTER_HOSTAddress for the MariaDB master node.nil
MARIADB_MASTER_PORT_NUMBERPort number for the MariaDB master node.3306
MARIADB_MASTER_ROOT_USERMariaDB database root user of the master host.root
MARIADB_MASTER_ROOT_PASSWORDPassword for the MariaDB database root user of the the master host.nil
MARIADB_MASTER_DELAYMariaDB database replication delay.0
MARIADB_REPLICATION_USERMariaDB replication database user.nil
MARIADB_REPLICATION_PASSWORDPassword for the MariaDB replication database user.nil
MARIADB_PORT_NUMBERPort number to use for the MariaDB Server service.nil
MARIADB_REPLICATION_MODEMariaDB replication mode.nil
MARIADB_REPLICATION_SLAVE_DUMPMake a dump on master and update slave MariaDB databasefalse

完整內容可查閱Bitnami MariaDB的說明。

2. WordPress

services:
  wordpress:
    image: docker.io/bitnami/wordpress:6
    ports:
      - '80:8080'
      - '443:8443'
    volumes:
      - /path/to/wordpress-persistence:/bitnami/wordpress
    depends_on:
      - mariadb
    environment:
      # ALLOW_EMPTY_PASSWORD is recommended only for development.
      - ALLOW_EMPTY_PASSWORD=yes
      - WORDPRESS_DATABASE_HOST=mariadb
      - WORDPRESS_DATABASE_PORT_NUMBER=3306
      - WORDPRESS_DATABASE_USER=bn_wordpress
      - WORDPRESS_DATABASE_NAME=bitnami_wordpress

WordPress 的 /path/to/wordpress-persistence 也要換成專用主機目錄。這個測試範例以 ALLOW_EMPTY_PASSWORD=yes 簡化初始化,正式配置應提供資料庫與管理者密碼;depends_on 的簡短寫法只安排啟動順序,不代表 MariaDB 已能接受查詢,啟動等待仍由映像或健康檢查機制處理。

WordPress網站使用者及網站相關設定如下:

NameDescriptionDefault Value
WORDPRESS_BLOG_NAMEWordPress blog name."User's blog"
WORDPRESS_USERNAMEWordPress user name.user
WORDPRESS_PASSWORDWordPress user password.bitnami
WORDPRESS_EMAILWordPress user e-mail address.user@example.com
WORDPRESS_FIRST_NAMEWordPress user first name.UserName
WORDPRESS_LAST_NAMEWordPress user last name.LastName

下表列出這裡使用的伺服器設定。將主機 443 映射到容器 8443,仍需另外配置憑證及 HTTPS,並決定由容器或反向代理終止 TLS。

NameDescriptionDefault Value
WORDPRESS_DATA_TO_PERSISTFiles to persist relative to the WordPress installation directory. To provide multiple values, separate them with a whitespace.wp-config.php wp-content
WORDPRESS_ENABLE_HTTPSWhether to enable HTTPS for WordPress by default.no
WORDPRESS_SCHEMEScheme to generate application URLs. Deprecated by WORDPRESS_ENABLE_HTTPS.http
WORDPRESS_HTACCESS_OVERRIDE_NONESet the Apache AllowOverride variable to None. All the default directives will be loaded from /opt/bitnami/wordpress/wordpress-htaccess.conf.yes
WORDPRESS_ENABLE_HTACCESS_PERSISTENCEPersist the custom changes of the htaccess. It depends on the value of WORDPRESS_HTACCESS_OVERRIDE_NONE, when yes it will persist /opt/bitnami/wordpress/wordpress-htaccess.conf if no it will persist /opt/bitnami/wordpress/.htaccess.no
WORDPRESS_RESET_DATA_PERMISSIONSForce resetting ownership/permissions on persisted data when initializing, otherwise it assumes the ownership/permissions are correct. Ignored when running as non-root.no
WORDPRESS_ENABLE_REVERSE_PROXYEnable WordPress support for reverse proxy headersno

郵件伺服器相關設定如下:

NameDescriptionDefault Value
WORDPRESS_SMTP_HOSTWordPress SMTP server host.nil
WORDPRESS_SMTP_PORT_NUMBERWordPress SMTP server port number.nil
WORDPRESS_SMTP_USERWordPress SMTP server user.nil
WORDPRESS_SMTP_FROM_EMAILWordPress SMTP from email.${WORDPRESS_SMTP_USER}
WORDPRESS_SMTP_FROM_NAMEWordPress SMTP from name.${WORDPRESS_FIRST_NAME} ${WORDPRESS_LAST_NAME}
WORDPRESS_SMTP_PASSWORDWordPress SMTP server user password.nil

以下使用 Gmail 設定 SMTP,連線埠由 WORDPRESS_SMTP_PORT_NUMBER 指定。帳號需依郵件服務實際支援的認證方式設定,Google 帳戶若採應用程式密碼,也必須符合其帳戶與兩步驟驗證條件,不能直接以一般登入密碼當作 SMTP 憑證。

  wordpress:
    ...
    environment:
      - WORDPRESS_DATABASE_USER=bn_wordpress
      - WORDPRESS_DATABASE_NAME=bitnami_wordpress
      - ALLOW_EMPTY_PASSWORD=yes
      - WORDPRESS_SMTP_HOST=smtp.gmail.com
      - WORDPRESS_SMTP_PORT_NUMBER=587
      - WORDPRESS_SMTP_USER=your_email@gmail.com
      - WORDPRESS_SMTP_PASSWORD=your_password
  ...

D. Non-root Container

在Container說明上有一段話:

Why use a non-root container?

Non-root container images add an extra layer of security and are generally recommended for production environments. However, because they run as a non-root user, privileged tasks are typically off-limits. Learn more about non-root containers in our docs.

non-root 映像以一般 UID 執行程式,因此不能假設它能寫入主機上由 root 或其他使用者擁有的目錄。對這篇文章使用的歷史映像,文件要求掛載資料目錄具備 UID 1001 所需的存取權限,這是後面 Permission denied 問題的關鍵。

我們可以試著直接執行剛剛的docker-compose.yml:

services:
  mariadb:
    image: docker.io/bitnami/mariadb:11.4
    volumes:
      - ./mariadb_data:/bitnami/mariadb
    environment:
      # ALLOW_EMPTY_PASSWORD is recommended only for development.
      - ALLOW_EMPTY_PASSWORD=yes
      - MARIADB_USER=bn_wordpress
      - MARIADB_DATABASE=bitnami_wordpress
  wordpress:
    image: docker.io/bitnami/wordpress:6
    ports:
      - '80:8080'
      - '443:8443'
    volumes:
      - ./wordpress_data:/bitnami/wordpress
    depends_on:
      - mariadb
    environment:
      # ALLOW_EMPTY_PASSWORD is recommended only for development.
      - ALLOW_EMPTY_PASSWORD=yes
      - WORDPRESS_DATABASE_HOST=mariadb
      - WORDPRESS_DATABASE_PORT_NUMBER=3306
      - WORDPRESS_DATABASE_USER=bn_wordpress
      - WORDPRESS_DATABASE_NAME=bitnami_wordpress

先建立專用的測試專案資料夾,放入 docker-compose.yml,並建立 mariadb_data 與 wordpress_data 兩個資料目錄。下方腳本的權限調整只針對這兩個目錄,執行前應確認所在路徑,避免影響其他既有資料。

project-folder/
├── mariadb_data/
├── wordpress_data/
└── docker-compose.yml

將bash切換到專案資料夾,並執行以下指令:

docker-compose -f ./docker-compose.yml up --build -d

原安裝紀錄中,資料庫容器在這一步無法正常啟動,日誌出現 Permission denied;這代表需要再檢查掛載目錄與映像執行 UID 的權限,而不是只反覆重建容器。

資料目錄的 Permission denied 錯誤

Bitnami MariaDB 初始化日誌,顯示無法建立 /bitnami/mariadb/data 目錄,錯誤為 Permission denied。

然後在文件講解如何設定volumes時,默默出現了一句話:

NOTE: As this is a non-root container, the mounted files and directories must have the proper permissions for the UID 1001.

non-root 容器的執行身分與主機掛載目錄的權限需要一起檢查,否則服務及環境變數看似正確,仍可能在初始化資料時遇到 Permission denied。

Permissions for the UID 1001

依照這個要求,下面的 one_click.sh 會建立指定的兩個測試資料目錄、把擁有者設為 UID/GID 1001,再啟動 Compose。這是針對原映像與新建測試目錄的設定,若使用其他映像或既有資料,應先確認其 UID/GID 與資料保存方式。

sudo chmod +x one_click.sh

讓腳本可執行後再執行即可;修訂版不會把主機帳號加入假定存在的群組,也不會把所有資料檔一律改成可執行的 775 權限。

#!/usr/bin/env bash
set -euo pipefail

WORDPRESS_DATA_UID=1001
for wordpress_data_directory in ./mariadb_data ./wordpress_data; do
    mkdir -p "$wordpress_data_directory"
    sudo chown -R "$WORDPRESS_DATA_UID:$WORDPRESS_DATA_UID" "$wordpress_data_directory"
    sudo chmod -R u+rwX "$wordpress_data_directory"
done

echo "Starting the Compose services..."
docker compose -f ./docker-compose.yml up -d

在使用仍可取得的對應映像、資料初始化與日誌都正常後,可到 http://localhost/ 檢查網站,管理後台的標準路徑是 /wp-admin/。表格中的 user/bitnami 是歷史預設示例,若沿用該環境應更改管理者憑證,不能把它們當成正式站的固定設定。

登入 WordPress 後台後,可在佈景主題管理中安裝並啟用主題,再開啟首頁確認主題與基本頁面是否正常顯示。

E. 總結

這個流程以 Compose 組合 WordPress 與 MariaDB,設定持久化目錄,再依容器的 UID 1001 處理主機掛載目錄權限。重新部署時,除了服務設定,也要一起確認映像版本與既有資料的相容性。

如果只需要回查配置,可以對照前面的 docker-compose.yml 與 one_click.sh,但在執行前仍應確認映像取得方式、資料目錄與權限。權限腳本只能解決特定寫入問題,不能取代資料備份、密碼設定或版本相容性檢查。

這次整理把原本分散在映像與持久化說明中的設定放在一起,尤其是 non-root 身分、bind mount 權限與初始化條件,方便回查當時部署問題的原因。後續維護仍應以正在使用的映像版本文件為準。