通过 Docker 部署 WordPress 搭建博客保姆级教程

前言(废话)

因为最近想搭建一个属于自己的博客,这样就能像筑巢一样随意装饰自己的家,没有那么多的平台约束。虽然搭建个人博客的框架有很多,比如HEXO,HUGO,VuePress等,但在思前想后,最终还是选择了WordPress。

我在部署过程中遇到了一系列的问题:需要什么服务,Mysql、PHP、Nginx?如何突破WordPress的上传文件大小限制?如何使用Nginx配置域名访问?如何配置SSL证书实现HTTPS域名访问?通过Nginx对WordPress进行反向代理后,出现样式丢失以及无法登陆后台如何解决?如何使用挂载卷持久化存储数据,防止容器重启/崩溃后造成数据丢失?

对于小白来说,上述的问题每一个都只能像无头苍蝇般搜罗大量碎片化的资料,才有可能搜到真正实用的。由于我也经历过这么一段痛苦的时刻,在部署过程中,借鉴了许多大佬的方法,因此想写一篇这样的教程,一是为了怕自己忘记,二是为了让其它人也能完完整整地全流程顺利地部署下来。

 

本文 WordPress 基于 Ubuntu 云服务器搭建,接下来进入正题:

 

需要用到的软件:

Xshell,Xftp,Navicat(任意一款数据库管理工具)

 

重装Docker

服务器默认的 Docker 版本较低,所以最好进行一下更新。

卸载旧版本 Docker:

sudo apt-get remove docker docker-engine docker.io containerd runc

更新软件包:

sudo apt-get update

sudo apt-get upgrade

安装依赖包:

sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

添加 Docker 的官方 GPG 密钥:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

添加 Docker 的稳定版软件源:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

再次更新软件包:

sudo apt-get update

安装 Docker Engine 和 containerd:

sudo apt-get install docker-ce docker-ce-cli containerd.io

验证 Docker 的安装是否成功:

sudo docker run hello-world

添加用户到 Docker 组(可在不使用 sodu 的情况下运行 docker 命令):

sudo usermod -aG docker $USER

最后将 Docker 设置为开机自启动:

sudo systemctl enable docker

配置 Docker 镜像加速源:

用 ftp 打开 /etc/docker 目录,该目录下有一个 daemon.json文件(没有的话可以自己新建一个,名字要同名),记事本打开编辑,粘贴配置国内镜像源(24年8月29日更新,如果后面拉取镜像的时候还是会提示超时,可以上网查找最新更新的镜像源去替换):

 {
   "registry-mirrors": [
     "https://docker.registry.cyou",
     "https://docker-cf.registry.cyou",
     "https://dockercf.jsdelivr.fyi",
     "https://docker.jsdelivr.fyi",
     "https://dockertest.jsdelivr.fyi",
     "https://mirror.aliyuncs.com",
     "https://dockerproxy.com",
     "https://mirror.baidubce.com",
     "https://docker.m.daocloud.io",
     "https://docker.nju.edu.cn",
     "https://docker.mirrors.sjtug.sjtu.edu.cn",
     "https://docker.mirrors.ustc.edu.cn",
     "https://mirror.iscas.ac.cn",
     "https://docker.rainbond.cc",
   ]
 }

 

------ 后续的操作,推荐大家在电脑桌面开个记事本,记录一下用到的指令,以防自己忘记做过哪些操作了,出问题了,也方便自己回溯找到错误的地方 ------

 

拉取 WordPress 最新镜像

执行以下命令拉取镜像(默认最新)

docker pull wordpress

 

镜像拉取成功后,启动运行 WordPress 容器:

docker run -it --name wordpress -p 9999:80 -v /usr/local/share/wordpress:/var/www/html -d wordpress

 

这里解释一下上面的命令

--name wordpress => 为容器指定一个名称,此处命名为 wordpress

-p 9999:80 => 将容器内部的端口映射到宿主机的端口,此处容器将80端口映射到宿主机的9999端口

-v /usr/local/share/wordpress:/var/www/html => 使用挂载卷将宿主机的目录挂载到容器内部,此处是将宿主机的 /usr/local/share/wordpress 挂载到容器内部的 /var/www/html 目录。宿主机目录是什么意思呢,就是打开 ftp 你所看到的目录就是宿主机上实际的目录,操作(增删改)宿主机上 /usr/local/share/wordpress 这个目录下的文件,等同于操作容器内部的 /var/www/html 这个目录,可以看成自动同步吧,我是这么理解的

