概述
本文档记录了 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 不稳定
解决方案:
- 在服务器上生成 SSH 密钥:
ssh root@$SERVER_IP "ssh-keygen -t ed25519 -C 'digital-garden-server' -f ~/.ssh/id_ed25519 -N ''"- 获取公钥并添加到 GitHub:
ssh root@$SERVER_IP "cat ~/.ssh/id_ed25519.pub"
# 在 GitHub Settings > SSH and GPG keys 中添加- 更改 git remote 为 SSH URL:
ssh root@$SERVER_IP "cd /root/digital-garden && git remote set-url origin git@github.com:HubertBiyo/digital-garden.git"- 测试连接:
ssh root@$SERVER_IP "ssh -T git@github.com"
# 应看到: Hi username! You've successfully authenticated3. Docker Compose 命令版本不兼容
问题现象:
docker-compose: command not found
根本原因:
- 服务器安装的是 Docker Compose v2 (v2.40.0)
- v2 作为 Docker 插件运行,命令格式是
docker compose(空格) - 脚本使用的是 v1 命令格式
docker-compose(连字符)
解决方案:
全局替换脚本中所有 docker-compose 为 docker 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.04. 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 nodeshebang - 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 证书
解决方案:
- 创建 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- 启用站点配置:
ln -sf /etc/nginx/sites-available/notes.biyo.site /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx- 申请 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 (冲突!)解决方案:
- 修改 docker-compose.yml 端口:
services:
app:
build: .
container_name: digital-garden
ports:
- "8084:80" # 改为未使用的端口
restart: always- 提交并重新部署:
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"- 更新 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-
服务可访问性
- 本地端口访问: http://serverip:8080
- 域名访问: https://notes.biyo.site
-
日志检查
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 statusSSH 到服务器手动检查:
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 个主要问题及解决方案