From 2bf72e1febb942388d732df4711ad1ccdac60212 Mon Sep 17 00:00:00 2001 From: seahi Date: Wed, 17 Dec 2025 08:51:11 +0800 Subject: [PATCH] Update app.py --- .drone.yml | 70 +++++++++++++++++++++++++++ Dockerfile | 30 ++++++++++++ README.md | 37 ++++++++++++++ app.py | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++ build.sh | 25 ++++++++++ 5 files changed, 301 insertions(+) create mode 100644 .drone.yml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 app.py create mode 100644 build.sh diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..c5cf445 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,70 @@ +kind: pipeline +type: docker +name: build-by-tag + +node: + name: pve + +trigger: + event: + - tag + ref: + - refs/tags/v* + +steps: + - name: build-and-push + image: docker:dind + volumes: + - name: dockersock + path: /var/run/docker.sock + environment: + REGISTRY: harbor.seahi.me + IMAGE_NAME: stu/versions-for-swarm + HARBOR_USERNAME: + from_secret: harbor_username + HARBOR_PASSWORD: + from_secret: harbor_password + commands: + # 登录 Harbor + - echo $HARBOR_PASSWORD | docker login $REGISTRY -u $HARBOR_USERNAME --password-stdin + + # 从 Git Tag 获取版本号 + - export VERSION=${DRONE_TAG} + - echo "📦 构建版本: $VERSION" + + # 判断是否为 buggy 版本 + - | + if echo "$VERSION" | grep -q "buggy"; then + BUGGY_FLAG="--build-arg BUGGY=true" + echo "⚠️ 检测到 buggy 版本,启用故障模式" + else + BUGGY_FLAG="" + fi + + # 构建镜像 + - docker build + --build-arg APP_VERSION=$VERSION + $BUGGY_FLAG + -t $REGISTRY/$IMAGE_NAME:$VERSION + . + + # 如果是 v2.1,同时标记为 latest + - | + if [ "$VERSION" = "v2.1" ]; then + docker tag $REGISTRY/$IMAGE_NAME:$VERSION $REGISTRY/$IMAGE_NAME:latest + docker push $REGISTRY/$IMAGE_NAME:latest + echo "🏷️ 已标记为 latest" + fi + + # 推送镜像 + - docker push $REGISTRY/$IMAGE_NAME:$VERSION + + # 清理 + - docker system prune -f + + - echo "✅ 版本 $VERSION 构建并推送成功!" + +volumes: + - name: dockersock + host: + path: /var/run/docker.sock diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5d64f58 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.9-alpine + +# 构建参数 +ARG APP_VERSION=v1.0 +ARG BUGGY=false + +# 设置时区 +RUN apk add --no-cache tzdata && \ + cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone && \ + apk del tzdata + +ENV TZ=Asia/Shanghai \ + APP_VERSION=${APP_VERSION} \ + BUGGY=${BUGGY} + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY app.py . + +EXPOSE 80 + +# 添加健康检查(v2.0+ 特性) +HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1 + +CMD ["python", "app.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..982ba77 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# Docker Swarm 版本管理演示项目 + +> 🎓 专为 Docker Swarm 滚动更新与回滚教学设计的多版本应用 + +[![Build Status](https://drone.seahi.me/api/badges/Teaching/versions-for-swarm/status.svg)](https://drone.seahi.me/Teaching/versions-for-swarm) + +## 📋 项目简介 + +这是一个用于演示 Docker Swarm 滚动更新、回滚和版本管理的教学项目。通过**视觉化的版本差异**(不同颜色主题),学生可以直观地观察到: + +- ✅ 滚动更新过程中的零停机部署 +- ✅ 多副本逐步替换的过程 +- ✅ 故障版本的自动/手动回滚 +- ✅ CI/CD 自动构建多版本镜像 + +## 🎨 版本说明 + +| 版本 | 主题颜色 | 特性 | 用途 | +|------|---------|------|------| +| **v1.0** | 🔵 蓝色 | 基础功能 | 初始部署演示 | +| **v2.0** | 🟢 绿色 | 新增健康检查、API接口 | 正常升级演示 | +| **v2.1** | 🟢 绿色 | 性能优化、Bug修复 | 稳定版本 | +| **v3.0-buggy** | 🔴 红色 | ⚠️ 50%概率返回500错误 | 回滚场景演示 | + +## 🚀 快速开始 + +### 1️⃣ 部署初始版本 (v1.0) + +```bash +docker service create \ + --replicas 3 \ + --name demo-app \ + --publish 9000:80 \ + --env STUDENT_ID=00 \ + --update-delay 10s \ + --update-parallelism 1 \ + harbor.seahi.me/stu/versions-for-swarm:v1.0 diff --git a/app.py b/app.py new file mode 100644 index 0000000..6e172af --- /dev/null +++ b/app.py @@ -0,0 +1,139 @@ +from flask import Flask, jsonify +import socket +import os +from datetime import datetime +import random + +app = Flask(__name__) + +# 从环境变量读取版本号 +VERSION = os.getenv('APP_VERSION', 'v1.0') +BUGGY = os.getenv('BUGGY', 'false').lower() == 'true' + +# 版本主题配置 +THEMES = { + 'v1.0': {'color': '#4A90E2', 'name': '蓝色经典版', 'features': '基础功能'}, + 'v2.0': {'color': '#50C878', 'name': '绿色升级版', 'features': '新增健康检查、API接口'}, + 'v2.1': {'color': '#50C878', 'name': '绿色稳定版', 'features': '性能优化、Bug修复'}, + 'v3.0-buggy': {'color': '#E74C3C', 'name': '红色测试版', 'features': '⚠️ 此版本存在已知问题'} +} + +@app.route('/') +def hello(): + # 模拟 v3.0-buggy 的问题 + if BUGGY and random.random() < 0.5: + return "💥 服务异常:数据库连接失败", 500 + + theme = THEMES.get(VERSION, THEMES['v1.0']) + + return f""" + + + + Docker Swarm 滚动更新演示 + + + + + +
+

