当前这个网站,好久没维护了。之前是部署在一台比较老旧的 TencentOS 系统上,并且是比较老旧的 apache 版本,整台服务器都很难维护,迁移就比较麻烦,然后就一直放着没动它。原本部署的这台服务器配置也低,虽然一年几十元,但不打算续费了,今年年底就要到期了,就花了点时间捣鼓一下,先将它所有环境从宿主机迁入到 Docker Compose 中,然后整个 Docker Compose 项目打包迁移。当看到这篇文章的时候,是已经迁移成功了,目前部署在 RackNerd 的美国VPS服务器上,我买的是这款配置(超划算RackNerd服务器),非常不错(还拿来搭建了VPN服务器🚀),配置如下:
$29.89 /年 💰 (29.89 美元/年)
- 🖥️ 3 vCPU 核心 (3 vCPU Cores)
- 💾 60 GB SSD 存储 (60 GB SSD Storage)
- 🧠 3.5 GB 内存 (3.5 GB RAM)
- 📡 5 TB 月流量 (5 TB Monthly Transfer)
- 🌐 1Gbps 网络端口 (1Gbps Network Port)
- 🔑 完全根访问权限 (Full Root Access)
- 🌍 1 个 IPv4 地址 (1 IPv4 Address)
- ⚙️ KVM/SolusVM
如果购买的话,尽可能选择 DC3 机房,DC3 机房在中国访问的速度比较友好。在中国访问的速度与国际出入口带宽有关。
目前网站运行状况良好,除了昨天迁移时反复修改了几次 DNS 导致缓存产生而出现 SSL 安全提示之外,今早起来发现也恢复正常了。
现在来回顾一下昨天的迁移过程,怎样把 WordPress 装到 Docker Compose 里面来。主要工作分为三个部分:
第一部分,从宿主机导出 Mysql 数据库。
这个网站使用的是 Mysql 8.0.28 版本,服务器中还有其他网站的数据库,现在需要单独把 WordPress 博客的数据库导出来,也非常简单,只需要在命令行执行以下命令:
“`
mysqldump -u root -p –databases <数据库名称> –routines –events –triggers –single-transaction > <导出保存的名称>.sql
“`
执行之后会提示输出 root 密码,稍等几秒就导出完成了。
此时还需要把原来的 WordPress 网站目录整个复制到 Docker compose 项目根目录下(website)。
也需要去 `wp-config.php` 修改 `DB_HOST` 为 `mysql` 。
第二部分,编写 docker-compose.yml 以及 Dockerfile。
为了把 WordPress 装到容器里,我给它准备了 Dockerfile 和 docker-compose.yml ,服务器本身就有 docker compose 环境,这里就不把环境准备展开赘述了。
Dockerfile:
“`
FROM php:8.3.24-fpm
# 接收构建时代理参数
# ARG http_proxy
# ARG https_proxy
# 安装 mysqli, pdo, pdo_mysql 模块
RUN docker-php-ext-install mysqli pdo pdo_mysql
# 设置 PHP 配置(例如:max_execution_time)
RUN echo ‘max_execution_time = 90’ >> /usr/local/etc/php/conf.d/my-php.ini
# 安装 gd 模块
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd –with-freetype –with-jpeg \
&& docker-php-ext-install gd
# 安装 exif 模块
RUN docker-php-ext-install exif
# 安装 imagick 模块
RUN apt-get install -y libmagickwand-dev –no-install-recommends \
&& (pecl install imagick || true) \
&& docker-php-ext-enable imagick
# 安装 zip 模块
RUN apt-get install -y \
libzip-dev \
zip \
&& docker-php-ext-install zip
# 安装 intl 模块
RUN apt-get install -y libicu-dev \
&& docker-php-ext-install intl
# 清理安装后的文件
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
“`
这份 Dockerfile 主要是构建了 php 环境的容器,并且把一些必须的扩展都打包进去了,有了这个环境就能跑 WordPress 或者其他 php 项目。
docker-compose.yml:
“`
services:
nginx:
image: nginx:1.25.3
restart: always
ports:
– “127.0.0.1:8001:80”
volumes:
– ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
– ./website:/var/www/website
– /etc/letsencrypt:/etc/letsencrypt:ro
– ./ssl:/etc/ssl
– ./nginxlog:/var/log/nginx
depends_on:
– php
networks:
– app-network
php:
build:
context: .
dockerfile: Dockerfile
image: php:8.3.24-fpm
restart: always
volumes:
– ./website:/var/www/website
– ./php/php.ini:/usr/local/etc/php/php.ini
networks:
– app-network
mysql:
image: mysql:8.0.28
container_name: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mysqlrootpassword
volumes:
– ./data:/var/lib/mysql
networks:
– app-network
phpmyadmin:
image: phpmyadmin/phpmyadmin
restart: always
ports:
– “127.0.0.1:8002:80”
environment:
PMA_HOST: mysql
MYSQL_ROOT_PASSWORD: mysqlrootpassword
depends_on:
– mysql
networks:
– app-network
networks:
app-network:
driver: bridge
“`
有了这两个文件,Docker Compose 就可以跑起来了。但还需要补充一下 php.ini 和 nginx.conf,因为我让这个 Docker Compose 同时提供了 php 和 nginx 的服务。
php/php.ini:
“`
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = Off
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
variables_order = “GPCS”
request_order = “GP”
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 200M
auto_prepend_file =
auto_append_file =
default_mimetype = “text/html”
default_charset = “UTF-8”
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 60M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[imap]
[intl]
[sqlite3]
[Pcre]
[Pdo]
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = On
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = “a=href,area=href,frame=src,form=”
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = 1
[COM]
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir=”/tmp”
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[dba]
[opcache]
[curl]
[openssl]
[ffi]
“`
nginx/nginx.conf
“`
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 映射 HTTPS 状态(用于 fastcgi_param)
map $http_x_forwarded_proto $fastcgi_https {
default off;
https on;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
error_log /var/log/nginx/error.log debug;
access_log /var/log/nginx/access.log;
root /var/www/website;
index index.html index.htm index.php;
client_max_body_size 1000M;
# 处理静态文件请求
location ~* \.(ico|gif|jpg|jpeg|png|js|css)$ {
try_files $uri =404;
}
# 防止访问特定文件类型
location ~* \.(bak|inc|lib|sh|tpl|lbi|dwt)$ {
deny all;
return 404;
}
# 处理 PHP 文件
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS $fastcgi_https; # 识别 HTTPS
fastcgi_pass php:9000;
fastcgi_index index.php;
}
# URL 重写规则
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?route=$1 last;
}
}
}
“`
至此,第二部分就完成了,使用 docker compose build --no-cache && docker compose up -d
启动容器。
第三部分,数据库导入。
在第二部分中,docker-compose.yml 首次启动时创建的是空的数据库,我们需要把原来备份的数据库文件复制到容器内,并且在容器内恢复数据库以及创建用户和权限。
复制数据库文件到容器:
`docker cp <导出保存的名称>.sql.sql mysql:/<导出保存的名称>.sql`
进入容器内导入原备份的 .sql 数据到数据库中
“`
docker exec -it mysql bash
ls -lt /<导出保存的名称>.sql
mysql -u root -p < /<导出保存的名称>.sql
“`
通过以下三条命令创建用户和权限:
用户名、数据库名、用户密码都必须与 wordpress 一致,并且使用 % 可以从任意 IP 登录。
“`
CREATE USER ‘wwwbg7iaecom’@’%’ IDENTIFIED BY ‘Web3900,.’;
GRANT ALL PRIVILEGES ON wwwbg7iaecom.* TO ‘wwwbg7iaecom’@’%’;
FLUSH PRIVILEGES;
SELECT user, host FROM mysql.user;
“`
完成以上操作之后,退出容器。重启一次 Docker Compose: docker compose down && docker compose up -d
至此,就完成了整个项目的迁移了,现在可以通过 http://127.0.0.1:8001 访问 WordPress 博客了。
还不够,对不对?用户怎么通过 http://127.0.0.1:8001 访问嘛?没错,还需要宿主机的 nginx 反代一下到 http://127.0.0.1:8001 ,或者使用 Cloudflare Tunnel 反代也可以。做完就个动作,整个项目才算真正迁移完毕。
现在你看到的这篇文章,就是已经迁移完的结果了。
(这篇文章发完,才发现这个网站还没支持代码块功能,后面抽个时间给它加上。)