概述

本文档记录了 Digital Garden 项目首次部署到生产服务器时遇到的所有问题及解决方案,用于后续部署参考和问题预防。

环境信息

  • 本地环境: Windows 11
  • 服务器: Ubuntu (腾讯云国内服务器 $SERVER_IP)
  • 部署工具: PowerShell 脚本 (deploy/scripts/deploy.ps1)
  • 容器化: Docker + Docker Compose v2

问题清单

1. SSH 连接测试误报错误

问题现象:

[ERROR] SSH connection failed: Warning: Permanently added '$SERVER_IP' (ED25519) to the list of known hosts.

根本原因:

  • PowerShell 脚本设置了 $ErrorActionPreference = 'Stop' 严格错误处理
  • SSH 首次连接时将主机添加到 known_hosts 会输出警告到 stderr
  • 脚本将 stderr 重定向到 stdout (2>&1),导致警告信息被当作错误

解决方案:

# 在 SSH 测试部分临时禁用严格错误处理
$previousErrorAction = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
 
$testResult = ssh -o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=accept-new "${serverUser}@${serverHost}" "echo 'Connection successful'" 2>&1
$sshExitCode = $LASTEXITCODE
 
$ErrorActionPreference = $previousErrorAction

关键修改:

  • 添加 -o StrictHostKeyChecking=accept-new 自动接受新主机
  • 临时修改 ErrorActionPreference 为 Continue
  • 使用 $LASTEXITCODE 而不是捕获异常来判断成功与否

2. Git 无法通过 HTTPS 访问 GitHub

问题现象:

fatal: could not read Username for 'https://github.com': No such device or address

根本原因:

  • 服务器上 git remote 使用 HTTPS URL
  • 非交互式 SSH 会话中无法输入 GitHub 用户名密码
  • 国内服务器访问 GitHub HTTPS 不稳定

解决方案:

  1. 在服务器上生成 SSH 密钥:
ssh root@$SERVER_IP "ssh-keygen -t ed25519 -C 'digital-garden-server' -f ~/.ssh/id_ed25519 -N ''"
  1. 获取公钥并添加到 GitHub:
ssh root@$SERVER_IP "cat ~/.ssh/id_ed25519.pub"
# 在 GitHub Settings > SSH and GPG keys 中添加
  1. 更改 git remote 为 SSH URL:
ssh root@$SERVER_IP "cd /root/digital-garden && git remote set-url origin git@github.com:HubertBiyo/digital-garden.git"
  1. 测试连接:
ssh root@$SERVER_IP "ssh -T git@github.com"
# 应看到: Hi username! You've successfully authenticated

3. Docker Compose 命令版本不兼容

问题现象:

docker-compose: command not found

根本原因:

  • 服务器安装的是 Docker Compose v2 (v2.40.0)
  • v2 作为 Docker 插件运行,命令格式是 docker compose (空格)
  • 脚本使用的是 v1 命令格式 docker-compose (连字符)

解决方案:

全局替换脚本中所有 docker-composedocker compose:

# 部署脚本
docker compose down || true
docker compose up -d --build
 
# 本地部署
docker compose up -d --build
 
# 查看日志
docker compose logs -f
 
# 查看状态
docker compose ps
 
# 停止服务
docker compose down
 
# 重启服务
docker compose restart

检查服务器 Docker Compose 版本:

docker compose version
# 输出: Docker Compose version v2.40.0

4. Docker Hub 镜像拉取超时

问题现象:

failed to do request: Head "https://registry-1.docker.io/v2/library/nginx/manifests/alpine": dial tcp 108.160.167.156:443: i/o timeout

根本原因:

  • 国内服务器访问 Docker Hub 官方源速度慢或超时
  • 之前配置的中科大镜像源已失效

解决方案:

配置可用的 Docker 镜像源:

cat > /etc/docker/daemon.json << EOF
{
  "registry-mirrors": [
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io"
  ]
}
EOF
 
systemctl restart docker

验证配置:

docker info | grep -A 5 "Registry Mirrors"

可用镜像源列表 (2026-01):

5. Alpine Linux BusyBox 环境不兼容

问题现象:

/usr/bin/env: unrecognized option: S
BusyBox v1.37.0 (2025-12-16 14:19:28 UTC) multi-call binary.

