几年前就跟老朋友扯淡要开自己的博客,今天终于把这个任务完成了,作为第一篇博客,先来记录一下这个不甚顺利的建站过程吧。
为什么选择 WordPress
随手 Google 一下就可以找到诸多博客框架,如 WordPress,Hexo,Jekyll,Hugo 等,促使我选择 WordPress 的理由主要有:
- 企业更多会选择 WordPress 来构建主页,作为一个要成为 CTO 的男人,我的技术栈都是面向企业而非独立开发者,选择 WordPress (以及后面会提到的 NGINX, Docker 等) 是自然而然的事。
- WordPress 生态最大,未来即使迁移到其他博客框架上也有很多轮子可以用,上面提到的博客框架都有官方提供的迁移工具:Hexo,Jekyll,Hugo。
建站过程
购买云服务
促使我选择 Azure 云服务的理由只有一个:穷!毕竟公司每个月 150 USD 的羊毛不用白不用。个人认为 Azure Portal 还算好用,比 AWS 的 UX 顺滑那么一些…
在 Azure Portal 注册以及绑定 billing 信息后,搜索如下资源进行购买
资源名称 | 价格 | 购买流程 | 文档 |
---|---|---|---|
域名 (frankzhang.net) | 每年 11.99 USD 起 | 搜索 “App Service Domains” 进行购买 | Buy a custom domain name – Azure App Service | Microsoft Docs |
虚拟机 (Azure Ubuntu VM) | B2S (双核 4 GB) 每月 38.544 USD | 搜索 “Virtual Machines” 进行购买 | Quickstart – Create a Linux VM in the Azure portal – Azure Virtual Machines | Microsoft Docs |
数据库 (Azure Database for MySQL servers) | 0 | 想什么呢,云数据库你用得起么?🤣 | MySQL :: A Quick Guide to Using the MySQL APT Repository |
购买好上述服务后,需要将域名绑定到对应虚拟机的 IP 上,在 Azure Portal 上只需打开 VM 对应的 public IP 资源,在其配置中增加一条 alias record (A 记录),如下我添加了 blog.frankzhang.net 指向此 IP