🚀 {theme['name']}

+
版本 {VERSION}
+
+
+ + + + + + + + + + + + + + + + + +
📦 容器主机名{socket.gethostname()}
🎓 学号服务s{os.getenv('STUDENT_ID', '00')}
⏰ 当前时间{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
✨ 版本特性{theme['features']}
+
🔄 页面每3秒自动刷新,观察容器变化
+
+ + + """ + +@app.route('/api/version') +def version(): + return jsonify({ + 'version': VERSION, + 'hostname': socket.gethostname(), + 'student_id': os.getenv('STUDENT_ID', '00'), + 'timestamp': datetime.now().isoformat(), + 'buggy': BUGGY + }) + +@app.route('/health') +def health(): + if BUGGY and random.random() < 0.3: + return {'status': 'unhealthy'}, 503 + return {'status': 'healthy', 'version': VERSION}, 200 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=80) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..2e6301c --- /dev/null +++ b/build.sh @@ -0,0 +1,25 @@ +#!/bin/bash +REGISTRY="harbor.seahi.me/stu" +IMAGE_NAME="whoami-for-swarm" + +# 构建 v1.0 +docker build --build-arg APP_VERSION=v1.0 \ + -t ${REGISTRY}/${IMAGE_NAME}:v1.0 . +docker push ${REGISTRY}/${IMAGE_NAME}:v1.0 + +# 构建 v2.0 +docker build --build-arg APP_VERSION=v2.0 \ + -t ${REGISTRY}/${IMAGE_NAME}:v2.0 . +docker push ${REGISTRY}/${IMAGE_NAME}:v2.0 + +# 构建 v2.1 +docker build --build-arg APP_VERSION=v2.1 \ + -t ${REGISTRY}/${IMAGE_NAME}:v2.1 . +docker push ${REGISTRY}/${IMAGE_NAME}:v2.1 + +# 构建 v3.0-buggy(有问题的版本) +docker build --build-arg APP_VERSION=v3.0-buggy --build-arg BUGGY=true \ + -t ${REGISTRY}/${IMAGE_NAME}:v3.0-buggy . +docker push ${REGISTRY}/${IMAGE_NAME}:v3.0-buggy + +echo "✅ 所有版本构建完成!"