基于 Docker + Watchtower 自动化部署后端服务
本文提供一套生产级通用后端服务自动化部署方案,基于 Docker Compose 编排 + Watchtower 自动更新机制,适用于所有已容器化的后端应用(Java/Go/Python/Node.js 等)。实现 "一次配置,终身自动更新",彻底解决手动部署、版本更新、容器重启等繁琐运维问题。
前置条件
在开始部署前,请确保你的服务器已满足以下通用要求:
- 服务器已安装 Docker 20.10+ 和 Docker Compose V2+ (推荐使用官方一键安装脚本)
- 你的后端代码已打包为Docker 镜像 ,并推送到任意镜像仓库(Docker Hub/GitHub GHCR / 阿里云 ACR / 腾讯云 TCR 等)
- 服务器可正常访问你的镜像仓库(私有仓库需提前获取访问凭证)
- 服务器已开放后端服务所需的端口(如 8080、3000 等)
部署步骤
步骤 1:创建项目目录结构
在服务器上创建标准化的项目目录,用于存放配置文件、日志、静态资源等持久化数据:
bash
# 创建通用项目目录结构(可根据实际需求调整)
mkdir -p ~/your-project/{logs,data,config,static}
logs/:存放后端服务日志文件data/:存放数据库、文件存储等持久化数据config/:存放后端服务配置文件static/:存放静态资源(图片、视频、文档等)
步骤 2:登录镜像仓库
根据你使用的镜像仓库类型,执行对应的登录命令,获取镜像拉取权限:
通用登录命令
bash
# 替换为你的镜像仓库地址、用户名和密码/令牌
docker login [镜像仓库地址] -u [用户名] --password-stdin
常见镜像仓库登录示例
shell
# 1. Docker Hub
docker login -u your-docker-username --password-stdin
# 2. GitHub Container Registry (GHCR)
export GITHUB_TOKEN=your-github-personal-access-token
export GITHUB_USER=[你github的user]
echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_USER --password-stdin
# 3. 阿里云容器镜像服务 (ACR)
docker login registry.cn-hangzhou.aliyuncs.com -u your-aliyun-username --password-stdin
登录成功后,终端会提示 Login Succeeded。
步骤 3:编写通用 Docker Compose 配置文件
在 ~/your-project 目录下创建 docker-compose.yml 文件,以下是通用模板 ,只需替换尖括号 <> 中的内容即可适配你的后端服务:
yaml
# 通用后端服务自动化部署配置
# 使用 Watchtower 实现镜像自动检测与更新
version: '3.8'
services:
# 你的后端服务
backend:
image: <你的后端镜像地址:标签> # 例如: ghcr.io/username/backend:latest
container_name: <容器名称> # 例如: my-backend
restart: always # 容器异常自动重启
ports:
- "<主机端口>:<容器内端口>" # 例如: "8080:8080"
volumes:
# 挂载日志目录(将容器内日志映射到宿主机)
- ./logs:/app/logs
# 挂载数据目录(持久化数据库、文件等数据)
- ./data:/app/data
# 挂载配置文件(如需外部配置)
# - ./config/application.yml:/app/application.yml:ro
environment:
# 时区配置(统一为上海时区)
- TZ=Asia/Shanghai
# 你的后端服务环境变量(根据实际需求添加)
- SPRING_PROFILES_ACTIVE=prod
- DATABASE_URL=jdbc:mysql://db:3306/mydb
- REDIS_URL=redis://redis:6379
extra_hosts:
# 允许容器访问宿主机服务(如需连接宿主机数据库/Redis)
- "host.docker.internal:host-gateway"
healthcheck:
# 健康检查配置(确保服务正常启动后才对外提供服务)
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:<容器内端口>/health"]
interval: 30s # 检查间隔
timeout: 3s # 超时时间
start_period: 10s # 启动等待时间
retries: 3 # 重试次数
labels:
# Watchtower 自动更新标签(必须添加)
- "com.centurylinklabs.watchtower.enable=true"
# Watchtower 作用域标签(可选,用于区分不同服务组)
- "com.centurylinklabs.watchtower.scope=backend"
depends_on:
# 如需依赖其他服务(如数据库、Redis),在此处声明
# - db
# - redis
# Watchtower 自动更新服务(全局只需部署一个)
watchtower:
image: containrrr/watchtower:1.7.1
container_name: watchtower
restart: always
volumes:
# 挂载Docker套接字,用于管理容器生命周期
- /var/run/docker.sock:/var/run/docker.sock
# 挂载Docker认证配置,用于拉取私有镜像
- /root/.docker/config.json:/config.json:ro
environment:
- TZ=Asia/Shanghai
# 仅监控带有 com.centurylinklabs.watchtower.enable=true 标签的容器
- WATCHTOWER_LABEL_ENABLE=true
# 作用域配置(与后端服务保持一致)
- WATCHTOWER_SCOPE=backend
# 自动清理更新后的旧镜像,释放磁盘空间
- WATCHTOWER_CLEANUP=true
# 定时检查更新(Cron表达式:秒 分 时 日 月 周)
# 示例:每天凌晨2点检查更新
- WATCHTOWER_SCHEDULE=0 0 2 * * *
# 包含重启中的容器
- WATCHTOWER_INCLUDE_RESTARTING=true
# 不包含已停止的容器
- WATCHTOWER_INCLUDE_STOPPED=false
# 更新完成后发送通知(可选,支持Slack/钉钉/企业微信等)
# - WATCHTOWER_NOTIFICATIONS=slack
# - WATCHTOWER_NOTIFICATION_URL=slack://webhook-url
# 调试模式(生产环境建议关闭)
- WATCHTOWER_DEBUG=false
关键配置说明
| 配置项 | 作用 | 通用建议 |
|---|---|---|
restart: always |
容器退出时自动重启 | 生产环境必须开启 |
volumes |
数据持久化 | 所有需要保留的数据都应挂载到宿主机 |
healthcheck |
服务健康检查 | 必须实现 /health 接口,确保服务可用性 |
WATCHTOWER_SCHEDULE |
更新检查频率 | 建议设置在业务低峰期(如凌晨 2-4 点) |
WATCHTOWER_CLEANUP |
自动清理旧镜像 | 生产环境必须开启,避免磁盘爆满 |
步骤 4:启动自动化部署服务
进入项目目录,执行以下命令启动所有服务:
shell
cd ~/your-project
docker compose up -d
Docker 会自动完成以下操作:
- 拉取后端服务和 Watchtower 的最新镜像
- 按照配置创建并启动容器
- Watchtower 开始监控后端服务的镜像更新
通用日常运维操作
1. 查看服务运行状态
shell
# 查看所有容器状态
docker compose ps
# 查看单个容器状态
docker ps | grep <容器名称>
2. 查看服务日志
shell
# 实时查看所有服务日志
docker compose logs -f
# 实时查看后端服务日志
docker compose logs -f backend
# 查看最近100行日志
docker compose logs --tail 100 backend
3. 手动更新镜像
若需跳过 Watchtower 定时任务,立即更新后端服务:
shell
# 拉取最新镜像
docker compose pull backend
# 重启后端服务(Watchtower会自动执行此步骤)
docker compose restart backend
4. 停止和删除服务
shell
# 停止所有服务
docker compose down
# 停止服务并删除数据卷(谨慎使用!会删除所有持久化数据)
docker compose down -v
5. 验证自动化更新
当你将新版本的后端镜像推送到镜像仓库后,Watchtower 会在配置的时间自动执行以下操作:
- 检测到镜像有新版本
- 拉取最新镜像
- 停止旧容器
- 使用新镜像启动新容器
- 清理旧镜像全程无需人工干预,服务中断时间仅为容器重启时间(通常几秒)。
高级配置与最佳实践
1. 使用 .env 文件管理环境变量
为避免在 docker-compose.yml 中硬编码敏感信息,推荐使用 .env 文件管理环境变量:
shell
# 在项目目录下创建 .env 文件
touch ~/your-project/.env
在 .env 文件中添加环境变量:
env
# 数据库配置
DATABASE_URL=jdbc:mysql://db:3306/mydb
DATABASE_USERNAME=root
DATABASE_PASSWORD=your-password
# Redis配置
REDIS_URL=redis://redis:6379
REDIS_PASSWORD=your-redis-password
# Watchtower配置
WATCHTOWER_SCHEDULE=0 0 2 * * *
然后在 docker-compose.yml 中引用这些变量:
yaml
environment:
- DATABASE_URL=${DATABASE_URL}
- DATABASE_USERNAME=${DATABASE_USERNAME}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
2. 多服务部署
如果需要在同一台服务器上部署多个后端服务,只需:
- 为每个服务创建独立的项目目录
- 在每个服务的
docker-compose.yml中添加不同的WATCHTOWER_SCOPE - 全局只需部署一个 Watchtower 服务(或为每个服务组部署独立的 Watchtower)
3. 配置更新通知
Watchtower 支持多种通知方式,当容器更新完成后自动发送通知:
yaml
environment:
# 钉钉通知
- WATCHTOWER_NOTIFICATIONS=dingtalk
- WATCHTOWER_NOTIFICATION_URL=dingtalk://token@secret
# 企业微信通知
- WATCHTOWER_NOTIFICATIONS=wechatwork
- WATCHTOWER_NOTIFICATION_URL=wechatwork://webhook-url
# 邮件通知
- WATCHTOWER_NOTIFICATIONS=email
- WATCHTOWER_NOTIFICATION_EMAIL_FROM=your-email@example.com
- WATCHTOWER_NOTIFICATION_EMAIL_TO=admin@example.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.example.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=your-email@example.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=your-email-password