-d => 这个参数代表以 “detached” 模式运行容器,就是在后台运行

-d 后面的wordpress => 就是刚才拉取的 wordpress 镜像名称

 

这样使用数据卷挂载容器目录的方法,就可以将容器运行时产生的数据持久化存储起来,即使容器被删除或者重新创建,数据也不会丢失,仍然存在于宿主机的目录下。

 

查看容器状态:

运行命令

docker ps

即可看到正在运行的容器

这是我服务器中 docker 内运行的容器状态,由于已经全部配置过了,所以会显示这些。nginx 和 mysql 是我们后面需要的容器,在这一步只需要看到 wordpress 有显示就可以了。

 

 

安装 WordPress 博客程序

在浏览器访问 http://ip:9999/wp-admin/setup-config.php 进行安装

这里的 ip 是你服务器的公网ip,因为我的服务器是阿里云的,记得访问前要在安全组管理规则那放开 9999 端口!

 

选简体中文然后到下一步

 

到达该配置界面,由于目前还没配置数据库,容器中还没有 mysql 服务,所以可以先把网页晾在一边。

 

安装配置 Mysql

运行 mysql 服务,启动容器
 docker run -d --name mysql -v /usr/local/share/mysql/data:/var/lib/mysql -v /usr/local/share/mysql/conf:/etc/mysql/conf.d -v /usr/local/share/mysql/logs:/var/log/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8

不要直接复制粘贴!按照上述命令,根据自己的实际情况修改,运行之后 docker 会自动拉取mysql:8 的镜像的;其中,/usr/local/share/mysql/data、/usr/local/share/mysql/conf、/usr/local/share/mysql/logs 是我宿主机上的目录,换成你服务器上的目录,可以统一找个地方放

 

3306的端口记得要在安全组放开,或者在防火墙放开;-e MYSQL_ROOT_PASSWORD=123456 是设置 mysql root 用户的密码,123456可以换成你要设置的密码

运行之后还是 docker ps 检查一下 docker 中的容器运行状态,有看到 mysql 就可以啦

配置允许外部访问

进入容器内部

docker exec -it mysql /bin/bash

进入 mysql 数据库

mysql -u root -p

接着会让你输密码,这里输入密码时是没有字符提示的,输完直接回车即可;

设置 mysql 允许外部访问

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

FLUSH PRIVILEGES;

 

创建数据库

 

这里用命令行的形式创建

create database wordpress;

 

查找 mysql 容器的 IP 地址

exit 退出 mysql 容器,使用以下命令获取 mysql 容器的 ip 地址

docker inspect <mysql-container-name> | grep IPAddress

其中 <mysql-container-name> 是 mysql 容器的名称

执行命令后,显示的 172.18.0.4 就是 mysql 容器的 ip 地址

 

WordPress 与 Mysql 建立连接

ftp 打开 wordpress 的挂载目录,找到 wp-config-sample.php,用记事本打开编辑

修改选中的信息

 

修改完成后,回到 wordpress 配置页面,填写配置信息

 

配置提交完成后,无脑安装登录即可。如果显示与数据库建立连接失败,请检查一下,用户名是不是 root ,密码有没有填错,数据库主机是否填的是 mysql 容器的 ip 地址,mysql 中创建的数据库名称是否正确。

 

如果最后进入这个页面了,恭喜你 wordpress 安装成功了!!!

 

能坚持到这一步,真的很厉害了,尽管过程有些繁琐。

 

博客主题更换与上传

如果对目前使用的主题不满意,可以更换主题,外观 - 主题 - 安装主题,可以看到有很多现成可选择的主题

 

如果这些主题都不是很满意,可以选择自己上传主题,我选用的是 Argon,这里贴个下载地址:

Releases · solstice23/argon-theme (github.com)

下载主题的 zip 压缩包,之后点击上传主题即可

但是这时又会出现一个新的问题,wordpress 默认设置了上传文件的大小不能大于 2MB,所以我们只能更改它的配置文件信息,具体如何操作,接着往下看吧

 

解除 WordPress 上传文件大小限制

其实这里可以安装插件解决,但其实治标不治本,因此我们选择直接修改它的 php 配置。

在 WordPress 容器内的 /usr/local/etc/php/conf.d 目录是 php 的相关配置,我们可以新建一个 uploads.ini 配置文件,填写上传文件相关的配置。

 file_uploads = On
 memory_limit = 500M
 upload_max_filesize = 100M
 post_max_size = 100M
 max_execution_time = 600

