Docker Compose 實戰:一份 YAML 指揮 WordPress、Nginx、Redis、MariaDB 四重奏
☰ 目錄 table-of-contents.md
如果你還記得,我們之前聊過如何用 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 憑證管理、更完善的備份策略),它完全有能力成為你正式上線網站的基石。這就是容器化帶來的革命:它模糊了開發與維運的界線,讓開發者能更好地掌控自己的應用程式。
延伸閱讀
- n8n、Make、Zapier 怎麼選?2026 自動化平台完整比較
- 「在我電腦明明可以跑的?」WordPress Docker 容器化部署終極教學
- 你的 Nginx 還在用預設值?資深工程師的 WordPress 效能調校聖經,榨乾伺服器最後一滴效能!
- 網站慢到想哭?解鎖 WordPress 終極加速密技:Redis 物件快取實戰教學
打造一個穩固又高效的網站架構是專案成功的基礎。如果你在部署過程中遇到任何問題,或是希望為你的企業導入更專業、更客製化的 DevOps 流程與網站架構,浪花科技的團隊擁有豐富的實戰經驗。我們不只是寫程式,更是你數位轉型路上的技術夥伴。
別讓複雜的技術問題拖慢你的腳步,立即聯繫我們,讓我們的專業團隊為你量身打造最適合的解決方案!
常見問題
用 Docker Compose 部署的 WordPress 高效能架構通常包含哪些服務?
為什麼不把 WordPress、資料庫、快取全部塞進同一個 Docker 容器?
Docker Compose 中的 Volume(卷宗)有什麼用,為什麼資料庫一定要用?
在 Docker Compose 中,WordPress 容器要怎麼連到 MariaDB 容器?
WordPress 的 Docker 映像檔為什麼選用 fpm-alpine 版本?
訂閱免費電子報
把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。