欢迎光临

Docker Compose部署WordPress完全实战:MariaDB配置、Nginx反代与Let’s Encrypt自动SSL一站式建站指南

WordPress作为全球使用最广泛的内容管理系统,占据了超过40%的网站市场份额。然而传统的WordPress部署方式——手动安装PHP、MySQL、Nginx/Apache——不仅步骤繁琐,而且环境隔离性差、迁移困难、版本升级容易踩坑。Docker Compose的出现彻底改变了这一局面:通过一个

1
docker-compose.yml

文件,我们可以定义完整的WordPress运行环境,包括数据库、Web服务器、SSL证书自动续期,实现一键部署、秒级重建和无缝迁移。

本文将手把手教你用Docker Compose在VPS上部署一个生产级WordPress站点,涵盖MariaDB数据库配置、Nginx反向代理、Let’s Encrypt自动SSL证书、数据持久化与备份恢复等完整流程。无论你是第一次建站的新手,还是希望从传统部署迁移到容器化的老站长,都能从中获得可直接复用的配置和实战经验。

服务器机房与Docker容器化部署场景

一、为什么用Docker Compose部署WordPress:容器化建站的核心优势

传统WordPress部署最大的痛点在于环境依赖管理。PHP版本、MySQL配置、Nginx规则、SSL证书——这些组件之间相互依赖,一旦某个环节出问题,排查成本极高。Docker Compose通过容器化技术将每个组件封装在独立容器中,各自拥有隔离的文件系统和网络,从根本上解决了”在我的机器上能跑”的问题。

容器化部署WordPress的具体优势包括:

对比维度 传统部署(宝塔/LNMP) Docker Compose部署
环境一致性 依赖手动配置,易出现环境差异 镜像固化环境,开发生产完全一致
部署速度 30分钟-2小时(含排错) 5分钟(拉取镜像即就绪)
迁移成本 需重新配置全部环境 复制compose文件+数据卷即可
版本升级 手动编译,风险高 修改镜像tag,一键回滚
资源隔离 共享系统环境,互相干扰 容器隔离,CPU/内存可限制
SSL证书 手动配置certbot或面板 自动化容器,零干预续期

对于VPS建站场景,Docker Compose还有一个常被忽视的优势:数据卷持久化。所有WordPress文件、数据库数据、上传的图片都挂载在宿主机目录中,即使容器被删除重建,数据也完整保留。这意味着你可以随时升级WordPress版本、切换PHP版本、甚至更换VPS,而不会丢失任何站点数据。

如果你想了解Docker Compose更基础的知识,可以参考我们之前写的Docker + Docker Compose实战指南,本文将在此基础上聚焦WordPress专用配置。

二、项目结构与核心配置文件

一个生产级的Docker Compose WordPress部署项目结构如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wordpress-docker/
├── docker-compose.yml          # 核心编排文件
├── .env                        # 环境变量(密码等敏感信息)
├── nginx/
│   ├── nginx.conf              # Nginx主配置
│   └── conf.d/
│       └── wordpress.conf      # WordPress站点配置
├── mysql/
│   └── init/
│       └── init.sql             # 数据库初始化脚本(可选)
├── wordpress/
│   └── wp-content/              # WordPress内容目录(持久化挂载)
└── certbot/
    ├── conf/                    # SSL证书存储
    └── www/                     # 证书验证目录

首先创建项目目录和

1
.env

文件。将敏感信息(数据库密码等)放在

1
.env

中是Docker Compose的最佳实践,避免在

1
docker-compose.yml

中硬编码密码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mkdir -p wordpress-docker/{nginx/conf.d,mysql/init,wordpress/wp-content,certbot/conf,certbot/www}
cd wordpress-docker

# 创建环境变量文件
cat > .env << 'EOF'
# 数据库配置
MYSQL_ROOT_PASSWORD=YourStrongRootPass123!
MYSQL_DATABASE=wordpress
MYSQL_USER=wp_user
MYSQL_PASSWORD=YourStrongWpPass456!

# WordPress配置
WORDPRESS_DB_HOST=db:3306
WORDPRESS_DB_NAME=wordpress
WORDPRESS_DB_USER=wp_user
WORDPRESS_DB_PASSWORD=YourStrongWpPass456

# 域名
DOMAIN=example.com
EMAIL=admin@example.com
EOF

