跳至正文

Docker 安装 WordPress 并快速手动迁移所有数据

运行环境选择:裸机环境 -> Docker

主要软件选择:NGINX,MariaDB,phpMyAdmin

由于 Mysql 所需内存过多,原先的服务器配置已无法支持运行。

因此在 DigitalOcean 上购买了新的配置的服务器,并决定使用Docker部署,方便管理。

就我观察而言,目前暂无完整的相关教程,在这里做一个简述。

前述

关于Web服务器与数据库程序的选择:

Nginx 和 Apache 各有什么优缺点?MariaDB和MySQL全面对比

参考资料(主要的):

How To Install WordPress With Docker ComposeRunning WordPress with MariaDB

准备工作(你需要什么)

  1. 一台尚在正常运行 WordPress 的服务器
  2. 一个等待部署的环境(可以是同一台服务器,但因为可能需要短暂运行两套完整的WordPress服务,可能需要较多的内存 >= 1G)

安装 Docker

APT 安装 Docker 软件包

参考官方教程安装。

PS:请安装 docker-ce 而非 docker.io,原因:What is docker.io in relation to docker-ce and docker-ee?

给予登录用户 Docker 操作权限

参考官方文档

sudo groupadd docker

sudo usermod -aG docker $USER

编写配置文件

创建一个存放所有配置文件的文件夹

mkdir -p $HOME/.config/wordpress

编写 Docker 配置文件(配置仅供参考,请仔细配置信息解释部分)

$HOME/.config/wordpress/docker-compose.yml

version: '3'
 services:
   db:
     image: mariadb
     container_name: mariadb
     restart: unless-stopped
     env_file: .env
     environment:
       - MYSQL_DATABASE=wordpress
     volumes:
       - dbdata:/var/lib/mysql
     networks:
       - app-network
 wordpress:
     depends_on:
       - db
     image: wordpress:fpm
     container_name: wordpress
     restart: unless-stopped
     env_file: .env
     environment:
       - WORDPRESS_DB_HOST=db:3306
       - WORDPRESS_DB_NAME=wordpress
       - WORDPRESS_DB_USER=$MYSQL_USER
       - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
     volumes:
       - ./php-conf/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
       - wordpress:/var/www/html
     networks:
       - app-network
 webserver:
     depends_on:
       - wordpress
     image: nginx
     container_name: webserver
     restart: unless-stopped
     ports:
       - "80:80"
       - "443:443"
     volumes:
       - wordpress:/var/www/html
       - ./nginx-conf:/etc/nginx/conf.d
       - certbot-etc:/etc/letsencrypt
     networks:
       - app-network
 certbot:
     depends_on:
       - webserver
     image: certbot/certbot
     container_name: certbot
     volumes:
       - certbot-etc:/etc/letsencrypt
       - wordpress:/var/www/html
     command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com
 volumes:
   certbot-etc:
   wordpress:
   dbdata:
 networks:
   app-network:
     driver: bridge

$HOME/.config/wordpress/.env

MYSQL_ROOT_PASSWORD=XXXXXXXX
MYSQL_USER=wordpress
MYSQL_PASSWORD=XXXXXXXX

$HOME/.config/wordpress/.dockerignore

.env
.git
docker-compose.yml
.dockerignore

配置信息解释

.dockerignore

我的理解是类似于 .gitignore 用来忽略非必要的文件

.dockerignore 文件从入门到实践

.env

一个简单的文件,用来存储待会需要使用的环境变量,叫做其他名字或者不创建该文件均可

MYSQL_ROOT_PASSWORD=XXXXXXXX (填入初始 Root 密码)
MYSQL_USER=wordpress (填入 wordpress 数据库操作用户名,可以自由填写)
MYSQL_PASSWORD=XXXXXXXX (填入上面那个用户的初始密码)
# 建议使用密码生成器生成足够安全的密码

docker-compose.yml

用来编排 Docker 镜像。用来描述 Docker 镜像之间的依赖关系及启动它们所设置参数。简言之,就是为了避免手动输入过多的命令,减少操作复杂程度。

使用 docker-compose 替代 docker run

版本信息

version: '3'

