网上关于用自己的 VPS 搭博客的教程非常多,但是多半是一些非常陈旧和杂乱的实践。

作为一个折腾博客五年多的「折腾达人」,本文汇总自己多年的折腾经验,形成一个我认为的「最佳实践」,希望能够作为参考。同时为了简化过程,这篇博客介绍的并不完全是我服务器上的部署方式,更加优化的一些地方在文末有列举。

💡 这篇博客介绍的「最佳实践」的含义为「已经在别处产生显著效果并且能够适用于此处的优秀实践」,而不是「最优秀的实践」,并无「最」字面上「达到极点」的含义。无意否认存在比这篇博客的介绍更加简便、清晰、强大、优秀的实践。

前置知识

部署环境架构的选择

如果用自己的 VPS 搭建博客,部署环境有几种常见的方式:

容器化是近年的趋势,也是这篇博客介绍的方法。

博客系统的选择

目前开源的博客系统五花八门,我也尝试过很多。从整体的架构上可以分为三类:

我个人比较推荐的是 WordPress 或者 Typecho。

WordPress

WordPress 是一个十分成熟的 PHP 博客程序。据统计,整个互联网约有三分之一的网站使用 WordPress。

新版本的 WordPress 内置的是 Gutenberg 编辑器,这是一个强大的“块编辑器”(区别于传统的文字编辑器)。这个编辑器比较现代化,对用户友好,但是实现比较复杂。如果你习惯使用 Markdown 来写文章,或者想要对博客系统进行一些二次开发,可能会比较麻烦,更推荐使用 Typecho。

💡 注意:开源的 WordPress 博客程序项目的官网是 wordpress.org,而不是 wordpress.com!后者是 WordPress 的公司 Automatic 运营的线上博客服务,和前者没有直接关系。

Typecho

Typecho 是国人开发的 PHP 博客系统,非常简洁轻量,比 WordPress 更加轻量。Typecho 隔几年才更新一次,已经有十五年以上的历史了……我的这个博客就是用 Typecho 搭建的。

Typecho 原生支持 Markdown,而且主题、插件的开发都比 WordPress 要容易地多。不过对于对 Markdown 不熟悉的用户来说,这个编辑器比 WordPress「简陋」地多。

总结一句,WordPress 强大全面,Typecho 轻量简洁,看个人喜好选择。

这篇博客以 Typecho 为例。

安装 Docker 和 Compose

Docker 是最常用的容器平台。

首先我们要在服务器上安装 Docker(注意是安装 Docker Engine 不是 Docker Desktop),然后安装 Docker Compose。可以参考官方的安装文档

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

Docker Compose 的安装文档在这里

架构规划

我们需要运行以下几个容器:

还需要安装 Caddy(或 Nginx),作为 Web Server。这个相当于作为整个服务器的「网关」,可以不以容器的方式安装(因为 Caddy 的 caddy reload 命令真的很爽)。

创建容器网络

为了让 Typecho 容器能够访问数据库,phpMyAdmin 能够管理数据库,我们要分别为他们创建网络,和数据库互联。假定这两个网络名为 blogdb_admin

容器网络

我们可以先创建网络,稍后在相关的 docker-compose.yml 中指定连接:

docker network create blog
docker network create db_admin

安装启动数据库

Typecho 支持 MySQL 数据库。此处我们选用 MariaDB。

💡 关于 MariaDB 与 MySQL:MariaDB 是 MySQL 关系数据库管理系统的一个 Fork,由社区开发,有商业支持,旨在继续保持在 GNU GPL 下开源。MariaDB 打算保持与 MySQL 的高度兼容性,确保具有库二进制奇偶校验的直接替换功能,以及与 MySQL API 和命令的精确匹配。感觉二者的关系如同 Rocky Linux 与 CentOS。我个人比较推荐使用前者。

为了维护的方便,这篇博客介绍的容器运行均使用 Docker Compose。运行数据库的 docker-compose.yml 如下:

version: "3"

services:
  mariadb:
    image: mariadb:latest
    container_name: mariadb
    networks:
      - blog
      - db_admin
    environment:
      - MARIADB_ROOT_PASSWORD=NhwaJU0tW7UZ5u
    volumes:
      - /data/mysql:/var/lib/mysql
    restart: unless-stopped

networks:
  blog:
    external: true
  db_admin:
    external: true

