Linux使用Docker部署项目后期更新

在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

  1. 在GitHub仓库设置中添加Webhook
  2. URL: http://your-server:8080/webhook
  3. Content type: application/json
  4. 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. 最佳实践建议

  1. 版本标签: 为镜像打上版本标签

    bash 复制代码
    docker build -t node-express-app:v1.2.3 .
  2. 健康检查: 在Dockerfile中添加健康检查

    dockerfile 复制代码
    HEALTHCHECK --interval=30s --timeout=3s \
      CMD curl -f http://localhost:3000/health || exit 1
  3. 日志管理: 配置日志轮转

    bash 复制代码
    docker run -d \
      --log-opt max-size=10m \
      --log-opt max-file=3 \
      node-express-app

选择适合你项目规模的更新策略。对于小型项目,简单的重新构建方法就足够了;对于生产环境,建议使用蓝绿部署或自动化部署流程。

相关推荐
孤独得猿3 小时前
聊天室项目开发——etcd的安装和使用
linux·服务器·c++·etcd
siriuuus3 小时前
Linux Tomcat 简单使用及 Nginx 反向代理
linux·nginx·tomcat
呱呱巨基4 小时前
vim编辑器
linux·笔记·学习·编辑器·vim
竹等寒4 小时前
Linux-网络安全私房菜(二)
linux·服务器·web安全
YuCaiH4 小时前
Linux文件处理
linux·笔记·嵌入式
早睡冠军候选人5 小时前
Ansible学习----Ansible Playbook
运维·服务器·学习·云原生·容器·ansible
sulikey5 小时前
从实验出发深入理解Linux目录权限:r、w、x分别控制什么?能否进入目录到底由谁决定?
linux·运维·服务器·ubuntu·centos
疯狂吧小飞牛5 小时前
ip rule 策略路由
linux·网络·tcp/ip·运维开发
缘友一世5 小时前
深入理解Shell与反弹Shell:从原理到实战
linux·网络安全·shell