Docker部署流程实践笔记
分类:全栈框架
发布于:
阅读时间:47 分钟
Docker 自动化部署流程实践笔记
本文档记录了基于 GitHub Actions + 阿里云 ACR + 服务器部署的完整自动化部署流程实践。
📋 目录
🏗️ 架构概览
graph LR
A[开发者推送代码] --> B[创建 Release]
B --> C[GitHub Actions 触发]
C --> D[构建 Docker 镜像]
D --> E[推送到阿里云 ACR]
E --> F[传输配置文件到服务器]
F --> G[服务器拉取镜像]
G --> H[启动容器服务]
H --> I[部署完成]
技术栈
- CI/CD: GitHub Actions
- 容器化: Docker + Docker Compose
- 镜像仓库: 阿里云容器镜像服务 (ACR)
- 反向代理: Caddy
- 服务器: Linux (支持 Docker)
- 项目构建: Bun + Node.js
🔧 前置准备
1. GitHub Secrets 配置
在 GitHub 仓库的 Settings > Secrets and variables > Actions 中配置以下密钥:
阿里云容器镜像服务
ALIYUN_REGISTRY_USERNAME = 你的阿里云账号
ALIYUN_REGISTRY_PASSWORD = 你的阿里云密码
服务器访问配置
SERVER_HOST = 服务器IP地址
SERVER_USER = 服务器用户名
SERVER_KEY = SSH私钥内容
2. 服务器环境准备
安装 Docker 和 Docker Compose
# 安装 Docker
curl -fsSL https://get.docker.com | sh
sudo systemctl start docker
sudo systemctl enable docker
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
创建项目目录
sudo mkdir -p /1/MechanicEndWorld2
sudo chown $USER:$USER /1/MechanicEndWorld2
创建 Caddy 数据目录
mkdir -p /1/MechanicEndWorld2/caddy_data
mkdir -p /1/MechanicEndWorld2/caddy_config
🚀 GitHub Actions 工作流配置
项目包含四个主要的工作流文件:
1. build-image.yml - 镜像构建
触发条件:
- 手动触发 (
workflow_dispatch) - 被其他工作流调用 (
workflow_call)
主要步骤:
- 检出代码
- 登录阿里云 ACR
- 生成 Docker 标签
- 构建并推送镜像
- 提取版本标签
关键配置:
env:
REGISTRY: registry.cn-chengdu.aliyuncs.com
IMAGE_NAME: docker-tzd/mechanicendworld
2. transfer-files.yml - 文件传输
功能: 将部署配置文件传输到服务器
传输的文件:
.container/prod/*- 生产环境配置.env- 环境变量文件
验证机制:
- 检查必要文件是否存在
- 验证服务器端文件结构
3. deploy-service.yml - 服务部署
支持的操作:
deploy: 部署新版本restart: 重启服务stop: 停止服务status: 查看状态
部署流程:
- 停止现有服务
- 拉取最新镜像
- 启动新容器
- 健康检查
- 清理旧镜像
4. deploy-pipeline.yml - 完整管道
触发条件:
- 手动触发(支持参数配置)
- 创建 Release 时自动触发
流程阶段:
- 构建镜像 (可跳过)
- 传输文件
- 部署服务 (可跳过)
- 生成摘要报告
🐳 Docker 镜像构建
Dockerfile 结构
# 多阶段构建
FROM oven/bun:1.2.20-alpine AS build
WORKDIR /app
COPY . .
RUN bun install
RUN bun run build:exe:prod
# 运行时镜像
FROM oven/bun:1.2.20-alpine
WORKDIR /app
COPY --from=build /app/dist.exe ./dist.exe
COPY --from=build /app/.container/prod/* ./.container/prod/
COPY --from=build /app/.env* ./
COPY --from=build /app/public ./public
ENV NODE_ENV=production
CMD ["./dist.exe"]
EXPOSE $APP_PORT
构建特性
- 多阶段构建: 减少最终镜像大小
- 预编译二进制: 使用
dist.exe提高启动速度 - 环境隔离: 分离构建和运行环境
- 健康检查: 内置服务健康监控
镜像标签策略
latest: 最新版本v1.0.0: 基于版本号的语义化标签main: 基于分支名pr-2: 基于拉取请求
☁️ 阿里云容器镜像服务配置
镜像仓库地址
registry.cn-chengdu.aliyuncs.com/docker-tzd/mechanicendworld
登录命令
docker login registry.cn-chengdu.aliyuncs.com \
--username=你的阿里云账号 \
--password=你的阿里云密码
镜像拉取
docker pull registry.cn-chengdu.aliyuncs.com/docker-tzd/mechanicendworld:latest
🖥️ 服务器部署配置
docker-compose.prod.yml 配置
应用服务配置
services:
app:
image: registry.cn-chengdu.aliyuncs.com/docker-tzd/mechanicendworld:${IMAGE_TAG:-latest}
container_name: MechanicEndWorld-end
pull_policy: always # 强制拉取最新镜像
ports:
- "${APP_PORT}:${APP_PORT}"
env_file:
- .env.production
- ../../.env
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:${APP_PORT} || exit 1"]
interval: 10s
timeout: 3s
retries: 3
restart: unless-stopped
Caddy 反向代理配置
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
- "9010:9010" # 前端静态资源
- "9011:9011" # 远程资源
volumes:
- ../../front:/1/MechanicEndWorld2/front
- ../../remote:/1/MechanicEndWorld2/remote
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
Caddy 配置文件
主域名反向代理
wx.cykycyky.top {
reverse_proxy app:{env.APP_PORT} {
health_uri /
health_interval 30s
}
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
}
静态资源服务
:9010 {
root * /1/MechanicEndWorld2/front
header /assets/* {
Cache-Control "public, max-age=31536000, immutable"
}
encode {
gzip
zstd
}
file_server
try_files {path} /index.html
}
🔄 部署流程详解
自动部署流程
-
触发阶段
- 创建 GitHub Release
- 或手动触发工作流
-
构建阶段
# GitHub Actions 执行 - 检出代码 - 登录阿里云 ACR - 构建 Docker 镜像 - 推送镜像到仓库 -
传输阶段
# 传输配置文件 scp .container/prod/* server:/1/MechanicEndWorld2/ scp .env server:/1/MechanicEndWorld2/ -
部署阶段
# 服务器执行 cd /1/MechanicEndWorld2/.container/prod docker-compose -f docker-compose.prod.yml down docker-compose -f docker-compose.prod.yml pull docker-compose -f docker-compose.prod.yml up -d docker image prune -f
手动部署命令
# 完整部署
cd /1/MechanicEndWorld2/.container/prod
docker-compose -f docker-compose.prod.yml up -d
# 重启服务
docker-compose -f docker-compose.prod.yml restart
# 查看状态
docker-compose -f docker-compose.prod.yml ps
docker-compose -f docker-compose.prod.yml logs --tail 20
📊 监控与维护
健康检查
应用服务内置健康检查:
wget -q --spider http://localhost:${APP_PORT} || exit 1
日志查看
# 查看容器日志
docker-compose -f docker-compose.prod.yml logs --tail 100
# 实时日志
docker-compose -f docker-compose.prod.yml logs -f
# 查看特定服务日志
docker-compose -f docker-compose.prod.yml logs app
docker-compose -f docker-compose.prod.yml logs caddy
性能监控
# 查看容器资源使用
docker stats
# 查看磁盘使用
docker system df
# 清理未使用资源
docker system prune -f
🔧 故障排除
常见问题
1. 镜像拉取失败
# 检查网络连接
ping registry.cn-chengdu.aliyuncs.com
# 重新登录 Docker
docker login registry.cn-chengdu.aliyuncs.com
# 检查镜像标签
docker pull registry.cn-chengdu.aliyuncs.com/docker-tzd/mechanicendworld:latest
2. 容器启动失败
# 查看容器状态
docker ps -a
# 查看容器日志
docker logs 容器ID
# 检查配置文件
cat .container/prod/.env.production
cat .env
3. 网络连接问题
# 检查端口占用
netstat -tlnp | grep :9003
# 检查防火墙
sudo ufw status
sudo iptables -L
# 检查 Docker 网络
docker network ls
docker network inspect 1panel-network
4. 权限问题
# 检查文件权限
ls -la /1/MechanicEndWorld2/
# 修复权限
sudo chown -R $USER:$USER /1/MechanicEndWorld2/
调试步骤
-
检查 GitHub Actions 日志
- 访问 GitHub 仓库的 Actions 页面
- 查看具体工作流的执行日志
- 定位失败步骤
-
验证服务器配置
# 检查 Docker 服务 sudo systemctl status docker # 检查 Docker Compose 版本 docker-compose version # 检查磁盘空间 df -h -
网络连通性测试
# 测试阿里云 ACR 连接 curl -I https://registry.cn-chengdu.aliyuncs.com/v2/ # 测试应用健康检查 curl -I http://localhost:9003 -
回滚操作
# 使用上一版本镜像 export IMAGE_TAG=上一版本标签 docker-compose -f docker-compose.prod.yml up -d
📝 最佳实践
1. 安全配置
- 使用 SSH 密钥而非密码认证
- 定期轮换访问密钥
- 限制网络访问权限
2. 版本管理
- 使用语义化版本号
- 保留关键版本的镜像标签
- 定期清理旧版本镜像
3. 监控告警
- 设置容器健康检查
- 配置日志收集
- 建立告警机制
4. 备份策略
- 定期备份数据卷
- 备份配置文件
- 建立灾难恢复计划
🎚️ 环境变量配置
.env.production 示例
NODE_ENV=production
APP_PORT=9003
# 数据库配置
DATABASE_URL=postgresql://user:password@host:port/database
# 其他应用配置
.env 示例
# 共享环境变量
COMPOSE_PROJECT_NAME=mechanicendworld
📚 参考资源
维护者: [@your-username] 更新时间: 2025-01-14 版本: v1.0
[#docker-compose.local.yml](/tags/docker-compose.local.yml)
services:
app:
image: mechanicendworld:latest # 使用本地构建的镜像
container_name: MechanicEndWorld-local
ports:
- "9003:9003" # 直接映射端口
env_file:
- .container/prod/.env.production
- .env
environment:
- NODE_ENV=production
- APP_PORT=9003
healthcheck:
test: [ "CMD-SHELL", "wget -q --spider http://localhost:9003 || exit 1" ]
interval: 10s
timeout: 3s
retries: 3
command: [ "./dist.exe" ] # 启动编译后的 dist.exe 文件
restart: unless-stopped
networks:
- local-network
# 可选:如果需要数据库,可以添加 PostgreSQL 服务
# postgres:
# image: postgres:15-alpine
# container_name: postgres-local
# environment:
# POSTGRES_DB: MechanicEndWorld
# POSTGRES_USER: app_user
# POSTGRES_PASSWORD: app_pass
# ports:
# - "5432:5432"
# volumes:
# - postgres_data:/var/lib/postgresql/data
# networks:
# - local-network
networks:
local-network:
driver: bridge
# volumes:
# postgres_data:
# driver: local