30分钟建成一个个人博客

wordpress 是广为人知的内容管理系统，而 docker 可以打包应用以及依赖包到一个轻量级、可移植的容器中，然后发布到任何流行的 Linux 机器上，两者的结合让建站只需要简单的几步配置。

购买实例（服务器）

阿里云、腾讯云、华为云、亚马逊云、谷歌云等等地方都可以购买云服务器，其中谷歌和亚马逊都有试用一年的套餐，而阿里、腾讯、华为的新用户和校园用户也有许多折扣，小伙伴们可以自行挑选合适的套餐购买。

安装 docker 和 docker-compose

这里可以直接在购买服务器的时候选择含有 docker 的镜像，如果没有也可以在控制台中找到更换操作系统（或更换镜像）来换一个带有 docker 的镜像，如果还是没有可以通过以下方法安装：

Copy
# 安装docker
sudo curl -sSL https://get.daocloud.io/docker | sh

# 安装docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

创建持久化目录

docker 容器一旦销毁后，容器内的数据就会丢失，为了避免这种事情的发生，我们一般会通过挂载卷的方式来持久化这些数据：

Copy
# 切换到安装目录
cd ~

# 创建挂载所需的目录
## 创建mysql配置目录
mkdir db
## 创建mysql数据目录
mkdir db_data
## 创建wordpress文件目录
mkdir wordpress_data
## 创建nginx文件目录
mkdir nginx

# 创建必备配置文件
## 创建mysql配置文件
cat > ./db/mysql.cnf << EOF
[mysqld]
explicit_defaults_for_timestamp=true
wait_timeout=86400
interactive_timeout=7200
EOF
## 创建nginx配置文件

### 先启动一个ngninx的镜像
sudo docker run -it -d --name nginx nginx:latest
### 将容器内的/etc/nginx目录拷贝到本地
sudo docker cp nginx:/etc/nginx ./nginx/conf
### 将容器内的/usr/share/nginx/html目录拷贝到本地
sudo docker cp nginx:/usr/share/nginx/html ./nginx/html
### 创建ngnix的日志目录
mkdir ./nginx/log
### 文件拷贝完毕移除ngnix镜像
sudo docker stop nginx
sudo docker rm nginx

配置 docker-compose.yml

Copy
vi docker-compose.yml

文件内容如下

Copy
version: '3'
services:
nginx:
image: nginx:latest
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf:/etc/nginx:ro
- ./nginx/html:/usr/share/nginx/html:rw
- ./nginx/log:/var/log/nginx:rw
- ./nginx/ssl:/etc/ssl:ro

wpdatabase:
image: mysql:latest
volumes:
- ./db_data:/var/lib/mysql
- ./db/mysql.cnf:/etc/my.cnf
restart: always
environment:
MYSQL_ROOT_PASSWORD: root # 数据库管理员密码，推荐改为强密码
MYSQL_DATABASE: wordpress # wordpress数据库
MYSQL_USER: wordpress # wordpress用户
MYSQL_PASSWORD: wordpress # wordpress用户的密码，推荐改为强密码

wordpress:
depends_on:
- wpdatabase
image: wordpress:latest
volumes:
- ./wordpress_data:/var/www/html
restart: always
environment:
WORDPRESS_DB_HOST: wpdatabase:3306
WORDPRESS_DB_USER: wordpress # 上面配置的mysql用户
WORDPRESS_DB_PASSWORD: wordpress # 上面配置的mysql用户的密码

启动容器

Copy
sudo docker-compose up -d

修改 ngnix 配置文件

经过上面的配置，我们可以通过sudo docker ps看到容器已经启动了，但是 nginx 还没配置好代理，所以还无法直接访问到 wordpress 的页面，我们只需要创建一个配置文件即可：

Copy
# 创建nginx配置文件
vi ./nginx/conf/conf.d/wordpress.conf

按i键进入编辑模式，将以下内容更改后粘贴：

Copy
server {
listen 80;
server_name x.x.x.x; # 此处修改为你的主机IP

location / {
proxy_pass http://wordpress;
proxy_redirect off;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 转发host信息
proxy_set_header Host $host;
}
}

按:后输入wq!保存文件即可

重启 nginx 容器并访问网站

Copy
sudo docker-compose restart nginx

此时直接访问服务器 IP 地址即可访问 worepress，如果出现了错误，可以使用tail -f ./nginx/log/error.log查看错误日志

进阶配置

建站一条龙服务

上述的方法只能在服务器上简单部署一个 wordpress 应用，别人可以用公网 IP 去访问你的页面，但这不合规也不安全，一个完整的建站流程还包括域名注册、网站备案、公安备案、DNS 解析、SSL 证书签发等等，以上步骤都可以在云服务厂商获取一条龙服务，其中域名注册是收费的，其他环节都有免费方案，需要注意的是网站备案需要近 20 天左右的审批时间。

SSL 证书配置

在云服务厂商那获取免费的 ssl 证书后上传到服务器，并将.crt 和.key 文件拷贝到./nginx/conf 目录中，并生成将 mozilla 的 pem 文件：

Copy
# 拷贝ssl证书文件
cp /path/to/xxx.crt ./nginx/conf
cp /path/to/xxx.key ./nginx/conf

# 生成mozilla的pem文件
curl https://ssl-config.mozilla.org/ffdhe2048.txt > ./nginx/conf/dhparam.pem

按标记的注释对./nginx/conf/conf.d/wrodpress.conf 进行文件修改：

Copy
# generated 2022-03-24, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1k, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6

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

server_name _;
server_name yangziwen.cn www.yangziwen.cn; # 这里改为自己的域名

location / {
return 301 https://yangziwen.cn$request_uri; # 这里改为自己的域名
}
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yangziwen.cn www.yangziwen.cn; # 这里改为自己的域名

