不只 WordPress!Docker Compose 一鍵部署 Nginx + Redis + MariaDB 黃金組合,打造企業級高效能架構

2025/09/22 | 全端與程式開發, 架構與效能優化

不只 WordPress!Docker Compose 一鍵部署 Nginx + Redis + MariaDB 黃金組合,打造企業級高效能架構

嗨,我是浪花科技的資深工程師 Eric。如果你看過我們之前那篇關於 Docker 的入門教學,相信你已經告別了「在我電腦明明可以跑」的惡夢。但當你的專案開始成長,需求變得複雜時,你會發現單一一個 WordPress 容器就像是只會一招的武林高手,雖然厲害,但面對千軍萬馬時還是會力不從心。

一個真正能打的企業級網站,絕對不是只有 WordPress 本身那麼簡單。它需要一個高性能的網頁伺服器(Web Server)、一個穩定可靠的資料庫(Database),再加上一個飛快的快取層(Caching Layer)。這些服務各司其職,就像一支分工精密的特種部隊。今天,我就要帶你更上一層樓,學習如何使用 Docker Compose 多服務部署,將 Nginx、MariaDB、Redis 這些神兵利器與 WordPress 完美整合,一鍵打造出一個堅若磐石、快如閃電的高效能架構。

這不只是把服務兜在一起而已,這是一種工程的藝術,一種對架構的思考。準備好了嗎?泡杯咖啡,讓我們開始吧!

為什麼單一 WordPress 容器已經不夠看?

官方的 WordPress Docker 映像檔(image)很方便,它內建了 Apache 伺服器和 PHP 環境,讓你拉下來就能跑。對於開發或簡單的部落格來說,確實夠用。但當流量上來,或你需要更精細的控制時,問題就浮現了:

  • 效能瓶頸: 內建的 Apache 雖然穩定,但在高併發(High Concurrency)場景下的效能表現,通常不如 Nginx。
  • 缺乏彈性: 所有東西都綁在一個容器裡,想單獨升級 PHP、更換網頁伺服器、或調整資料庫設定,都會變得綁手綁腳。
  • 擴展性受限: 當你需要獨立擴展(scale out)某個服務時,例如增加更多的 PHP-FPM worker 或擴充資料庫,單一容器架構會讓你頭痛不已。
  • 缺乏快取機制: 沒有物件快取(Object Caching)的 WordPress,每次頁面請求都會頻繁查詢資料庫,當訪客一多,資料庫馬上就成為整個網站的效能瓶頸。

簡單來說,All-in-One 的方案犧牲了專業分工帶來的效能與彈性。而 Docker Compose 多服務部署 就是為了解決這個問題而生的最佳方案。

Docker Compose 登場:容器界的交響樂指揮家

如果說 Dockerfile 是用來定義「單一容器」的藍圖,那 Docker Compose 就是用來定義和運行「多個容器應用程式」的指揮家。它透過一個簡單的 YAML 格式設定檔(通常是 docker-compose.yml),就能讓你像指揮交響樂一樣,優雅地協調各個服務容器的啟動順序、網路連線、資料共享等複雜操作。

你不用再手動一個一個下 docker run 指令,還要處理複雜的網路設定。只需要一個指令 docker-compose up,整個應用程式堆疊(application stack)就能應聲而起。這才是現代化開發與維運該有的帥氣模樣,不是嗎?

打造我們的黃金組合:架構設計藍圖

在這次的實戰中,我們將部署一個經典且高效的 WordPress 架構,包含以下四個核心服務:

  • Nginx: 作為我們的網頁伺服器與反向代理(Reverse Proxy)。它負責接收所有來自外部的 HTTP 請求,將靜態檔案(如圖片、CSS、JS)直接回傳,並將動態的 PHP 請求轉發給 WordPress 容器處理。效能極高,是業界首選。
  • WordPress (PHP-FPM): 這是我們的應用程式核心。我們將使用官方的 PHP-FPM 版本映像檔,它專門處理 PHP 腳本,不包含網頁伺服器。這樣分工更明確,也更安全。
  • MariaDB: 作為 WordPress 的資料庫。它是 MySQL 的一個開源分支,由原 MySQL 創始人維護,完全相容且效能更佳,是許多開發者的心頭好。
  • Redis: 一個高效能的鍵值(key-value)記憶體資料庫。我們將用它來實現 WordPress 的物件快取(Object Cache),大幅減少資料庫查詢次數,讓網站後台和前台的反應速度原地起飛。

這四個服務將在 Docker Compose 的調度下,運行在各自獨立的容器中,但又透過內部網路緊密地協同工作。

手把手拆解 `docker-compose.yml`:指揮家的樂譜

