在CentOS中使用docker部署了项目,对项目想改后,可以使用以下是几种更新部署方法:
1. 手动更新方法
方法一:重新构建镜像
bash
# 进入项目目录
cd /path/to/your-project
# 停止当前容器
docker stop node-app
# 删除旧容器
docker rm node-app
# 重新构建镜像(使用新代码)
docker build -t node-express-app .
# 启动新容器
docker run -d \
--name node-app \
-p 3000:3000 \
-v $(pwd)/database:/usr/src/app/database \
node-express-app
方法二:使用Docker Compose更新
bash
# 进入项目目录
cd /path/to/your-project
# 拉取最新代码(如果使用Git)
git pull
# 重新构建并启动
docker-compose down
docker-compose up -d --build
2. 自动化更新脚本
创建部署脚本 deploy.sh
bash
#!/bin/bash
# 部署脚本
set -e
echo "开始部署 Node.js 应用..."
# 进入项目目录
cd /path/to/your-project
# 拉取最新代码(如果使用Git)
echo "拉取最新代码..."
git pull origin main
# 备份数据库(重要!)
echo "备份数据库..."
cp -r database/database.backup.$(date +%Y%m%d_%H%M%S)
# 停止并删除旧容器
echo "停止旧容器..."
docker-compose down || true
# 重新构建镜像
echo "构建新镜像..."
docker-compose build
# 启动服务
echo "启动新容器..."
docker-compose up -d
# 等待应用启动
sleep 10
# 检查应用状态
echo "检查应用状态..."
curl -f http://localhost:3000/health || echo "应用可能还在启动中"
echo "部署完成!"
给脚本执行权限:
bash
chmod +x deploy.sh
3. 使用Git Webhooks自动部署
创建自动部署脚本 webhook-deploy.sh
bash
#!/bin/bash
# Webhook 部署脚本
WEBHOOK_SECRET="your-secret-token"
PROJECT_DIR="/path/to/your-project"
DOCKER_COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
# 验证webhook签名(可选)
verify_signature() {
local signature=$1
local payload=$2
# 实现签名验证逻辑
}
# 处理部署
deploy() {
cd $PROJECT_DIR
# 拉取最新代码
git pull origin main
# 重新部署
docker-compose -f $DOCKER_COMPOSE_FILE down
docker-compose -f $DOCKER_COMPOSE_FILE up -d --build
echo "部署完成: $(date)"
}
# 主逻辑
read payload
signature=$(echo "$payload" | grep -o '"signature":"[^"]*' | cut -d'"' -f4)
# 验证签名(如果设置了secret)
# verify_signature "$signature" "$payload"
deploy
设置GitHub Webhook
- 在GitHub仓库设置中添加Webhook
- URL:
http://your-server:8080/webhook
- Content type:
application/json
- Secret: 你的密钥
4. 使用Watchtower自动更新(推荐用于开发环境)
安装和运行Watchtower
bash
# 拉取Watchtower镜像
docker pull containrrr/watchtower
# 运行Watchtower监控特定容器
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--interval 30 \
node-app
在Docker Compose中添加Watchtower
yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
volumes:
- ./database:/usr/src/app/database
environment:
- NODE_ENV=production
restart: unless-stopped
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 30
restart: unless-stopped
5. 蓝绿部署策略(零停机更新)
创建蓝绿部署脚本 blue-green-deploy.sh
bash
#!/bin/bash
# 蓝绿部署脚本
BLUE_PORT=3000
GREEN_PORT=3001
CURRENT_COLOR="blue"
# 检测当前运行的颜色
detect_current_color() {
if docker ps --format "table {{.Names}}" | grep -q "node-app-blue"; then
CURRENT_COLOR="blue"
NEW_COLOR="green"
NEW_PORT=$GREEN_PORT
else
CURRENT_COLOR="green"
NEW_COLOR="blue"
NEW_PORT=$BLUE_PORT
fi
}
# 部署新版本
deploy_new_version() {
echo "部署 $NEW_COLOR 版本..."
docker build -t node-express-app:$NEW_COLOR .
docker run -d \
--name node-app-$NEW_COLOR \
-p $NEW_PORT:3000 \
-v $(pwd)/database:/usr/src/app/database \
node-express-app:$NEW_COLOR
# 等待新应用启动
echo "等待新应用启动..."
sleep 10
# 健康检查
if curl -f http://localhost:$NEW_PORT/health > /dev/null 2>&1; then
echo "$NEW_COLOR 版本健康检查通过"
return 0
else
echo "$NEW_COLOR 版本健康检查失败"
return 1
fi
}
# 切换流量
switch_traffic() {
echo "切换到 $NEW_COLOR 版本..."
# 使用Nginx或负载均衡器切换流量
# 这里简单演示停止旧版本
docker stop node-app-$CURRENT_COLOR
docker rm node-app-$CURRENT_COLOR
# 重命名新容器
docker rename node-app-$NEW_COLOR node-app-$CURRENT_COLOR
}
# 主部署流程
detect_current_color
echo "当前运行: $CURRENT_COLOR, 新部署: $NEW_COLOR"
if deploy_new_version; then
switch_traffic
echo "部署成功完成!"
else
echo "部署失败,回滚到 $CURRENT_COLOR 版本"
docker stop node-app-$NEW_COLOR
docker rm node-app-$NEW_COLOR
fi
6. 数据库迁移处理
创建数据库迁移脚本
javascript
// migrations/migrate.js
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
function runMigrations() {
const dbPath = process.env.NODE_ENV === 'production'
? '/usr/src/app/database/mydb.sqlite'
: path.join(__dirname, '../database/mydb.sqlite');
const db = new sqlite3.Database(dbPath);
// 执行迁移
db.serialize(() => {
// 示例:添加新表
db.run(`
CREATE TABLE IF NOT EXISTS new_features (
id INTEGER PRIMARY KEY AUTOINCREMENT,
feature_name TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 示例:修改现有表
db.run(`
ALTER TABLE users ADD COLUMN phone TEXT
`, (err) => {
// 忽略列已存在的错误
if (err && !err.message.includes('duplicate column name')) {
console.error('迁移错误:', err);
}
});
});
db.close();
}
module.exports = { runMigrations };
在应用启动时运行迁移
javascript
// app.js
const { runMigrations } = require('./migrations/migrate');
// 应用启动时运行数据库迁移
runMigrations();
// 其他应用代码...
7. 回滚策略
创建回滚脚本 rollback.sh
bash
#!/bin/bash
# 回滚脚本
echo "开始回滚..."
# 停止当前容器
docker stop node-app
docker rm node-app
# 使用之前的镜像启动
docker run -d \
--name node-app \
-p 3000:3000 \
-v $(pwd)/database:/usr/src/app/database \
node-express-app:previous
echo "回滚完成"
8. 最佳实践建议
-
版本标签: 为镜像打上版本标签
bashdocker build -t node-express-app:v1.2.3 .
-
健康检查: 在Dockerfile中添加健康检查
dockerfileHEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:3000/health || exit 1
-
日志管理: 配置日志轮转
bashdocker run -d \ --log-opt max-size=10m \ --log-opt max-file=3 \ node-express-app
选择适合你项目规模的更新策略。对于小型项目,简单的重新构建方法就足够了;对于生产环境,建议使用蓝绿部署或自动化部署流程。