进入 wordpress 容器,生成我们将要修改的文件

docker exec -it wordpress /bin/bash 进入 wordpress 容器

cd /usr/local/etc/php/conf.d 进入 php 配置文件目录

touch uploads.ini 生成 uploads.ini 文件

最后 ctrl + p ctrl + q 或输入 exit 退出容器返回到主机

查找刚生成的 uploads.ini 文件

注意,上面的那串路径才是我们要的。

复制完整路径后,用 ftp 进入该目录,记事本打开编辑该文件,复制上传配置粘贴到此处,ctrl + s 保存,ctrl + w 关闭即可

 

最后重启一下 wordpress 容器

docker restart wordpress

在 wordpress 后台网页刷新一下,点开这个页面,即可看到上传大小限制已经成功解除了!

 

现在可以重新回到更换主题的地方,上传自己喜欢的主题了~

 

 

接下来在网页地址栏输入 http://服务器公网ip:9999 即可访问博客首页了

但是如果一直用 ip 加 端口号 的形式让别人访问自己的博客,会不太安全,如果我们想要实现域名访问,甚至配置 SSL 实现 https 访问,那就需要利用到 nginx 了

 

利用 Nginx 绑定域名,配置 https

 

Docker 中安装配置 Nginx

 

安装 nginx 镜像

docker pull nginx

以终端的方式打开镜像容器

docker run -i -t nginx /bin/bash

拷贝镜像中 nginx.conf 配置文件的内容

cat /etc/nginx/nginx.conf

↑ 在电脑桌面新建一个记事本,把上述显示的内容拷贝过来,最后重命名为 nginx.conf 备用

 

拷贝镜像中 default.conf 配置文件的内容

cat /etc/nginx/conf.d/default.conf

↑ 同理桌面新建记事本,拷贝内容,重命名为 default.conf 备用

 