安全提示:务必使用强密码(至少16位,包含大小写字母、数字和特殊字符),切勿使用示例中的默认密码。

1
.env

文件应加入

1
.gitignore

,不要提交到版本库。

三、Docker Compose编排文件详解:WordPress + MariaDB + Nginx + Certbot

核心的

1
docker-compose.yml

文件定义了四个服务:Nginx(反向代理)、WordPress(PHP-FPM)、MariaDB(数据库)、Certbot(SSL证书自动化)。下面逐段解析每个服务的配置要点。

数据库与容器编排架构图


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
version: '3.8'

services:
  db:
    image: mariadb:10.11
    container_name: wp_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d
    networks:
      - wp_internal
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  wordpress:
    image: wordpress:6.4-php8.2-fpm
    container_name: wp_app
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST}
      WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
    volumes:
      - wp_data:/var/www/html
      - ./wordpress/wp-content:/var/www/html/wp-content
    networks:
      - wp_internal

  nginx:
    image: nginx:1.25-alpine
    container_name: wp_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - wp_data:/var/www/html:ro
      - certbot_conf:/etc/letsencrypt:ro
      - certbot_www:/var/www/certbot:ro
    depends_on:
      - wordpress
    networks:
      - wp_internal

  certbot:
    image: certbot/certbot:latest
    container_name: wp_certbot
    restart: unless-stopped
    volumes:
      - certbot_conf:/etc/letsencrypt
      - certbot_www:/var/www/certbot
    entrypoint: >
      sh -c "trap exit TERM;
      while :; do
        certbot renew --webroot -w /var/www/certbot --quiet
        sleep 12h
      done"
    networks:
      - wp_internal

volumes:
  db_data:
  wp_data:
  certbot_conf:
  certbot_www:

networks:
  wp_internal:
    driver: bridge

上述配置中有几个关键设计决策值得展开说明:

1. 使用MariaDB而非MySQL。MariaDB 10.11是当前长期支持版本,对WordPress兼容性极佳,且在容器环境中内存占用比MySQL低15%-20%。对于1核512M的小型VPS,MariaDB的优势尤为明显。

2. PHP-FPM而非Apache镜像。选择

1
wordpress:6.4-php8.2-fpm

而非默认的Apache镜像,是因为Nginx + PHP-FPM的组合在高并发下性能显著优于Apache mod_php。PHP 8.2相比7.4在WordPress场景下性能提升约30%。

3. 健康检查机制。MariaDB服务配置了

1
healthcheck

,WordPress的

1
depends_on

使用

1
condition: service_healthy

。这确保WordPress容器在数据库完全就绪后才启动,避免首次启动时连接数据库失败的竞态条件。

4. Certbot自动续期。证书有效期90天,续期容器每12小时检查一次(Let’s Encrypt建议每12小时检查,实际续期只在到期前30天才会执行)。这种设计无需在宿主机配置cron任务。

四、Nginx反向代理配置:性能优化与安全加固

Nginx配置是整个部署中技术含量最高的部分。我们需要处理HTTP到HTTPS的跳转、Let’s Encrypt验证、WordPress的伪静态规则、以及各种安全头和性能优化。

首先是Nginx主配置文件

1
nginx/nginx.conf

:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
   
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';
   
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
   
    # 基础性能优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;
   
    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 256;
    gzip_types
        text/plain text/css text/xml text/javascript
        application/json application/javascript application/xml
        application/rss+xml application/atom+xml image/svg+xml;
   
    # 上游PHP-FPM
    upstream php-fpm {
        server wordpress:9000;
        keepalive 32;
    }
   
    # 限制请求体大小(WordPress上传文件)
    client_max_body_size 64m;
    client_body_timeout 60s;
   
    include /etc/nginx/conf.d/*.conf;
}

接下来是WordPress站点配置

1
nginx/conf.d/wordpress.conf

,包含SSL配置和WordPress伪静态规则:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# HTTP -> HTTPS 重定向 + Let's Encrypt验证
server {
    listen 80;
    server_name example.com www.example.com;
   
    # Let's Encrypt证书验证
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
   
    # 其余请求重定向到HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS 主站点
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
   
    # SSL证书路径
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
   
    # SSL安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
   
    # HSTS安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
   
    # WordPress根目录
    root /var/www/html;
    index index.php index.html;
   
    # WordPress伪静态规则
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
   
    # PHP文件处理
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass php-fpm;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS on;
       
        # FastCGI性能优化
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout 120s;
        fastcgi_send_timeout 120s;
    }
   
    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
   
    # 禁止访问敏感文件
    location ~ /\.(ht|git|env) {
        deny all;
    }
    location ~ /(wp-config\.php|xmlrpc\.php|readme\.html|license\.txt) {
        deny all;
    }
}

关于Nginx配置的更多性能调优技巧,如worker进程数调优、连接数优化等,可以参考我们的Nginx性能调优与安全加固指南。

五、首次部署:SSL证书初始化与一键启动

由于首次获取SSL证书需要Nginx先在80端口运行以响应Let’s Encrypt的验证请求,我们需要分两步部署:先以HTTP模式启动Nginx获取证书,再切换到完整HTTPS配置。

步骤1:创建临时HTTP配置获取证书


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 临时HTTP配置(仅用于首次获取证书)
cat > nginx/conf.d/wordpress.conf << 'EOF'
server {
    listen 80;
    server_name example.com www.example.com;
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}
EOF

# 启动Nginx和Certbot容器
docker compose up -d nginx

# 获取SSL证书
docker compose run --rm certbot certonly   --webroot -w /var/www/certbot   --email admin@example.com   --agree-tos --no-eff-email   -d example.com -d www.example.com

# 证书获取成功后,替换为完整配置(上面的HTTPS版本)
# 重新加载Nginx
docker compose restart nginx

步骤2:一键启动全部服务


1
2
3
4
5
6
7
8
# 启动所有服务
docker compose up -d

# 查看运行状态
docker compose ps

# 查看日志
docker compose logs -f --tail=50

启动成功后,浏览器访问

1
https://example.com

即可看到WordPress安装向导。完成安装后,建议立即在WordPress后台进行以下安全配置:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 在wp-config.php中添加安全配置(通过容器执行)
docker compose exec wordpress sh -c '
cat >> /var/www/html/wp-config.php << "WPCONF"

// 禁用文件编辑
define("DISALLOW_FILE_EDIT", true);
// 自动更新核心
define("WP_AUTO_UPDATE_CORE", true);
// 限制修订版本数量
define("WP_POST_REVISIONS", 5);
// 自动清空回收站(天数)
define("EMPTY_TRASH_DAYS", 7);
WPCONF
'

WordPress Docker部署完成后的管理界面

六、数据备份与迁移:让站点永不丢失

容器化部署最大的误区是认为”容器就是数据”。事实上,容器本身是无状态的,真正的数据存储在 volumes 中。一个完整的备份方案需要同时备份数据库和WordPress文件。

以下是一个生产可用的自动备份脚本,支持数据库导出和文件打包:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash
# wordpress-backup.sh — WordPress Docker站点自动备份
set -euo pipefail

BACKUP_DIR="/root/backups/wordpress"
RETAIN_DAYS=30
PROJECT_DIR="/root/wordpress-docker"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/wp_backup_${DATE}.tar.gz"

mkdir -p "$BACKUP_DIR"
cd "$PROJECT_DIR"

# 1. 导出数据库
echo "[$(date)] 开始导出数据库..."
docker compose exec -T db mysqldump   -u root -p"${MYSQL_ROOT_PASSWORD}"   --single-transaction   --routines --triggers   "${MYSQL_DATABASE}" > "${BACKUP_DIR}/db_${DATE}.sql"

# 2. 打包WordPress文件和数据库导出
echo "[$(date)] 打包备份文件..."
tar czf "$BACKUP_FILE"   "${BACKUP_DIR}/db_${DATE}.sql"   docker-compose.yml .env   nginx/ wordpress/wp-content/

# 3. 清理临时文件
rm -f "${BACKUP_DIR}/db_${DATE}.sql"

# 4. 清理过期备份
find "$BACKUP_DIR" -name "wp_backup_*.tar.gz" -mtime +${RETAIN_DAYS} -delete

# 5. 显示备份结果
SIZE=$(du -sh "$BACKUP_FILE" | cut -f1)
echo "[$(date)] 备份完成: $BACKUP_FILE ($SIZE)"
echo "[$(date)] 当前备份总数: $(ls -1 ${BACKUP_DIR}/wp_backup_*.tar.gz | wc -l)"

将此脚本加入crontab即可实现自动备份:


1
2
# 每天凌晨3点自动备份
0 3 * * * /bin/bash /root/wordpress-docker/wordpress-backup.sh >> /var/log/wp-backup.log 2>&1

迁移到新VPS只需三步:复制

1
docker-compose.yml

和

1
.env

文件、传输备份的

1
wp-content

目录、导入数据库SQL文件。这比传统部署的迁移效率提升了10倍以上。如果你需要将备份自动同步到对象存储,可以参考我们的Nginx反向代理与Let’s Encrypt自动SSL配置指南中关于多站点管理的方案。

七、常见问题排查与性能调优

在实际运行中,你可能会遇到以下常见问题。这里给出排查思路和解决方案:

问题现象 可能原因 解决方案
502 Bad Gateway PHP-FPM未启动或超时 检查docker compose logs wordpress,增加fastcgi_read_timeout
数据库连接失败 MariaDB未就绪 检查healthcheck状态,确认depends_on条件
SSL证书获取失败 域名DNS未解析到VPS 用dig example.com确认解析,等待DNS传播
上传文件403/413 请求体超过Nginx限制 调整client_max_body_size为64m或更大
页面加载慢 PHP-FPM进程数不足 配置PHP_FPM_PM_MAX_CHILDREN参数
内存溢出(OOM) 容器内存限制过低 在compose中添加mem_limit,或升级VPS

对于1核512M的低配VPS,建议做以下优化:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 针对低配VPS的资源限制
services:
  db:
    deploy:
      resources:
        limits:
          memory: 256M
    command: >
      --innodb-buffer-pool-size=128M
      --innodb-log-file-size=32M
      --max-connections=50
      --key-buffer-size=16M
      --table-open-cache=200
     
  wordpress:
    deploy:
      resources:
        limits:
          memory: 128M
    environment:
      PHP_FPM_PM: dynamic
      PHP_FPM_PM_MAX_CHILDREN: 8
      PHP_FPM_PM_START_SERVERS: 2
      PHP_FPM_PM_MIN_SPARE_SERVERS: 1
      PHP_FPM_PM_MAX_SPARE_SERVERS: 3

对于高配VPS(2核2G以上),可以启用FastCGI缓存进一步提升性能:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 在nginx.conf的http块中添加
fastcgi_cache_path /var/cache/nginx levels=1:2
    keys_zone=wordpress:100m inactive=60m
    max_size=1g use_temp_path=off;

# 在wordpress.conf的server块中添加
set $skip_cache 0;
# 登录用户和POST请求不缓存
if ($http_cookie ~* "wordpress_logged_in") { set $skip_cache 1; }
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }

location ~ \.php$ {
    fastcgi_pass php-fpm;
    fastcgi_cache wordpress;
    fastcgi_cache_valid 200 301 302 10m;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    fastcgi_cache_use_stale error timeout invalid_header;
    add_header X-Cache-Status $upstream_cache_status;
}

启用FastCGI缓存后,匿名访客的页面加载速度通常可以提升3-5倍,因为PHP-FPM只在缓存未命中时才被调用。

总结

用Docker Compose部署WordPress是一次性投入、长期受益的选择。本文覆盖了从项目结构设计、核心配置文件编写、Nginx反向代理与SSL自动化、首次部署流程、数据备份到性能调优的完整链路。核心要点总结如下:

  1. 环境隔离:MariaDB、WordPress、Nginx各自运行在独立容器中,互不干扰,迁移时只需复制配置和数据卷
  2. SSL自动化:Certbot容器每12小时检查证书状态,到期前30天自动续期,完全零维护
  3. 数据持久化:通过Named Volumes和bind mounts确保数据安全,容器重建不影响站点数据
  4. 性能可调:从512M低配VPS到4核8G高配服务器,通过调整PHP-FPM进程数和FastCGI缓存即可适配
  5. 备份可复用:一套备份脚本覆盖数据库和文件,迁移到新VPS只需三步操作

相比传统的宝塔面板或手动LNMP部署,Docker Compose方案在环境一致性、部署速度、迁移便利性和升级安全性上都有质的飞跃。如果你正在规划一个新WordPress站点或考虑从传统部署迁移,这套方案是当前最成熟的容器化建站实践之一。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Docker Compose部署WordPress完全实战:MariaDB配置、Nginx反代与Let’s Encrypt自动SSL一站式建站指南
分享到: 更多 (0)