用于注明配置文件适配的版本号,当前(2019-07-25)是 3。

MariaDB 数据库配置

   db:
     image: mariadb (启动镜像的名称)
     container_name: mariadb (启动容器的名称,可以叫做其他名字)
     restart: unless-stopped (宿主机重启则自动启动,永不停止)
     env_file: .env (环境变量,文件设置)
     environment:
       - MYSQL_DATABASE=wordpress (存储 WordPress 网站数据的数据库名称,可自由填写)(环境变量,手动设置)
     volumes:
       - dbdata:/var/lib/mysql (数据卷关联,存储数据库文件,也可以在这里挂载宿主机文件/夹)
     networks:
       - app-network (Docker 网络连接环境)

WordPress 配置

 wordpress:
     depends_on:
       - db (提前启动数据库,依赖 db,就是上面那个数据库)
     image: wordpress:fpm (使用fpm版本,默认的 wordpress 容器内置  Apache2 作为 Web 服务器)
     container_name: wordpress
     restart: unless-stopped
     env_file: .env
     environment:
       - WORDPRESS_DB_HOST=db:3306 (数据库连接端口,为默认端口。因为在 Docker 中运行,网络隔离,无需更改)
       - WORDPRESS_DB_NAME=wordpress (数据库名称,可自由填写)
       - WORDPRESS_DB_USER=$MYSQL_USER (数据库登录用户名,绑定配置文件中的值)
       - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD (数据库登录密码)
     volumes:
       - wordpress:/var/www/html (数据卷关联,存储网站文件)
     networks:
       - app-network

NGINX 配置

 webserver:
     depends_on:
       - wordpress
     image: nginx
     container_name: webserver
     restart: unless-stopped
     ports: (端口关联)
       - "80:80"
       - "443:443"
     volumes:
       - wordpress:/var/www/html (WordPress 网站文件)
       - ./nginx-conf:/etc/nginx/conf.d (NGINX 配置文件,尚未编写)
       - certbot-etc:/etc/letsencrypt (关联cerbot-etc数据卷,以使用HTTPS证书文件)
     networks:
       - app-network

Certbot 配置

 certbot:
     depends_on:
       - webserver
     image: certbot/certbot
     container_name: certbot
     volumes:
       - certbot-etc:/etc/letsencrypt (存储获取到的HTTPS证书)
       - wordpress:/var/www/html (验证网站)
     command: certonly --webroot --webroot-path=/var/www/html --email [email protected] --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com (这里的 example.com 需要替换为你自己的网址,[email protected] 需要替换为你自己申请证书的邮箱)

申请 HTTP 证书

Let’s Encrypt 的 HTTPS证书是只要你的Web服务器正常运行就能获得的,所以,我们接下来让 NGINX 能够正常运行。

编写 NGINX 配置(只为了获取证书用)

参考 How To Install WordPress With Docker Compose

创建文件夹

mkdir -p $HOME/.config/wordpress/nginx-conf

$HOME/.config/wordpress/nginx-conf/nginx.conf