安装 MySQL
如上面表格罗列的,由于我买不起云数据库,只好自行在 Azure VM 中安装 MySQL,参照官方文档,但 Azure Ubuntu VM 似乎已经包含了 MySQL 的 apt repository,所以只需下面两行命令搞定
sudo apt update
sudo apt install mysql-server
由于 MySQL 默认只监听 localhost 的 3306 端口,下面的命令修改其监听任意来源而不仅仅是 localhost。不用担心,云服务的网络设置默认只开放 22 端口,未来我们还会放开 80 和 443 端口,但无论如何 3306 端口是不会被外网所访问到的。这步卡了我很久,由于我的 WordPress 是安装在 Docker 容器内,在后续的安装中显示 “Error establishing a database connection”,从怀疑 MySQL 用户密码错误到怀疑 Azure 内网设置不正确,最后才发现是由于 MySQL “bind_address” 这个默认配置。
echo 'bind-address = 0.0.0.0' | sudo tee -a /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
这里我选择在宿主机上直接安装 MySQL 而非在 Docker 中,是因为在企业中我们都会购买云数据库 (RDS),其架构是远程/内网有一或多台数据库服务器,在宿主机上直接安装 MySQL 模拟了这样的网络架构。(哈哈不吹了,其实是因为这样最简单也更偏向于企业内的用法,没听说过哪家线上 MySQL 是用 Docker image 来启动的。另外最近听朋友说到一个惨案,他习惯使用 docker 删除操作,一不小心把数据 volume 也删了…)
此处省略了创建数据库和用户(给 WordPress 专用)的步骤,请自行脑补。
安装 Docker
都 2021 年了,哪个公司的服务器上还能不安装 Docker 呢?(好吧微软的 Windows 服务器的确不用 Docker…)
继续根据官方文档,一顿操作即可
# Set up repository, can be ignored in cloud ubuntu vm.
sudo apt update
sudo apt install apt-transport-https ca-certificates gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 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
# Install Docker Engine
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
安装 WordPress
官方文档的安装方式需要提前在服务器上安装好 PHP,由于我不清楚 PHP 为什么是世界上最好的语言,抱着敬而远之的态度,我选择使用 Docker 来帮我隔离掉这项我不甚了解的技术,所幸 WordPress Community 维护了 WordPress Docker Images(这就是选择大生态工具的好处),于是事情变得十分简单。
cd /var/www/blog.frankzhang.net
docker pull wordpress
docker run -e WORDPRESS_DB_HOST=<host_ip>:3306 -e WORDPRESS_DB_USER=<username> -e WORDPRESS_DB_PASSWORD=<password> --name wordpress -p 8181:80 -v "$PWD/html":/var/www/html -d wordpress
上述参数的简单解释
- –name,给容器起个名字
- -p,指定端口映射,格式为:宿主机端口:容器端口,后续我会使用 NGINX 来反向代理此宿主机端口。
- -v,映射宿主机一个 volume 到容器内,用这种方式即使 WordPress Docker 容器 / image 被删除,宿主机上的文件仍然存在,Wordpress Docker 容器 /var/www/html 目录内存放 WordPress 的 PHP 代码,主题及配置,图片和视频等多媒体文件等。
- -d,在后台运行容器。
- -e 环境参数皆在 Docker Hub WordPress Image 主页里有详细介绍,这里不再赘述。
至此,咱们的 WordPress 已经可以在内网访问了,通过 curl localhost:8181 应该可以看到返回的 WordPress html 网页了。
安装 NGINX
关于 NGINX 是否应该通过 Docker 容器来运行,暂时我认为是否定的,有以下几个原因
- NGINX 不像应用那样改动 / 升级频繁
- NGINX 本身的安装十分简便 (apt install nginx)
- 我想要使用 Certbot 自动更新 SSL 证书,使用容器不方便做到。
惯例:官方文档,不过这次我是按照这篇教程来的,安装 NGINX 后要记得去 Azure Portal 将网络设置修改一下,允许外网访问 80 和 443 端口,如下

然后可以去写入 NGINX 配置文件了,sudo vi /etc/nginx/sites-available/blog.frankzhang.net 填入如下配置,之后记得在 /etc/nginx/sites-enabled 目录下创建一个到此配置的软链接。
server {
listen 80;
server_name blog.frankzhang.net;
return 301 https://blog.frankzhang.net$request_uri; # 将 HTTP 请求都转至 HTTPS
}
server {
listen 443 ssl http2;
server_name blog.frankzhang.net;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
location / {
proxy_pass http://localhost:8181;
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 https;
}
}
其实上述配置的核心就一句话,将 443 端口的请求转发至 localhost:8181,Docker 来运行 WordPress 真香,否则还要去配置什么我并不大懂的 PHP FastCGI。
最后一步便是安装 SSL 证书了,作为个人用户咱们就省点钱用用免费的 Certbot (Let’s Encrypt) 好了,命令也十分简单,如下
sudo apt install certbot
sudo certbot --nginx
然后按照其指示安装即可,安装成功后如果设置了自动 renew,Certbot 会在 /etc/cron.d 目录下放置一个脚本,每 12 小时尝试更新一次。
初始化 WordPress
第一次访问 https://blog.frankzhang.net,Wordpress 会出现配置页面,根据指示不断的下一步,大功告成!
结语
在整个过程中遇到的几个坑
- MySQL 默认只监听 localhost 3306 端口,通过内网 IP 不可访问。
- 网上很多 WordPress 和 NGINX 的教程,基本都会跟你讲 FastCGI 在 NGINX 内的相关配置,把我搞得晕头转向。其实由于咱们使用了 WordPress 默认的 Docker image,内部已经用 Apache server 来 host PHP 提供 HTTP 服务了,所以只需要无脑转发 HTTP 请求即可。