接下來,就是這篇文章的重頭戲。我們會一步步建立 docker-compose.yml 這個檔案。老實說,這檔案就像是我們整個架構的靈魂,每個字都得看仔細了。

第一步:建立專案目錄結構

首先,在你的電腦上建立一個專案資料夾,結構如下:

my-wordpress-stack/
├── docker-compose.yml      # 我們的主角
├── .env                    # 存放敏感資訊,如密碼
└── nginx/
    └── nginx.conf          # Nginx 的設定檔

第二步:編寫 `docker-compose.yml`

這會是一個比較長的檔案,我會分段解釋每個服務的設定。

# docker-compose.yml

version: '3.8'

services:
  # 資料庫服務 (MariaDB)
  db:
    image: mariadb:10.6
    container_name: wordpress_db
    restart: always
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - wordpress_network

  # Redis 快取服務
  redis:
    image: redis:6.2-alpine
    container_name: wordpress_redis
    restart: always
    networks:
      - wordpress_network

  # WordPress 核心服務 (PHP-FPM)
  wordpress:
    image: wordpress:6.4-fpm-alpine
    container_name: wordpress_app
    restart: always
    depends_on:
      - db
      - redis
    volumes:
      - wp_data:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: ${MYSQL_USER}
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
      WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
      WORDPRESS_TABLE_PREFIX: wp_
      WORDPRESS_DEBUG: ${WORDPRESS_DEBUG:-0} # 預設為 0
      WORDPRESS_CONFIG_EXTRA: |
        define('WP_CACHE', true);
        define('WP_CACHE_KEY_SALT', 'your-unique-salt-');
        define('WP_REDIS_HOST', 'redis');
        define('WP_REDIS_PORT', 6379);
    networks:
      - wordpress_network

  # Nginx 網頁伺服器
  nginx:
    image: nginx:1.25-alpine
    container_name: wordpress_nginx
    restart: always
    ports:
      - "${HTTP_PORT:-80}:80"
    volumes:
      - wp_data:/var/www/html
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - wordpress
    networks:
      - wordpress_network

# 定義資料卷 (Volumes)
volumes:
  db_data:
  wp_data:

# 定義網路 (Networks)
networks:
  wordpress_network:
    driver: bridge

我知道這看起來很嚇人,別急,我們一個個拆解:

  • services: 裡面定義了我們需要的四個服務:db, redis, wordpress, nginx
  • image: 指定每個服務要使用的 Docker 映像檔。我習慣用 alpine 版本,因為它體積小巧。
  • container_name: 給容器一個好記的名字,方便管理。
  • restart: always: 這很重要,確保容器在意外關閉或伺服器重啟後會自動重新啟動。
  • volumes: 這是實現資料持久化的關鍵。db_data:/var/lib/mysql 的意思是將一個名為 db_data 的 Docker volume 掛載到 MariaDB 容器的 /var/lib/mysql 路徑。這樣即使容器被刪除,你的資料庫檔案依然會被保留下來。wp_data 也是同理,用來儲存 WordPress 的核心檔案、外掛和上傳的媒體。
  • environment: 用來設定容器內的環境變數。注意到我用了 ${MYSQL_USER} 這種格式嗎?這代表變數的值會從 .env 檔案中讀取,避免將密碼等敏感資訊直接寫在設定檔裡,這是非常好的資安習慣!
  • networks: 我定義了一個名為 wordpress_network 的自訂橋接網路。所有服務都連接到這個網路,讓它們可以使用「服務名稱」(如 db, redis)作為主機名互相通訊,非常方便。
  • depends_on: 定義服務之間的啟動依賴關係。例如,wordpress 服務會等到 dbredis 服務啟動後才啟動。
  • WORDPRESS_CONFIG_EXTRA: 這是一個超好用的小技巧!可以直接在這裡注入額外的設定到 wp-config.php 檔案中,我們用它來設定 Redis 連線資訊。

第三步:設定環境變數 (`.env`)

在專案根目錄建立 .env 檔案,填入你的設定。請務必將密碼換成你自己設定的複雜密碼。

# .env

# 資料庫設定
MYSQL_DATABASE=wordpress_db
MYSQL_USER=wp_user
MYSQL_PASSWORD=your_strong_db_password
MYSQL_ROOT_PASSWORD=your_strong_root_password

# WordPress 設定
WORDPRESS_DEBUG=0

# Nginx 監聽的本機 Port
HTTP_PORT=8000

第四步:編寫 Nginx 設定檔 (`nginx.conf`)

nginx 資料夾下建立 nginx.conf。這個設定檔告訴 Nginx 如何處理進來的請求。