nginx.conf
 user  nginx;
 worker_processes  auto;
 ​
 error_log  /var/log/nginx/error.log notice;
 pid        /var/run/nginx.pid;
 ​
 ​
 events {
     worker_connections  1024;
 }
 ​
 ​
 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" "$http_x_forwarded_for"';
 ​
     access_log  /var/log/nginx/access.log  main;
 ​
     sendfile        on;
     #tcp_nopush     on;
 ​
     keepalive_timeout  65;
     client_max_body_size 100m;
     #gzip  on;
 ​
     include /etc/nginx/conf.d/*.conf;
 }

 

default.conf
 server {
     listen       80;
     server_name  localhost;
 ​
     #access_log  /var/log/nginx/host.access.log  main;
 ​
     location / {
         root   /usr/share/nginx/html;
         index  index.html index.htm;
     }
 ​
     #error_page  404              /404.html;
 ​
     # redirect server error pages to the static page /50x.html
     #
     error_page   500 502 503 504  /50x.html;
     location = /50x.html {
         root   /usr/share/nginx/html;
     }
 ​
     # proxy the PHP scripts to Apache listening on 127.0.0.1:80
     #
     #location ~ \.php$ {
     #    proxy_pass   http://127.0.0.1;
     #}
 ​
     # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
     #
     #location ~ \.php$ {
     #    root           html;
     #    fastcgi_pass   127.0.0.1:9000;
     #    fastcgi_index  index.php;
     #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
     #    include        fastcgi_params;
     #}
 ​
     # deny access to .htaccess files, if Apache's document root
     # concurs with nginx's one
     #
     #location ~ /\.ht {
     #    deny  all;
     #}
 }

 

启动运行 nginx 容器

 docker run  --name nginx -d -p 80:80 -p 443:443 -v /usr/local/nginx/https:/usr/local/nginx/https -v /usr/local/nginx/html:/usr/share/nginx/html -v /usr/local/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /usr/local/nginx/conf.d:/etc/nginx/conf.d  -v /usr/local/nginx/logs:/var/log/nginx nginx

 

我在宿主机上的 /usr/lcoal 目录下新建了一个nginx文件夹,上面这五个冒号左边的目录是我宿主机上实际存在的,大家也可以用 ftp 自己找个地方统一存放

 

接着用 ftp 将 conf 文件夹下的 nginx.conf 文件 替换为桌面上新建的,同理也将 conf.d 文件夹下的 default.conf 替换为桌面上新建的。

 

 

域名反代与SSL配置

将域名的SSL证书文件用 ftp 粘贴到宿主机的 https 文件夹下,一般是 .key 文件和 .crt/.pem 的其中一个。

在 conf.d 目录下新建一个 nginx 配置文件,因为我用的域名是 blog.albert-go.top,所以就干脆起名叫 blog.albert-go.top.conf ,然后记事本打开编辑,粘贴下列配置,需要结合自身实际情况进行修改

 # HTTPS server
 ​
 # wordpress
 server {
 listen       443 ssl;
 server_name  blog.albert-go.top; # 你要配置的域名
     
             # 你的 ssl 证书在 nginx 容器中的路径,一般只需要将最后面的换成你的证书文件名称即可
 ssl_certificate     /usr/local/nginx/https/blog.albert-go.top.pem; 
 ssl_certificate_key  /usr/local/nginx/https/blog.albert-go.top.key;
 ​
 ssl_session_timeout 5m;
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
 ssl_prefer_server_ciphers on;
 ​
 # 处理静态资源
 location / {
     proxy_pass  http://47.120.12.180:9999;  # 需要反向代理的地址
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     client_max_body_size 100m;
 }
 ​
 }
 ​
 # wordpress
 server {
 listen 80; # 监听80端口
 server_name  blog.albert-go.top;
 rewrite ^(.*)$ https://$host$1; # 将所有HTTP请求通过rewrite指令重定向到HTTPS。
 ​
 location / {
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://47.120.12.180:9999;
     client_max_body_size 100m; # 这个不能去掉,否则反代后用域名访问wordpress后台,上传文件时会报错
 }
 }

 

配置好后,保存退出,重启 nginx 容器

docker restart nginx

重启后,在网页地址栏输入 https://blog.albert-go.top 就能访问到博客首页了。如果发现还是无法正常访问,或者能访问,但首页的 js 和 css 样式错乱了,无法正常显示,wordpress 后台也无法正常登录,莫慌,接下来的流程将会解决这个问题,因为我都遇到了

 

解决前台样式丢失,后台无法登录,访问陷入重定向死循环

 

强制开启 SSL

找到 wordpress 所在目录,如果 wordpress 容器的启动命令是照搬我的话,目录就是这里 /usr/local/share/wordpress ,修改 wp-config.php,加入以下代码

注意域名要改成自己的

 $_SERVER['HTTPS'] = 'on';
 define('FORCE_SSL_ADMIN', true);
 define('FORCE_SSL_LOGIN', true);
 define('WP_HOME', 'https://blog.albert-go.top');
 define('WP_SITEURL', 'https://blog.albert-go.top');

 

强制跳转 https

找到 wordpress 所在目录,修改 wp-includes 目录下的 functions.php 文件

找到以下代码:

require( ABSPATH . WPINC . '/option.php' );

在其下方添加以下代码

add_filter('script_loader_src', 'agnostic_script_loader_src', 20,2); function agnostic_script_loader_src($src, $handle) { return preg_replace('/^(http|https):/', '', $src); } 
add_filter('style_loader_src', 'agnostic_style_loader_src', 20,2); function agnostic_style_loader_src($src, $handle) { return preg_replace('/^(http|https):/', '', $src); }

 

修改完成后,保存退出,重启 wordpress 容器

docker restart wordpress

 

用数据库管理工具,我这里使用的是 Navicat,有phpstudy的也可以,打开 wordpress 连接的 mysql 数据库,我的数据库名称是 wordpress,连接后,将所有数据表中含有 ip + 端口号 的地址替换为你配置的域名,如 47.120.12.180:9999 替换为 https://blog.albert-go.top

 

最后打开网页,在地址栏输入地址即可正常访问,后台也能登录了

 

完结了,一路配置下来,过程有点繁琐,辛苦啦~

因为基本上都是我在部署 wordpress 的过程中遇到的问题,所以为了解释清楚,可能说得有点啰嗦了...

 

参考资料:

Docker安装wordpress并配置数据库(超详细版)_wordpress docker

docker镜像加速源配置,目前可用镜像源列举(8月29日更新最新可用)_docker可用的镜像源

Docker部署WordPress出现上传的文件大小问题_从服务器收到预料之外的响应。此文件可能已被成功上传。请检查媒体库或刷新本页

WordPress使用nginx反向代理并且开启SSL,导致前台样式丢失,后台无法登录的解决办法 - 神奇码农 (sqmn666.com)

docker部署nginx 并实现反向代理 配置多个域名多个端口_nginx反向代理多个docker容器

docker 安装 wordpress,通过nginx反向代理,绑定域名,配置https - 大数据技术派 (cnblogs.com)