根本原因:

  • Quartz 构建脚本使用 #!/usr/bin/env -S node shebang
  • Alpine Linux 的 BusyBox 版本的 env 命令不支持 -S 选项
  • 需要完整版 GNU coreutils 支持

解决方案:

在 Dockerfile 构建阶段安装 coreutils:

# Build Stage
FROM node:22-alpine AS builder
 
# Install coreutils for env -S support
RUN apk add --no-cache coreutils
 
WORKDIR /app
# ... 其余构建步骤

为什么只在构建阶段安装:

  • 只有构建阶段需要运行 quartz 命令
  • 最终运行阶段使用 nginx:alpine 不需要 coreutils
  • 保持最终镜像体积最小化

6. 服务器上的文件冲突

问题现象:

error: Your local changes to the following files would be overwritten by merge:
    deploy/scripts/deploy.ps1
Please commit your changes or stash them before you merge.

根本原因:

  • 服务器上之前的部署尝试留下了修改的文件
  • Git pull 时检测到本地修改无法合并

解决方案:

# 强制重置到远程分支状态
ssh root@$SERVER_IP "cd /root/digital-garden && git reset --hard origin/main && git clean -fd"

预防措施:

  • 服务器上的代码仓库应视为只读
  • 所有修改应在本地完成后推送
  • 定期检查服务器仓库状态

7. 缺少 Nginx 反向代理配置

问题现象:

访问 https://notes.biyo.site 无法访问
域名没有配置 SSL 证书

根本原因:

  • 服务器运行系统级 Nginx 管理所有域名反向代理
  • 仅部署 Docker 容器不足以让域名可访问
  • 需要为新域名创建 Nginx 站点配置文件
  • 需要申请和配置 Let’s Encrypt SSL 证书

解决方案:

  1. 创建 Nginx 配置文件:
cat > /etc/nginx/sites-available/notes.biyo.site << 'EOF'
server {
    listen 80;
    server_name notes.biyo.site;
 
    location / {
        proxy_pass http://127.0.0.1:8084;
        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;
    }
}
EOF
  1. 启用站点配置:
ln -sf /etc/nginx/sites-available/notes.biyo.site /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
  1. 申请 SSL 证书:
certbot --nginx -d notes.biyo.site --non-interactive --agree-tos --email hubertbiyo@gmail.com

关键配置:

  • Certbot 自动配置 HTTPS 和 HTTP 到 HTTPS 的重定向
  • 证书自动续期(通过 cron 任务)
  • 包含安全的 SSL 配置(TLS 1.2+, 强加密套件)

8. Docker 端口冲突

问题现象:

访问 notes.biyo.site 重定向到 vault.biyo.site 内容
网站显示错误的项目内容

根本原因:

  • digital-garden 容器使用 8080 端口
  • vault.biyo.site 也配置反向代理到 127.0.0.1:8080
  • 两个域名指向同一个端口,导致内容混淆

端口占用情况:

8081 - couple-insight-api
8082 - devflow-backend-prod
8083 - baby-log-api
8080 - vault.biyo.site (冲突!)

解决方案:

  1. 修改 docker-compose.yml 端口:
services:
  app:
    build: .
    container_name: digital-garden
    ports:
      - "8084:80"  # 改为未使用的端口
    restart: always
  1. 提交并重新部署:
git add docker-compose.yml
git commit -m "fix: change port to 8084 to avoid conflict"
git push
ssh root@$SERVER_IP "cd /root/digital-garden && git pull && docker compose down && docker compose up -d"
  1. 更新 Nginx 配置中的端口:
proxy_pass http://127.0.0.1:8084;  # 更新为新端口

端口管理建议:

  • 维护端口分配表,记录每个端口的用途
  • 部署前检查端口是否被占用: netstat -tulpn | grep :PORT
  • 使用统一的端口范围(如 Web 应用 8080-8089)

最终端口分配:

# Web 应用
8081 - couple-insight-api
8082 - devflow-backend-prod
8083 - baby-log-api
8084 - digital-garden
 
# MinIO 对象存储
9002, 9003 - devflow-minio
9004, 9005 - baby-log-minio
 
# 数据库
5433 - couple-insight-db

完整部署检查清单