location / {
proxy_pass http://wordpress;

proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}

ssl_certificate xxx.crt; # 这里改为自己的ssl证书
ssl_certificate_key xxx.key; # 这里改为自己的ssl证书密钥
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;

# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
ssl_dhparam dhparam.pem;

# intermediate configuration
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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate xxx.crt; # 这里改为自己的ssl证书

# replace with the IP address of your resolver
resolver 8.8.8.8;

location ~* /xmlrpc.php {
deny all;
}

if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}

if ($request_method !~ ^(GET|PUT|HEAD|POST|OPTIONS)$ ) {
return 444;
}

}

以上的配置模板是由https://ssl-config.mozilla.org/生成的，并进行了一些简单的安全加固，接下来重启 ngnix 即可直接通过 https 访问自己的站点了

Copy
sudo docker-compose restart nginx

此时可以在https://myssl.com/中对自己的站点进行 HTTPS 评级，以上配置的分数为 A+，如果不是可能是因为之前主页上通过 http 引用了图片等资源，改为 https 引用即可

nginx 安全加固

在 ssl 配置中我们已经对 nginx 做了部分加固，还有一些配置需要在./nginx/conf/nginx.conf 中进行配置，将文件进行如下修改，主要是禁止了 http 和直接使用 ip 访问

Copy

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;
#隐藏 Nginx 的版本号，提高安全性。
server_tokens off;
#隐藏 PHP 版本
fastcgi_hide_header X-Powered-By;
proxy_hide_header X-Powered-By;
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;

#gzip on;

include /etc/nginx/conf.d/*.conf;
server {
listen 80 default;
server_name _;
return 444; #防止通过ip访问网站
location ~* \.(rar|zip|gz|tar|tgz|tar.gz|7z|z|bz2|tar.bz2|sql|log|rar|ini|bak|conf|DS_Store|idea|swp|svn|entries|git|config)$ {
deny all;
}
autoindex off;
include vhost/*.conf;
}
}

重启 nginx：

Copy
sudo docker-compose restart nginx

wordpress 安全加固

强烈建议站点建好后立马安装 Wordfence 插件，并开启双因子鉴权（Two-Factor Authentication），我在建好站等备案期间已经通过 Wordfence 插件拦截了许多尝试登录 admin 账号和访问敏感接口的行为

服务器安全加固

一般购买云服务器后厂商会赠送最基本的安全扫描，新建的实例需要及时按照扫描结果将一些敏感软件（如 openssh）更新到最新版本，以免存在漏洞

ssh 是我们登录服务器最常用的方式，也是黑客最爱的入口之一，新建实例后我们应该尽快进行以下两点配置：

新建密钥，并将服务器实例与密钥关联，具体方式可以参考云服务厂商的说明。新建密钥后我们登录实例就不需要再输密码了，只要在 ssh 客户端配置好自己的私钥即可连接实例，唯一需要注意的是要避免私钥的泄露，私钥一旦泄露或丢失需要及时到云服务的用户管理中心去删除原始密钥并创建新的密钥

修改服务器防火墙。进入云服务器的管理页面，修改防火墙，只要保留 80，443，ICMP 端口的访问即可，对于 22 端口如果不嫌麻烦的最好只留需要 ssh 登录的源端 ip 地址即可，不过像使用电信，移动宽带的用户，ip 在一段时间或者重启路由器后会变，此时如果 ssh 连接不上大概率是 ip 地址更新导致的。对于 ip 在一个固定网段的用户，可以通过子网掩码来划定 ip 范围，就是 ip 后面的 / 24，/16，/8 这些

SEO 配置

我们搭建好自己心爱的网站后，肯定希望尽快被志同道合的基友看到，这时 SEO（搜索引擎优化）就起到了很大的帮助。在 wordpress 中我们可以通过一些插件即可方便地配置 SEO，我用的是 Yoast SEO 这款插件，安装好后可以根据插件提示做一些简单配置。

sitemap（站点地图）是 SEO 相当重要的一部分，Yoast 的站点地图是收费功能，我们可以安装 WP Sitemap Page 插件来生成一个简单的站点地图，通过域名/sitemap_index.xml即可访问，这是一个索引文件，点开后会有各种类型的索引，每个索引里面具有对应的 url 链接，这些链接基本涵盖了我们网站所有对外显示的内容。通过将这些 xml 索引推给百度、谷歌、必应的站长工具，就可以让搜索引擎快速收录我们的站点，以下是这些站长工具的地址

谷歌：https://www.google.com/intl/zh-CN/webmasters/

百度：https://ziyuan.baidu.com/site/index

必应：https://www.bing.com/webmasters/about?setlang=zh-cn

配置方法也很简单，首先是站点关联，有各种关联方式，按照说明选一个配置就行。其次每个站长工具中都有站点地图的上传，谷歌和必应在菜单栏中就能看到，百度的在普通收录里面有个 sitemap 上传，只要将 sitemap_index.xml 中所有 xml 的链接提交即可。

提交完站点地图之后，只要等各大搜索引擎去爬取站点地图中的 url 即可，这里不得不夸赞一下谷歌的速度，录完第二天就能在 pc 端搜到自己网站的内容了，而百度，着实让人有点着急。
robots.txt 是一种爬虫协议，他们告诉搜索引擎的爬虫哪些能爬哪些不能爬，一份良好的 robots.txt 能够让爬虫快速发现你想要展示的页面，wordpress 默认有一个 robots.txt 配置了简单的屏蔽 wp-admin 的策略，我们可以为其加上 sitemap 的地址，让爬虫更快地发现 sitemap。首先进入./wordpress_data创建robots.txt文件，添加Sitemap: https://域名/站点地图名.xml, 然后访问https://域名/robots.txt生效即可。

参考链接