将文件命名为 docker-compose.yml,放到一个单独的文件夹内。在这个文件夹内运行:

docker-compose up -d

Docker Compose 会自动 pull 最新的 MariaDB 镜像并在后台启动容器(-d 就是使容器后台运行)。使用命令 docker ps -a 查看所有容器,可以查看到该容器正在运行。

Docker 启动了 mariadb 容器

💡 Docker 镜像的来源:所有 Docker 镜像都可以在 Dockerhub 上找到,docker pull 的默认来源也是 Dockerhub。

💡 运行 docker-compose down停止并删除容器。所以我们需要「容器无状态」,将带有状态的数据都可持久化存储,挂载到外部。

用 phpMyAdmin 管理数据库

💡 可以直接用 SQL:如果你比较熟悉 SQL,可以直接用 docker exec -it mariadb /bin/sh 进入容器内部,用 SQL 操作数据库。phpMyAdmin 本质上只是封装了各种 SQL 语句的一个 Web 界面。

为了方便管理我们的数据库,我们再运行一个 phpMyAdmin 容器。同样写一个 docker-compose.yml

version: "3"

services:
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    container_name: phpmyadmin
    environment:
      - PMA_HOST=mariadb
    networks:
      - db_admin
    ports:
      - "8080:80"
    restart: unless-stopped

networks:
  db_admin:
    external: true

在 phpMyAdmin 中,我们需要为 Typecho 创建数据库和用户。点击上面的「账户」,然后点击「新增用户账户」,用户名填写 typecho,密码可以随机设置一个,并勾选「创建与用户同名的数据库并授予所有权限」。其他部分保持默认即可。

phpMyAdmin 创建用户和数据库

点击「执行」,我们就为 Typecho 创建了用户和数据库。

💡 为什么不使用 root 用户?root 用户拥有最高权限,任何时候使用 root 用户都是非常危险的。而我们创建的 typecho 用户则只有操作 typecho 这一个数据库的权限。

安装 Typecho(FPM)容器

💡 关于 typecho 与 typecho-fpm: 在 Dockerhub 上可以看到 Typecho 镜像有多个 tags:typechotypecho-apache(同 typecho)和 typecho-fpmtypecho 镜像中自带了一个 Apache,启动容器后可以直接访问;而 typecho-fpm 只有 php 环境,并不带 Web 服务器,需要自己配置一个支持 php-fpm 的服务器提供访问。
为了使用 HTTPS,我们必须在外部配置一个 Web 服务器,所以如果使用前者,流量会经过两个 Web 服务器而拖慢速度。更推荐使用后者。WordPress 和 WordPress-fpm 镜像同理。原理图如下:

Typecho FPM 原理示意

用以下 docker-compose.yml 文件启动 Typecho-fpm 容器:

version: "3"

services:
  typecho:
    image: joyqi/typecho:1.2.0-php8.0-fpm
    container_name: typecho
    networks:
      - blog
    volumes:
      - "/data/typecho:/app"
    ports:
      - "9000:9000"
    restart: unless-stopped
    depends_on:
      - "mariadb"

networks:
  blog:
    external: true

安装 Caddy 与配置

为了方便使用,对于 Caddy,我们可以不用容器的安装方式,而是采用官方文档的方法直接安装。

以 Ubuntu / Debian 为例:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

安装之后,我们创建一个名为 Caddyfile 的文件,在其中写如下内容:

example.com {
        root * /data/typecho
        file_server
        php_fastcgi 127.0.0.1:9000 {
                root /app
        }
}

保存 Caddyfile 后,启动 Caddy(service caddy start),在相同目录下 caddy reload。这时访问 example.com 就可以看到 Typecho 的初始化界面了!

Typecho 容器运行成功

Typecho 初始化

Typecho 的初始化界面

数据库地址就是 mariadb 容器名,用户名、数据库名、密码就是刚才在 phpMyAdmin 里创建的。一切就绪后,点击「确认,开始安装」。

然后设置好 Typecho 登录用的账号密码,不出意外,Typecho 博客就搭建完成啦!

下一步

访问 https://你的域名/admin 进入 Typecho 的后台,可以定制主题、插件等等博客的一切。

访问 Typecho 官方文档了解更多信息。

其他可选的优化

在互联网环境逐渐恶化的今天,自己的博客就是一片属于自己的天地。希望我们都能在自己的精神花园里畅所欲言。