# nginx/nginx.conf

server {
    listen 80;
    server_name localhost;

    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass wordpress:9000; # 將請求轉發給 wordpress 服務的 9000 port
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
    }
}

這裡的關鍵是 fastcgi_pass wordpress:9000;。它告訴 Nginx,所有 PHP 請求都應該轉發給一個叫做 `wordpress` 的主機(也就是我們的 WordPress 容器)的 9000 埠。這就是服務之間溝通的魔法。

一鍵啟動與管理:常用指令大全

萬事俱備!現在回到你的專案根目錄,打開終端機,像個優雅的指揮家一樣,下達指令吧!

  • 啟動所有服務 (背景執行):
    docker-compose up -d
  • 查看所有服務的運行狀態:
    docker-compose ps
  • 查看特定服務的日誌 (Log):
    docker-compose logs -f wordpress
  • 停止並移除所有服務、網路和資料卷:
    docker-compose down -v

啟動後,打開瀏覽器,訪問 `http://localhost:8000`(如果你在 `.env` 中改了 `HTTP_PORT`,請使用對應的埠號),你應該就能看到 WordPress 的安裝畫面了!

最後一步:啟用 Redis 物件快取

我們的架構已經包含了 Redis,但還需要讓 WordPress 知道怎麼去用它。最簡單的方式是安裝一個外掛。

  1. 完成 WordPress 安裝。
  2. 登入後台,安裝並啟用「Redis Object Cache」外掛。
  3. 進入外掛設定頁面,點擊「Enable Object Cache」。因為我們已經在 wp-config.php 中透過環境變數注入了連線資訊,它應該能無痛連上 Redis 服務。

恭喜你!你已經成功部署了一個包含 Nginx、MariaDB 和 Redis 的高效能、可擴展的 WordPress 網站架構。這套架構不僅穩定,而且維護起來也比傳統的 LAMP/LEMP 環境要單純得多。

這就是 Docker Compose 的魅力所在:將複雜的架構設定,轉化為一份清晰、可版本控制的設定檔。無論是團隊協作、伺服器遷移,還是建立測試環境,都變得前所未有的簡單。這不只是省時間,更是提升了整個開發流程的品質與穩定性,這也是我們浪花科技在執行客戶專案時,非常推崇的作法。


管理一個高效能的 WordPress 網站架構是一門深奧的學問,從容器化部署、效能調校到安全性強化,每一個環節都至關重要。如果你希望為你的企業打造一個穩定、快速且安全的網站,卻不知從何下手,或是被複雜的技術細節搞得頭昏腦脹,歡迎隨時聯繫我們。

浪花科技 (Roamer Tech) 擁有豐富的企業級 WordPress 網站開發與維運經驗,我們樂於協助你解決各種技術難題。

立即填寫表單,與我們的技術專家聊聊!

延伸閱讀

常見問題 (FAQ)

Q1: 為什麼要用 Nginx 作為獨立服務,而不是直接用內建 Apache 的 WordPress 映像檔?

A: 主要是為了「專業分工」與「效能」。Nginx 在處理靜態檔案和高併發請求方面效能極佳,將它作為反向代理,可以過濾掉大量請求,只將需要 PHP 處理的動態請求轉發給 WordPress (PHP-FPM) 容器。這種架構更具彈性,也更容易針對不同部分進行效能調校與水平擴展,是業界主流的高效能網站架構。

Q2: 在這個架構中,Redis 物件快取到底扮演什麼角色?真的有必要嗎?

A: 絕對有必要!WordPress 內部有個稱為「Object Cache」的機制,它會將一些常用但生成耗時的資料(例如文章查詢結果、網站設定選項等)暫存在記憶體中,避免每次都去查詢資料庫。預設的快取是 non-persistent(非持久性)的,每次請求結束就消失了。而整合 Redis 後,快取會被存放在 Redis 這個高效能的記憶體資料庫中,可以跨請求共享,大幅降低資料庫負載,顯著提升網站後台及前台的反應速度,對於流量稍大的網站來說,效果非常顯著。

Q3: 如果我更新了 `docker-compose.yml` 檔案(例如升級映像檔版本),要如何套用變更?

A: 非常簡單!你只需要在專案的根目錄下,再次執行 docker-compose up -d 指令即可。Docker Compose 非常聰明,它會比對目前的容器狀態與你的設定檔,只重新建立那些設定有變動的服務容器。例如,你只改了 WordPress 的映像檔版本,它就只會重新拉取新的 WordPress 映像檔並重建 WordPress 容器,而不會去動你的資料庫或 Nginx 容器,非常高效且安全。

 
立即諮詢,索取免費1年網站保固