如何搭建一个个人网站-一:实际操作

技术 暂无评论

因为一时兴起,想要自己搭建一个博客,但在动手过程中,遇到了不少问题。于是改为先用AI根据需求出方案,再一步步实施,中间遇到的新问题也都通过AI来解决。最后结合我遇到的困难,在AI辅助下,写成此文。
本篇主要解决把博客真正跑起来,三步走:部署 Typecho → 部署 Caddy → 配 DNS + SSL 上线
注意/xxx代表的是你实际安装的路径,详见上一篇


一、部署 Typecho

1.1 创建目录

mkdir -p /xxx/typecho/{html,data}
  • html:博客程序文件,挂到容器的 /var/www/html
  • data:Typecho 数据,挂到 /app/usr

1.2 编写 docker-compose.yml

/xxx/typecho/docker-compose.yml 写入:

services:
  typecho:
    image: php:8.2-apache
    container_name: typecho
    restart: unless-stopped
    mem_limit: 256m
    mem_reservation: 128m
    ports:
      - "9000:80"                # 搭建阶段临时暴露;Apache 监听 80
    volumes:
      - ./html:/var/www/html
      - ./data:/app/usr
    environment:
      - TZ=Asia/Shanghai
    networks:
      - services-network

networks:
  services-network:
    external: true

几个要点(都是踩过坑后定下来的):

  • 内存限制用 mem_limit / mem_reservation,而不是 deploy.resources——后者在非 Swarm 模式下会静默失效
  • 不写 version 字段,Compose 已废弃它,写了只会多一行警告;
  • 9000:80 只是搭建阶段的临时映射,上线后要注释掉。

1.3 容器内手动安装 Typecho

因为用的是官方 PHP 镜像而非成品 Typecho 镜像,需要进容器手动装:

cd /xxx/typecho
docker compose up -d

docker exec -it typecho bash -c "
apt-get update && apt-get install -y wget unzip sqlite3 libsqlite3-dev && \
docker-php-ext-install pdo_sqlite && \
cd /var/www/html && \
wget https://github.com/typecho/typecho/releases/latest/download/typecho.zip && \
unzip typecho.zip && \
rm typecho.zip && \
chown -R www-data:www-data /var/www/html /app/usr && \
a2enmod rewrite
"

docker restart typecho

这段命令干了五件事:

  1. wgetunzipsqlite3 等工具;
  2. 编译 PHP 的 pdo_sqlite 扩展(Typecho 用 SQLite 存储,必须装它);
  3. 下载并解压 Typecho 到网站根目录;
  4. 把属主改成 www-data(Apache 的运行用户);
  5. 开启 Apache 的 rewrite 模块(Typecho 伪静态依赖它)。

1.4 初始化

初始化有个关键坑:建议不要用 http://IP:9000 提前安装,而是等 Caddy 和域名都配好后,用 https://example.com 进安装向导。因为安装时填的「网站地址」会被写进数据库,如果用 IP 装,之后所有链接都会指向 IP,还得回后台手动改。

如果备案等待期想先验证,用 IP 装也行,但记得之后去后台改网站地址。

安装向导几个配置项:

配置项填什么
数据库适配器Pdo 驱动适配(SQLite)
数据库文件路径保持默认
网站地址https://example.com
管理员用户名 / 密码自行设置
邮箱不需要真实邮箱

二、部署 Caddy

2.1 编写 Caddyfile

mkdir -p /xxx/caddy

cat > /xxx/caddy/Caddyfile << 'EOF'
example.com {
    reverse_proxy typecho:80
}
EOF

重点reverse_proxy typecho:80 里的 typecho 是 Docker 容器名,不是 localhost。因为所有容器都在同一个 services-network 网络里,Docker 会自动做容器名到 IP 的 DNS 解析。而在 Caddy 容器内部,localhost 指向它自己,写 localhost 就会反向代理到自己身上,直接报错。

2.2 编写 docker-compose.yml

cat > /xxx/caddy/docker-compose.yml << 'EOF'
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    mem_limit: 128m
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data:/data
    networks:
      - services-network

networks:
  services-network:
    external: true
EOF

两个易错点:

  • 卷挂载区分大小写:Linux 是区分大小写的,./Caddyfile./caddyfile 是两个不同的文件,拼错会导致挂载失败;
  • 不要挂载 ./config:/config:Caddy 的自动保存功能可能用一份空白配置覆盖你的 Caddyfile。

2.3 启动 Caddy

cd /xxx/caddy

docker start typecho        # 确保 Typecho 已启动

ufw allow 80/tcp
ufw allow 443/tcp

docker compose up -d
docker compose logs -f      # 看到 "serving initial configuration" 即成功

三、DNS + SSL 上线

3.1 添加 DNS A 记录

到域名注册商后台,添加一条 A 记录把域名指向服务器:

类型主机记录记录值
A@服务器公网 IP

这一步放在备案通过之后做(第一篇 3.3 有提)。

3.2 Caddy 自动申请证书

DNS 解析生效后,Caddy 会在第一次收到 HTTPS 请求时自动向 Let's Encrypt 申请证书,全程零配置。你只需要:

  1. 确认 80 和 443 端口在服务器防火墙和云安全组都已放行;
  2. 确认域名已解析到服务器 IP(nslookup example.com);
  3. 浏览器直接访问 https://example.com

第一次访问会稍慢(Caddy 正在申请证书),看到 HTTPS 小锁后就成功了。之后证书到期 Caddy 会自动续期,无需人工干预。

如果一直卡在「不安全」或申请失败,多半是这两个原因:

  • 80 端口没开——Let's Encrypt 的 HTTP-01 验证需要走 80 端口;
  • 域名还没解析生效——确认 A 记录已添加、且 nslookup 已返回正确 IP。

3.3 验证

浏览器访问 https://example.com,看到 Typecho 页面 + HTTPS 小锁,就算正式上线。

到这里博客已经能通过域名访问了。但还差两件事:公安备案 + 备案号展示,以及日常运维下一篇讲。

暂无评论

发表评论