server {
        listen 80;
        listen [::]:80;

        server_name example.com www.example.com;

        index index.php index.html index.htm;

        root /var/www/html;

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

        location / {
                try_files $uri $uri/ /index.php$is_args$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 ~ /\.ht {
                deny all;
        }

        location = /favicon.ico { 
                log_not_found off; access_log off; 
        }
        location = /robots.txt { 
                log_not_found off; access_log off; allow all; 
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

运行容器

进入 docker-compose.yml 所在文件夹

cd ~/.config/wordpress

运行容器

docker-compose up -d

你将会看到:

Creating db ... done 
Creating wordpress ... done 
Creating webserver ... done 
Creating certbot   ... done

检查容器状态

docker-compose ps

 Name        Command              State            Ports                  
 mariadb     docker-entrypoint.sh mysqld    Up     3306/tcp                                
 webserver   nginx -g daemon off;           Up     0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
 wordpress   docker-entrypoint.sh php-fpm   Up     9000/tcp

请确认 数据库的3306端口、WordPress 使用的9000端口与两个 NGINX 的Web 服务端口正常开启。

你可以查看log

docker-compose logs service_name

# server_name 为你所想查看的容器名,例如wordpress

确认 测试用HTTPS证书 已获得

docker-compose exec webserver ls -la /etc/letsencrypt/live

total 16
 drwx------ 3 root root 4096 Jul 24 14:58 .
 drwxr-xr-x 9 root root 4096 Jul 25 12:12 ..
 -rw-r--r-- 1 root root  740 Jul 24 14:58 README
 drwxr-xr-x 2 root root 4096 Jul 24 15:10 example.com (这里应该是你所申请的网站的域名)

再次运行单独 cerbot

docker-compose up --force-recreate --no-deps certbot

确认日志正确

Recreating certbot … done
 Attaching to certbot
 certbot      | Saving debug log to /var/log/letsencrypt/letsencrypt.log
 certbot      | Plugins selected: Authenticator webroot, Installer None
 certbot      | Renewing an existing certificate
 certbot      | Performing the following challenges:
 certbot      | http-01 challenge for example.com
 certbot      | http-01 challenge for www.example.com
 certbot      | Using the webroot path /var/www/html for all unmatched domains.
 certbot      | Waiting for verification…
 certbot      | Cleaning up challenges
 certbot      | IMPORTANT NOTES:
 certbot      |  - Congratulations! Your certificate and chain have been saved at:
 certbot      |    /etc/letsencrypt/live/example.com/fullchain.pem
 certbot      |    Your key file has been saved at:
 certbot      |    /etc/letsencrypt/live/example.com/privkey.pem
 certbot      |    Your cert will expire on 2019-08-08. To obtain a new or tweaked
 certbot      |    version of this certificate in the future, simply run certbot
 certbot      |    again. To non-interactively renew all of your certificates, run
 certbot      |    "certbot renew"
 certbot      |  - Your account credentials have been saved in your Certbot
 certbot      |    configuration directory at /etc/letsencrypt. You should make a
 certbot      |    secure backup of this folder now. This configuration directory will
 certbot      |    also contain certificates and private keys obtained by Certbot so
 certbot      |    making regular backups of this folder is ideal.
 certbot      |  - If you like Certbot, please consider supporting our work by:
 certbot      | 
 certbot      |    Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 certbot      |    Donating to EFF:                    https://eff.org/donate-le
 certbot      | 
 certbot exited with code 0

配置 NGINX

参考 How To Install WordPress With Docker Compose

停止 nginx 服务

docker-compose stop webserver

下载 CertBot 预置的 NGINX SSL 配置文件

curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf

编辑 nginx.conf (务必替换掉example.com)

$HOME/.config/wordpress/nginx-conf/nginx.conf

server {
        listen 80;
        listen [::]:80;

        server_name example.com www.example.com;

        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

        location / {
                rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.com www.example.com;

        index index.php index.html index.htm;

        root /var/www/html;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        include /etc/nginx/conf.d/options-ssl-nginx.conf;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications

        location / {
                try_files $uri $uri/ /index.php$is_args$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 ~ /\.ht {
                deny all;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }
        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

CertBot 自动续订

参考 How To Install WordPress With Docker Compose

WordPress 安装完成

到这里,WordPress 的 Docker 环境已经安装完成了。

现在在浏览器上访问你服务器的 IP,应该可以正常看见 WordPress 欢迎界面。

之后的内容是关于网站完整的数据快速迁移部分。

WordPress 数据迁移

数据库迁移

参考官方文档

这里选用 phpMyAdmin 作为数据库操作工具

数据库备份

安装 phpMyAdmin(这部分时间过于遥远,细节已记不清了)

  • APT 安装 phpmyadmin

sudo apt install phpmyadmin

  • 关联 phpMyAdmin 至 Web 服务器

ln -s /uer/share/phpadmin /var/www/html/phpadmin

  • 访问 phpMyAdmin

在浏览器上访问 http://<YOUR IP>/phpmyadmin

导出 WordPress 数据库

  • 选中 WordPress 数据库(你所需要导出的数据库)
  • 点击“导出”按钮
  • 点击“执行”,下载备份文件到本地。

数据库导入

安装 Docker 版本 phpMyAdmin

  • 确认 docker 内部网络连接

docker network ls

NETWORK ID          NAME                    DRIVER              SCOPE
096f53f6440c        bridge                  bridge              local
91cd580e6601        host                    host                local
fd96bc66d20c        none                    null                local
95dc00bd8b48        wordpress_app-network   bridge              local
790a7926eca2        wordpress_default       bridge              local

之前我们在 docker-compose.yml 文件中指定了 MariaDB 数据库的内部网络为:wordpress_app-network

  • 运行 phpMyAdmin

docker run --name myadmin -d --link mariadb:db -p 8081:80 --net wordpress_app-network phpmyadmin/phpmyadmin

Docker 会尝试运行镜像(如果不存在会自动下载),将 phpMyAdmin 与 MariaDB 数据库相链接,并将容器绑定在 wordpress_app-network 中,同时将 Web 访问端口绑定在宿主机的公网 8081 端口。

  • 访问 phpMyAdmin

在浏览器上访问 http://<YOUR IP>:8081

导入 WordPress 数据库

  • 选中 WordPress 数据库(你所需要导入的数据库)
  • 点击“导入”按钮
  • 上传备份文件
  • 点击“执行”

网站文件迁移

网站文件包括了你所安装的插件,你所上传的图片等资源文件。

WordPress 文件备份

SSH 登录老的服务器

ssh -p <你的ssh端口> <你的ssh登录用户名>@<你的旧服务器IP>

  • 确认网站文件位置

ls -la /var/www/html/wordpress

我把文件存放在了wordpress目录下。如果你像我一样,把数据存在了子目录,请在WordPress 控制台修改站点地址(URL)为站点根目录。

total 212
 drwxr-xr-x  5 www-data nogroup   4096 Jul 23 20:41 .
 drwxr-xr-x  3 root     root      4096 Mar 19 08:16 ..
 -rw-r--r--  1 www-data nogroup    420 Feb 27 03:22 index.php
 -rw-r--r--  1 www-data nogroup  19935 May  8 07:09 license.txt
 -rw-r--r--  1 www-data nogroup   7447 Jun 18 17:55 readme.html
 -rw-r--r--  1 www-data nogroup   6919 Feb 27 03:22 wp-activate.php
 drwxr-xr-x  9 www-data nogroup   4096 May  8 07:09 wp-admin
 -rw-r--r--  1 www-data nogroup    369 Feb 27 03:22 wp-blog-header.php
 -rw-r--r--  1 wwexitw-data nogroup   2283 Feb 27 03:22 wp-comments-post.php
 -rw-rw-rw-  1 www-data www-data  3219 May 19  2018 wp-config.php
 -rw-r--r--  1 www-data nogroup   2898 Feb 27 03:22 wp-config-sample.php
 drwxr-xr-x  8 www-data nogroup   4096 Jul 24 22:45 wp-content
 -rw-r--r--  1 www-data nogroup   3847 Feb 27 03:22 wp-cron.php
 drwxr-xr-x 20 www-data nogroup  12288 May  8 07:09 wp-includes
 -rw-r--r--  1 www-data nogroup   2502 Feb 27 03:22 wp-links-opml.php
 -rw-r--r--  1 www-data nogroup   3306 Feb 27 03:22 wp-load.php
 -rw-r--r--  1 www-data nogroup  39551 Jun 18 17:55 wp-login.php
 -rw-r--r--  1 www-data nogroup   8403 Feb 27 03:22 wp-mail.php
 -rw-r--r--  1 www-data nogroup  18962 May  8 07:09 wp-settings.php
 -rw-r--r--  1 www-data nogroup  31085 Feb 27 03:22 wp-signup.php
 -rw-r--r--  1 www-data nogroup   4764 Feb 27 03:22 wp-trackback.php
 -rw-r--r--  1 www-data nogroup   3068 Feb 27 03:22 xmlrpc.php
  • 打包网站文件

sudo tar -czvf ~/html.tar.gz /var/www/html/

  • 修改备份压缩包权限(便于下载)

sudo chown $USER:$USER html.tar.gz

  • 退出SSH登录

exit

下载备份压缩包

scp -r -P <你的ssh端口> <你的ssh登录用户名>@<你的旧服务器IP>:~/html.tar.gz ./

WordPress 文件恢复上传备份压缩包

上传备份压缩包

scp -r -P <你的ssh端口>./html.tar.gz <你的ssh登录用户名>@<你的新服务器IP>:

SSH 登录新的服务器

  • 解压备份压缩包

tar -xzvf ~/html.tar.gz

  • 传入备份文件到 Docker 数据卷

docker cp ~/var/www/html wordpress:/var/www

  • 进入 docker-compose.yml 所在文件夹

cd $HOME/.config/.wordpress

  • 检查传入文件

docker-compose exec webserver ls -la /var/www/html/

你会发现新传入的文件用户都会改为 1000,这样网站可以运行,但是为只读状态(忘记截图了)

  • 修复网站文件权限

docker-compose exec wordpress chown -R www-data:www-data /var/www/html

  • 覆盖 WordPress 文件(如果你把站点放在根目录下)
  1. 进入 WordPress 容器
    docker-compose exec wordpress sh
  2. 覆盖 WordPress 网站文件
    rm /var/www/html/wp-* && mv /var/www/html/wordpress/* /var/www/html/.

理由:WordPress 容器在启动前会检查 /var/www/html 下有无 WordPress 站点文件,所以我建议在容器内使用根目录。如果你需要在服务器上部署多个网站,可以考虑反向代理等。

修复 WordPress 数据库读取

编辑 wp-config.php 文件

cd $/HOME/var/www/html/wordpress

vim wp-config.php # 我之前用得是子目录,请检查你自己具体的文件位置

修改以下部分 与你之前在 .env 文件中设置一致

  • 修改帐号、密码与数据库名称
// ** MySQL 设置 - 具体信息来自您正在使用的主机 ** //
 /** WordPress数据库的名称 */
 define('DB_NAME', 'wordpress');
 /** MySQL数据库用户名 */
 define('DB_USER', 'wordpress');
 /** MySQL数据库密码 */
 define('DB_PASSWORD', '123456');
  • 修改数据库主机端口
/** MySQL主机 */
 define('DB_HOST', 'db:3306');
  • 保存

覆盖 WordPress 数据卷 wp-config.php 文件

docker cp wp-config.php wordpress:/var/www/html/wp-config.php


WordPress 数据恢复完成

  • 关闭 phpMyAdmin

docker stop myadmin

为保证数据库安全,请务必停止,只在需要调试时开启

后记

此次数据迁移主要把握两个方向:环境架设(测试可用)、数据备份(确定相关文件)。

可能会出现的错误及解决方案

  • 新网站运行正常,但访问不显示信息(空白)。

原因:数据库已导入,且正常运行,网站数据未导入成功。

  • 其他问题,请注意以下事项
  1. 请在未导入配置的情况下检查网站是否正常运行。
  2. WordPress 的问题主要是文件与数据库的匹配。

排查方法:

  1. 查看Docker日志
    docker-compose logs service_name
  2. 使用 phpMyAdmin 检查数据库与用户是否正常

《Docker 安装 WordPress 并快速手动迁移所有数据》有7个想法

  1. Pingback: WordPress安装教程 – Hire Camp

  2. 作者,你好!我是腾讯云+社区的小编,关注了您分享的技术文章,觉得很棒,我们诚挚邀请您加入云+社区,与我们众多的社区作者一起为开发者分享技术干货。这个是我们云+社区【腾讯云自媒体分享计划】入驻流程和权益介绍的地址:https://cloud.tencent.com/developer/support-plan。如果您愿意加入或者想了解更多的信息请联系我~微信:techou002,我们对您的加入充满期待。

  3. 您好,我来自V2ex,希望能跟您交换友情链接。

    我的博客也基本上是技术类文章,全部都是原创内容。

    希望得到回复,我的博客地址是:https://www.fi-ads.com/

    非常感谢!

  4. 谢谢, 老白终于搞定.两个半天,学vim, 学docker, 回忆linux.

    自行变更了一些流程, 把certbot部分全部放弃了. http80状态下建站和数据转移全部ok, 继续用mysql, 再参考DO的那篇,我也成了不白拉.谢谢.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

🌍 Language