WordPress 的遷移問題對我來講一直是個大難題。
其實也不是對我,這東西遷移雖然麻煩,但也只要複製個目錄然後給資料庫寫個 SQL(不換域名甚至不用寫)就搞定了,現在甚至有現成的插件(如 Duplicator)可以一鍵搞定,我擔心的是風藍(前情提要見 當我們談論風藍官網時我們在談論什麼)。
對於風藍來講其實需要一個更加傻瓜更加一鍵(雖然這不一定是好事)的解決方案,作為多年 Docker 用戶自然想到了容器化。用 Docker Compose 可以把網站和資料庫打包在一個目錄裡,移動到新機器不用修改,並且實現一行命令的啟動或停止。
實際操作起來還遇到了蠻多坑(包括之前不使用 Docker 時來不及記錄的),在這裡一並寫一下。
操作步驟#
Compose 文件來自 docker/awsome-compose:
services:
db:
# We use a mariadb image which supports both amd64 & arm64 architecture
image: mariadb:10.6.4-focal
# If you really want to use MySQL, uncomment the following line
#image: mysql:8.0.27
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
expose:
- 3306
- 33060
wordpress:
image: wordpress:latest
volumes:
- wp_data:/var/www/html
ports:
- 80:80
restart: always
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
wp_data:
實際操作的時候只是把掛載的兩個卷 db_data
和 wp_data
提到本地目錄中,其他基本不變。
這一步會創建兩個容器,一個 mariadb 資料庫和一個 nginx+wordpress 的 web 伺服器。 wordpress
映射出來的端口如果宿主機上沒裝 web 伺服器可以直接 80
,我是不太習慣映射到別的端口之後做反代的(寶塔新版本可以直接創建反代項目了,這點好評究竟是誰 2024 年了還在用寶塔),此處不再贅述。
docker compose up -d
之後訪問端口或域名就是一個全新的 wordpress,如果需要遷移的話可以用上文提到的 Duplicator 直接打包放到 wp_data
裡安裝。
踩坑#
終於到了我最喜歡的環節最折磨的排坑環節,現在看來大多數問題都不是容器化而是 WordPress 本身的一些麻煩特性,更加堅定了我雖然 WordPress 很好但是還是要堅決舍棄的信念。
需要注意的是,下面的幾乎所有問題我都沒有進行刨根問底了解原因,只是簡單推測 + 搜索解決方案罷了。歸根結底是我認為如果需要用這種奇技淫巧才能保證在現代環境下的使用的話,也不需要浪費大量的時間在折騰這些東西上,能用就行了。
ERR_TOO_MANY_REDIRECTS#
這個問題在我將設置中的 WordPress 地址和站點地址均改為 https://example.com
後出現了,訪問網站本身沒有問題,但是在訪問管理站點的時候卻會報 ERR_TOO_MANY_REDIRECTS
。在多次重啟以及苦等後都沒有改善後,我找到了 StackExchange 裡的這篇帖子,一下子就想明白了。
原生 WordPress 本身是不支持在站點內設置 HTTPS 的,因此我的 SSL 設置在反代位置的 Nginx。而 WordPress 的地址設置又掌管著其重定向的 Base URL,所以在訪問帶 https 的站點後,外層 Nginx 將我帶向了內層的 WordPress,而此時根據設置,WordPress 又要將我重定向到 https 站點,這樣一來二去重定向就進入了死循環。
我自己的解決方案有點類似這樓,只是我明確知道沒有在 Docker 中的 Nginx 裡設置 SSL,所以索性把地址改回 http
開頭好了。
有很多種改法,如果可以訪問到資料庫的話,可以修改 [sitename]_options
表裡的 home
和 siteurl
字段。也可以在文件根目錄的wp-config.php
裡加上:
define('WP_HOME','http://example.com');
define('WP_SITEURL','http://example.com');
同時,在修改了 wp-config.php
之後,站點設置中被覆蓋的項會變灰不能修改,也即資料庫中的值無用,這點請務必注意我就疑惑了好久為什麼改不了。
插件安裝與目錄權限#
對於直接在宿主機安裝的 WordPress,插件安裝是很順滑的,不需要特殊的操作就可以在插件市場一鍵安裝。但是 Docker 映像有一個問題,就是 WordPress 的官方映像是以 www-data
用戶運行的,而複製進去 / 自動創建的文件權限不對,這就導致在安裝插件時需要填寫 ftp 帳號云云。
解決方法參考了這個 issue 以及回覆中提到的 gist ,首先還是熟悉的在 wp-config.php
中添加:
define('FS_METHOD', 'direct');
這會改變插件的安裝模式。接著在終端中改變 WordPress 文件夾的所有者及權限:
docker exec -u root -it {CONTAINER_ID} /bin/bash
chown -R www-data wp-content
chmod -R 755 wp-content
當然我沒有改所有者而是直接把文件夾權限改到 777
了,別學我,會被打的()一說好像風藍官網上次下線就是因為被黑客打掉來著
優缺點#
私以為把 WordPress 這種古早框架遷移到 Docker 裡還是有一些優點的:
-
易於遷移
我最喜歡的優點,整個網站都在一個文件夾裡,真要搬家不需要備份恢復資料庫,不需要改設置,直接一整個目錄打個壓縮包就帶走了。
-
易於部署
整個系統的啟動只需要一句
docker compose up -d
,關閉和重啟也都是一句解決,也可以方便地用docker compose logs
同時看兩個容器的日誌。雖然原則上並不推薦資料庫進容器,但是容器!爽! -
更加安全(?)
在 Docker Compose 中資料庫和 WordPress 本體全都在虛擬網路中,平常資料庫對外不會暴露端口,降低了被打的風險。不過這點比較存疑,因為只要 WordPress 能訪問資料庫,直接攻破 WordPress 現有漏洞的成本也很低。
當然,缺點也很明顯:
-
資料庫以及文件訪問更加繁瑣
放進 Docker 之後文件和端口都需要映射才能訪問,有些操作更是需要進入容器內進行,就資料庫和文件管理上確實比之前繁瑣了。當然也可以在 Compose 的配置中加入 PHPMyAdmin 這種資料庫管理程序(成品),但是端口管理有點麻煩而且我沒有成功部署,可以自行嘗試。
-
需要處理權限問題
正如前文所言,Docker 也同樣意味著容器內外更容易出現所有者和權限不一致的問題,而且通常解決也要耗費一定的時間(可能要回去看 Dockerfile 或者進入容器)
-
訪問速度變慢
這是我最不能接受的缺點,本來 WordPress 就以其孱弱的性能臭名昭著,進 Docker 之後每次文件訪問要經過目錄掛載,每次資料庫請求也要經過目錄掛載,體感上網站的加載時間甚至增加了 100% 以上。
總結與展望#
總體而言算是還比較愉悅的體驗,但是在折騰這個的時候我發現自己伺服器上的面板突然無法讀出 Nginx 配置,在極慢的訪問速度和時不時掛掉的宿主機 Nginx 雙重壓力下,我覺得我還是會轉向更加新的技術棧。都 2024 年了,為什麼要花這麼長時間來折騰一個甚至不原生支持 HTTPS 的博客框架呢(但事實證明確實 WordPress 有其存在的必要,它還是目前社區最大可定制程度最高且支持多作者寫作的全功能 CMS),該進行新的選型了!
今天看到了一些新的優化方法(Redis, jsDelivr), 如果之後還有精力的話可能會嘗試折騰一下,畢竟現在風藍幾乎全部的 post 都在 WordPress 上,丟了屬實是有一些可惜。