告別單機作戰!Docker Compose 終極交響樂:一鍵指揮 WordPress + Nginx + Redis + MariaDB 四重奏
哈囉,我是浪花科技的資深工程師 Eric。如果你還記得,我們之前聊過如何用 Docker 把 WordPress 包起來,解決了那句工程師最痛恨的魔咒:「在我電腦明明可以跑的啊?」。但說真的,那只是前菜。一個真正能打仗、扛得住流量的專業網站,絕對不是只有 WordPress 本體那麼單純。它更像一個交響樂團,需要網頁伺服器、資料庫、快取系統… 各司其職,完美協奏。
今天,我們就要來談談如何從一個單純的樂手,晉升為整個樂團的指揮家。我們要用的指揮棒,就是 Docker Compose。這篇文章會帶你從零開始,用一個 `docker-compose.yml` 檔案,一鍵啟動一個包含 Nginx、MariaDB、Redis 與 WordPress (PHP-FPM) 的高效能網站架構。別再手動一個一個安裝服務了,身為一個追求效率(跟懶惰)的工程師,自動化才是王道!
為什麼單一容器不夠?解構現代 WordPress 網站架構
在我們動手之前,先來個小小的精神喊話,或者說是工程師的囉嗦。為什麼我們需要這麼多服務?不能全部塞在一個 Docker 容器裡嗎?理論上可以,但那就像把小提琴手、鼓手、鋼琴師全塞在一個電話亭裡,不僅施展不開,還很容易因為一個人出錯(比如資料庫掛了)導致整個樂團(網站)跟著陪葬。
一個專業的 WordPress 網站架構,通常包含以下幾個核心角色:
- 網頁伺服器 (Web Server) – Nginx: 樂團的門面擔當。它負責接收來自使用者的所有請求,把靜態檔案(如圖片、CSS、JS)直接回傳,並將動態請求(需要 PHP 處理的頁面)轉交給後端的 PHP-FPM。
- PHP 處理器 (PHP-FPM): 樂團的主唱。這是 WordPress 的核心,負責執行所有 PHP 程式碼,從資料庫撈取資料,產生最終的 HTML 頁面。
- 資料庫 (Database) – MariaDB: 樂團的靈魂與記憶庫。你的所有文章、頁面、使用者資料、設定… 全部都儲存在這裡。MariaDB 是 MySQL 的一個開源分支,完全相容且效能優異。
- 物件快取 (Object Cache) – Redis: 樂團的加速器。每次頁面載入都去資料庫重新查詢太慢了。Redis 是一個基於記憶體的快取系統,可以將常用的查詢結果暫存在記憶體中,大幅減少資料庫的壓力,讓網站快到飛起。
透過 Docker Compose 多服務部署,我們可以將這四個角色分別放進獨立的容器中。它們各自獨立、互不干擾,卻又能透過 Docker 內建的虛擬網路高效溝通。這就是所謂的「關注點分離」,不僅維護方便,未來要針對某個服務(例如資料庫)單獨升級或擴展也輕而易舉。
Docker Compose 核心概念:服務、網路與卷宗
Docker Compose 的精髓全在一支名為 `docker-compose.yml` 的 YAML 格式設定檔。你可以把它想像成樂團的總樂譜,上面清楚標示了每個樂手(服務)該做什麼、用什麼樂器(映像檔)、以及他們之間如何溝通(網路)。
- 服務 (Services): 樂譜中的每個獨立部分。在我們的例子中,`nginx`、`wordpress`、`db`、`redis` 就是四個獨立的服務。
- 網路 (Networks): Docker Compose 會自動幫你建立一個專屬的內部虛擬網路,讓所有服務可以透過「服務名稱」直接溝通。例如,WordPress 容器可以直接用 `db` 這個主機名稱連到 MariaDB 容器,完全不用管它實際的 IP 是多少,超方便!而且這個網路是隔離的,你不用把資料庫的 3306 連接埠暴露在公網上,大大提升了安全性。
- 卷宗 (Volumes): 容器本身是「無狀態」的,意思是只要容器一刪除,裡面的資料就灰飛煙滅了。這對程式碼來說沒問題,但對資料庫或使用者上傳的檔案來說可是天大的災難。卷宗 (Volume) 就是用來解決這個問題的,它能將主機的某個資料夾掛載到容器內部,讓資料可以永久保存,即使容器被銷毀重建,資料依然安然無恙。
實戰演練:打造你的 WordPress 高效能四重奏
理論說完了,來點實際的吧!跟著我一步一步把這個高效能架構建立起來。
Step 1: 建立專案結構
首先,在你的電腦上建立一個專案資料夾,結構如下:
my-wordpress-stack/
├── docker-compose.yml
├── nginx/
│ └── default.conf
└── wordpress/
└── (這個資料夾會自動產生,用來存放 WordPress 核心檔案)
Step 2: 編寫指揮棒 `docker-compose.yml`
這就是我們整個架構的核心,請將以下內容貼到 `docker-compose.yml` 檔案中。我會逐段解釋每個設定的意義。
version: '3.8'
services:
db:
image: mariadb:10.6
container_name: my_wp_db
restart: unless-stopped
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: your_strong_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: your_strong_user_password
networks:
- wordpress_network
redis:
image: redis:6.2-alpine
container_name: my_wp_redis
restart: unless-stopped
networks:
- wordpress_network
wordpress:
image: wordpress:6.4-php8.1-fpm-alpine
container_name: my_wp_app
restart: unless-stopped
depends_on:
- db
- redis
volumes:
- ./wordpress:/var/www/html
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: your_strong_user_password
WORDPRESS_DB_NAME: wordpress
networks:
- wordpress_network
nginx:
image: nginx:1.25-alpine
container_name: my_wp_nginx
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./wordpress:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- wordpress
networks:
- wordpress_network
volumes:
db_data:
networks:
wordpress_network:
driver: bridge
稍微囉嗦一下各區塊的設定:
db服務:使用 MariaDB 10.6 映像檔。volumes: - db_data:/var/lib/mysql這行是關鍵,它建立了一個名為 `db_data` 的具名卷宗 (named volume),專門用來存放資料庫檔案。`environment` 則是用來設定資料庫的各種帳號密碼。redis服務:相對單純,就是啟動一個 Redis 容器。wordpress服務:我們用的是 `fpm-alpine` 版本的映像檔,它只包含 PHP-FPM,不含網頁伺服器,更輕量、更專業。depends_on確保它會在 `db` 和 `redis` 啟動之後才啟動。volumes: - ./wordpress:/var/www/html則是將我們主機的 `wordpress` 資料夾掛載進去,這樣我們就能直接在主機上修改佈景主題或外掛檔案了。nginx服務:負責對外。ports: - "8080:80"把容器的 80 port 映射到我們主機的 8080 port,這樣我們就能透過 `http://localhost:8080` 訪問網站。它同時掛載了 WordPress 的檔案目錄和我們自訂的 Nginx 設定檔。
Step 3: Nginx 設定檔 (`nginx/default.conf`)
Nginx 需要知道如何處理 PHP 請求。將以下內容貼到 `nginx/default.conf`:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass wordpress:9000;
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|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
這裡的魔法是 fastcgi_pass wordpress:9000;。它告訴 Nginx,把所有 PHP 請求都轉發給一個叫做 `wordpress` 的主機的 9000 port,而這個 `wordpress` 正是我們在 `docker-compose.yml` 裡定義的服務名稱!這就是 Docker Compose 內建 DNS 解析的威力。想了解更多 Nginx 的調校技巧,可以參考這篇 Nginx 效能調校聖經。
Step 4: 啟動!`docker-compose up -d`
萬事俱備!在你的專案根目錄下,打開終端機,執行以下指令:
docker-compose up -d
-d 參數代表在背景執行。Docker Compose 會開始下載映像檔、建立網路、卷宗並依序啟動所有容器。你可以用 docker-compose ps 來查看所有容器的狀態。第一次啟動需要幾分鐘,請耐心等候。
啟動成功後,打開瀏覽器訪問 `http://localhost:8080`,你應該就能看到熟悉的 WordPress 安裝畫面了!
整合 Redis 物件快取:讓你的 WordPress 飛起來
我們的 Redis 容器已經在背景默默運作了,但 WordPress 還不知道它的存在。我們需要搭起他們之間的橋樑。
- 安裝 Redis 外掛: 進入 WordPress 後台,安裝並啟用「Redis Object Cache」這個外掛。
- 設定 `wp-config.php`: 啟用外掛後,它可能會提示 `wp-config.php` 無法寫入。沒關係,我們手動來。打開 `./wordpress/wp-config.php` 檔案 (如果還沒有,可以先完成 WordPress 安裝讓它自動生成),在 `/* That’s all, stop editing! Happy publishing. */` 這行註解之前,加入以下設定:
define('WP_REDIS_HOST', 'redis'); define('WP_REDIS_PORT', 6379); define('WP_CACHE_KEY_PREFIX', 'my_wp_site:'); define('WP_CACHE', true); - 啟用物件快取: 回到後台的 Redis Object Cache 設定頁面,點擊「Enable Object Cache」。如果狀態顯示為「Connected」,恭喜你!你的 WordPress 已經裝上了 Redis 渦輪引擎!想深入了解 Redis 如何為 WordPress 加速,可以看看這篇 Redis 物件快取實戰教學。
工程師的囉嗦時間:常見陷阱與最佳實踐
踩過坑的學長告訴你,光是能跑起來還不夠,有幾個細節能讓你的開發流程更順暢、更安全。
檔案權限問題
Docker for Mac/Windows 通常處理得比較好,但在 Linux 上,你可能會遇到 Nginx 或 WordPress 因為權限不足而無法寫入 `./wordpress` 資料夾的問題。這是因為容器內的使用者 ID (UID) 和主機上的使用者 ID 不匹配。一個常見的解法是,在啟動容器後,手動修改主機上資料夾的權限,例如 sudo chown -R www-data:www-data wordpress/,但這不是最優雅的方式。更進階的作法是在 Dockerfile 中去動態設定使用者 ID,但這對初學者來說有點複雜,我們先知道有這個問題即可。
環境變數管理
直接把資料庫密碼寫在 `docker-compose.yml` 裡不是個好習慣,尤其當你要把這個檔案交給同事或上傳到 Git 時。最佳實踐是使用 `.env` 檔案。你可以在 `docker-compose.yml` 同層目錄下建立一個 `.env` 檔案,內容如下:
DB_ROOT_PASSWORD=your_strong_root_password
DB_USER=wordpress
DB_PASSWORD=your_strong_user_password
DB_NAME=wordpress
然後修改 `docker-compose.yml`,用 ${VARIABLE_NAME} 的語法來讀取:
# ...
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
# ...
這樣一來,你的敏感資訊就跟設定檔分開了,記得把 `.env` 加入到 `.gitignore` 中!
結論:你已經是半個 DevOps 工程師了!
恭喜你!你不再只是一個會用 WordPress 的開發者,你已經掌握了如何用 Docker Compose 這個強大的工具,來編排和管理一個現代化的、高效能的、可複製的網站應用程式架構。從今天起,無論是建立一個新的本地開發環境,還是要將整個專案打包交給同事,都只是一行 `docker-compose up -d` 的事。
這套架構不僅適用於開發,稍作調整(例如加入 SSL 憑證管理、更完善的備份策略),它完全有能力成為你正式上線網站的基石。這就是容器化帶來的革命:它模糊了開發與維運的界線,讓開發者能更好地掌控自己的應用程式。
延伸閱讀
- 「在我電腦明明可以跑的?」WordPress Docker 容器化部署終極教學
- 你的 Nginx 還在用預設值?資深工程師的 WordPress 效能調校聖經,榨乾伺服器最後一滴效能!
- 網站慢到想哭?解鎖 WordPress 終極加速密技:Redis 物件快取實戰教學
打造一個穩固又高效的網站架構是專案成功的基礎。如果你在部署過程中遇到任何問題,或是希望為你的企業導入更專業、更客製化的 DevOps 流程與網站架構,浪花科技的團隊擁有豐富的實戰經驗。我們不只是寫程式,更是你數位轉型路上的技術夥伴。
別讓複雜的技術問題拖慢你的腳步,立即聯繫我們,讓我們的專業團隊為你量身打造最適合的解決方案!
常見問題 (FAQ)
Q1: Docker Compose 和單純的 Docker 指令有什麼不同?
A: 單純的 `docker run` 指令一次只能啟動和管理一個容器,當你需要啟動多個互相關聯的容器(如 Nginx, WordPress, DB)時,指令會變得非常冗長且難以管理。Docker Compose 則允許你用一個 YAML 設定檔來定義和管理整個應用程式的所有服務,只需一個 `docker-compose up` 指令就能啟動所有服務、設定好網路,讓整個流程變得極度簡潔、可重複且容易版本控制。
Q2: 我的 WordPress 容器連不上資料庫,顯示「Error establishing a database connection」,怎麼辦?
A: 這通常是網路或設定問題。請檢查以下幾點:
1. 服務名稱是否正確: 在 `docker-compose.yml` 中,WordPress 的 `WORDPRESS_DB_HOST` 環境變數值是否設定為資料庫服務的名稱(例如 `db:3306`)?
2. 網路設定: 確認 WordPress 容器和資料庫容器是否都加入了同一個 `networks`。
3. `depends_on`: 確認 WordPress 服務有設定 `depends_on: – db`,確保資料庫先於 WordPress 啟動。
4. 帳號密碼: 再三確認 `WORDPRESS_DB_USER`, `WORDPRESS_DB_PASSWORD`, `WORDPRESS_DB_NAME` 的值與資料庫服務中 `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE` 的值完全一致。
Q3: 我需要為每個 WordPress 專案都建立一個這麼複雜的 `docker-compose.yml` 嗎?
A: 是的,這是最佳實踐。為每個專案建立獨立的 Docker Compose 環境可以確保專案之間的完全隔離,避免版本衝突(例如一個專案需要 PHP 8.1,另一個需要 PHP 7.4)或資料干擾。你可以將這份 `docker-compose.yml` 當作一個標準範本,每次有新專案時,複製一份並根據需求稍作修改(例如更改容器名稱、連接埠映射),這樣可以大大加速新專案的啟動流程。
Q4: 這種架構適合正式上線的生產環境 (Production) 嗎?
A: 絕對適合,但還需要一些強化。本文提供的架構是一個絕佳的起點。要投入生產環境,你還需要考慮:
1. SSL/HTTPS: 整合 Let’s Encrypt 或其他 SSL 憑證來啟用 HTTPS。
2. 安全性: 強化密碼策略、設定防火牆規則、定期更新映像檔版本。
3. 備份與還原: 建立定期的資料庫和檔案卷宗備份機制。
4. 監控與日誌: 整合日誌管理系統(如 ELK Stack)和監控工具(如 Prometheus/Grafana)來追蹤系統健康狀況。但其核心的多服務容器化理念,正是現代雲端應用部署的主流方式。