首次部署前置条件

  • SSH 密钥配置

    • 本地配置了服务器 SSH 密钥(免密登录)
    • 服务器生成了 GitHub SSH 密钥
    • GitHub 账户添加了服务器的公钥
  • 服务器环境检查

    • Docker 已安装并运行
    • Docker Compose v2 已安装
    • Git 已安装
    • 防火墙已开放必要端口
  • Docker 配置

    • 已配置可用的镜像源(国内服务器)
    • Docker daemon 正常运行
  • Git 仓库配置

    • 服务器上已克隆仓库
    • Remote URL 配置为 SSH 格式
    • SSH 连接 GitHub 测试成功

部署脚本配置

  • server-config.txt 配置
ServerHost=your.server.ip
ServerUser=root
ServerPath=/root/digital-garden
  • 部署脚本修改项
    • SSH 连接测试已修复(临时禁用严格错误处理)
    • 所有 docker-compose 命令已更新为 docker compose
    • SSH 脚本 CRLF 行结束符已处理

Dockerfile 优化

  • Alpine 兼容性
    • 已安装 coreutils(支持 env -S)
    • 多阶段构建优化镜像大小
    • 构建缓存层次合理

端口配置

  • 端口分配检查
    • 检查端口是否被占用: netstat -tulpn | grep :PORT
    • 选择未使用的端口(参考端口分配表)
    • 更新 docker-compose.yml 中的端口映射

Nginx 和 HTTPS 配置

  • Nginx 反向代理

    • 创建站点配置文件: /etc/nginx/sites-available/domain.com
    • 启用站点: ln -sf /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/
    • 测试配置: nginx -t
    • 重新加载: systemctl reload nginx
  • SSL 证书配置

    • 使用 Certbot 申请证书
    • 验证 HTTPS 访问
    • 确认 HTTP 自动重定向到 HTTPS
    • 测试证书续期: certbot renew --dry-run

部署后验证

  • 容器状态检查
docker ps | grep digital-garden
docker compose logs -f

最佳实践建议

1. 部署脚本设计

错误处理:

  • 使用 $ErrorActionPreference = 'Continue' 处理可能产生 stderr 但成功的命令
  • 使用 $LASTEXITCODE 判断命令是否真正失败
  • 区分致命错误和警告信息

SSH 命令执行:

# 清理 CRLF 行结束符
$sshScript = $sshScript -replace "`r`n", "`n"
$sshScript = $sshScript -replace "`r", "`n"

命令版本兼容:

  • 优先使用新版本命令(docker compose v2)
  • 添加版本检查和提示

2. Docker 配置

国内服务器镜像源:

{
  "registry-mirrors": [
    "https://dockerproxy.com",
    "https://docker.m.daocloud.io"
  ]
}

多阶段构建:

  • 构建阶段安装所有必要工具
  • 运行阶段只包含运行时依赖
  • 最小化最终镜像体积

3. Git 配置

服务器端 Git 配置:

  • 使用 SSH 而非 HTTPS 访问 GitHub
  • 配置 SSH 密钥而非个人访问令牌
  • 服务器仓库保持只读,不在服务器上修改代码

4. 日常部署流程

# 1. 本地开发和测试
# 2. 提交代码到 Git
git add .
git commit -m "描述性提交信息"
git push
 
# 3. 执行部署脚本
powershell -ExecutionPolicy Bypass -File .\deploy\scripts\deploy.ps1 -Action app
 
# 4. 验证部署
# - 检查容器状态
# - 访问网站
# - 查看日志(如有问题)

5. 故障排查

查看容器日志:

powershell -ExecutionPolicy Bypass -File .\deploy\scripts\deploy.ps1 -Action logs

查看容器状态:

powershell -ExecutionPolicy Bypass -File .\deploy\scripts\deploy.ps1 -Action status

SSH 到服务器手动检查:

ssh root@121.4.26.74
cd /root/digital-garden
docker compose ps
docker compose logs digital-garden

常见问题快速参考

问题快速检查命令解决方案
SSH 连接失败ssh root@121.4.26.74检查 SSH 密钥配置和网络
Git pull 失败ssh root@121.4.26.74 "ssh -T git@github.com"检查 GitHub SSH 密钥配置
Docker 镜像拉取超时docker info | grep "Registry Mirrors"配置国内镜像源
容器无法启动docker compose logs检查构建错误和运行时错误
网站无法访问docker ps检查容器状态和端口映射

相关资源

更新记录

  • 2026-01-02 (晚): 添加问题 7 和 8(Nginx HTTPS 配置和端口冲突),完善部署检查清单
  • 2026-01-02 (早): 首次部署问题总结,包含 6 个主要问题及解决方案