不只 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服務會等到db和redis服務啟動後才啟動。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 知道怎麼去用它。最簡單的方式是安裝一個外掛。
- 完成 WordPress 安裝。
- 登入後台,安裝並啟用「Redis Object Cache」外掛。
- 進入外掛設定頁面,點擊「Enable Object Cache」。因為我們已經在
wp-config.php中透過環境變數注入了連線資訊,它應該能無痛連上 Redis 服務。
恭喜你!你已經成功部署了一個包含 Nginx、MariaDB 和 Redis 的高效能、可擴展的 WordPress 網站架構。這套架構不僅穩定,而且維護起來也比傳統的 LAMP/LEMP 環境要單純得多。
這就是 Docker Compose 的魅力所在:將複雜的架構設定,轉化為一份清晰、可版本控制的設定檔。無論是團隊協作、伺服器遷移,還是建立測試環境,都變得前所未有的簡單。這不只是省時間,更是提升了整個開發流程的品質與穩定性,這也是我們浪花科技在執行客戶專案時,非常推崇的作法。
管理一個高效能的 WordPress 網站架構是一門深奧的學問,從容器化部署、效能調校到安全性強化,每一個環節都至關重要。如果你希望為你的企業打造一個穩定、快速且安全的網站,卻不知從何下手,或是被複雜的技術細節搞得頭昏腦脹,歡迎隨時聯繫我們。
浪花科技 (Roamer Tech) 擁有豐富的企業級 WordPress 網站開發與維運經驗,我們樂於協助你解決各種技術難題。
延伸閱讀
- 告別「在我電腦明明可以跑」的惡夢:WordPress Docker 容器化部署終極教學
- 網站慢到想哭?解鎖 WordPress 終極加速密技:Redis 物件快取實戰教學
- 你的 WordPress 資料庫肥到走不動?資深工程師的終極瘦身指南,榨出110%的網站效能!
常見問題 (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 容器,非常高效且安全。






