diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 986700d..0000000 --- a/.drone.yml +++ /dev/null @@ -1,73 +0,0 @@ -kind: pipeline -type: docker -name: build-by-tag - -node: - name: pve - -trigger: - event: - - tag - ref: - - refs/tags/v* - -steps: - - name: build-and-push-normal - image: plugins/docker - settings: - registry: harbor.seahi.me - repo: harbor.seahi.me/stu/versions-for-swarm - username: - from_secret: harbor_username - password: - from_secret: harbor_password - insecure: true - tags: - - ${DRONE_TAG} - build_args: - - APP_VERSION=${DRONE_TAG} - auto_tag: false - when: - ref: - exclude: - - refs/tags/*buggy* - - - name: build-and-push-buggy - image: plugins/docker - settings: - registry: harbor.seahi.me - repo: harbor.seahi.me/stu/versions-for-swarm - username: - from_secret: harbor_username - password: - from_secret: harbor_password - insecure: true - tags: - - ${DRONE_TAG} - build_args: - - APP_VERSION=${DRONE_TAG} - - BUGGY=true - auto_tag: false - when: - ref: - include: - - refs/tags/*buggy* - - - name: tag-latest-if-v2.1 - image: plugins/docker - settings: - registry: harbor.seahi.me - repo: harbor.seahi.me/stu/versions-for-swarm - username: - from_secret: harbor_username - password: - from_secret: harbor_password - insecure: true - tags: - - latest - build_args: - - APP_VERSION=${DRONE_TAG} - auto_tag: false - when: - ref: - - refs/tags/v2.1 diff --git a/Dockerfile b/Dockerfile index efbf9df..9936f56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,17 +16,15 @@ ENV TZ=Asia/Shanghai \ WORKDIR /app -RUN pip install flask -# COPY requirements.txt . -# RUN pip install --no-cache-dir -r requirements.txt +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 80 # 添加健康检查(v2.0+ 特性) -# 注意:v1.0 版本没有 /health 端点,不应添加健康检查 -# HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ -# CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1 +HEALTHCHECK --interval=10s --timeout=3s --start-period=30s --retries=3 \ + CMD wget -q --spider http://127.0.0.1:80/health 2>&1 || exit 1 CMD ["python", "app.py"] diff --git a/README.md b/README.md index 982ba77..8bcba3a 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,32 @@ ```bash docker service create \ --replicas 3 \ - --name demo-app \ + --name s00 \ --publish 9000:80 \ --env STUDENT_ID=00 \ - --update-delay 10s \ - --update-parallelism 1 \ harbor.seahi.me/stu/versions-for-swarm:v1.0 +``` + +### 2️⃣ 部署后续版本 (v2.0) + +```bash +docker service update \ + --image harbor.seahi.me/stu/versions-for-swarm:v2.0 \ + s00 +``` + +### 3️⃣ 部署稳定版本 (v2.1) + +```bash +docker service update \ + --image harbor.seahi.me/stu/versions-for-swarm:v2.1 \ + s00 +``` + +### 4️⃣ 部署故障版本 (v3.0-buggy) + +```bash +docker service update \ + --image harbor.seahi.me/stu/versions-for-swarm:v3.0-buggy \ + s00 +``` diff --git a/app.py b/app.py index 6e172af..5ee68a9 100644 --- a/app.py +++ b/app.py @@ -1,30 +1,40 @@ -from flask import Flask, jsonify -import socket import os -from datetime import datetime import random +import socket +from datetime import datetime + +from flask import Flask, jsonify app = Flask(__name__) # 从环境变量读取版本号 -VERSION = os.getenv('APP_VERSION', 'v1.0') -BUGGY = os.getenv('BUGGY', 'false').lower() == 'true' +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': '⚠️ 此版本存在已知问题'} + "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('/') + +@app.route("/") def hello(): # 模拟 v3.0-buggy 的问题 if BUGGY and random.random() < 0.5: return "💥 服务异常:数据库连接失败", 500 - theme = THEMES.get(VERSION, THEMES['v1.0']) + theme = THEMES.get(VERSION, THEMES["v1.0"]) return f""" @@ -39,10 +49,10 @@ def hello(): max-width: 700px; margin: 50px auto; padding: 30px; - background: linear-gradient(135deg, {theme['color']}22 0%, {theme['color']}44 100%); + background: linear-gradient(135deg, {theme["color"]}22 0%, {theme["color"]}44 100%); }} .header {{ - background: {theme['color']}; + background: {theme["color"]}; color: white; padding: 20px; border-radius: 10px 10px 0 0; @@ -55,13 +65,13 @@ def hello(): box-shadow: 0 4px 6px rgba(0,0,0,0.1); }} .highlight {{ - color: {theme['color']}; + color: {theme["color"]}; font-weight: bold; font-size: 1.2em; }} .version-badge {{ display: inline-block; - background: {theme['color']}; + background: {theme["color"]}; color: white; padding: 5px 15px; border-radius: 20px; @@ -91,7 +101,7 @@ def hello():
-

🚀 {theme['name']}

+

🚀 {theme["name"]}

版本 {VERSION}
@@ -102,15 +112,15 @@ def hello(): 🎓 学号服务 - s{os.getenv('STUDENT_ID', '00')} + s{os.getenv("STUDENT_ID", "00")} ⏰ 当前时间 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} + {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} ✨ 版本特性 - {theme['features']} + {theme["features"]}
🔄 页面每3秒自动刷新,观察容器变化
@@ -119,21 +129,26 @@ def hello(): """ -@app.route('/api/version') + +@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 - }) + return jsonify( + { + "version": VERSION, + "hostname": socket.gethostname(), + "student_id": os.getenv("STUDENT_ID", "00"), + "timestamp": datetime.now().isoformat(), + "buggy": BUGGY, + } + ) -@app.route('/health') + +@app.route("/health") def health(): - if BUGGY and random.random() < 0.3: - return {'status': 'unhealthy'}, 503 - return {'status': 'healthy', 'version': VERSION}, 200 + if BUGGY and random.random() < 0.7: + return {"status": "unhealthy"}, 503 + return {"status": "healthy", "version": VERSION}, 200 -if __name__ == '__main__': - app.run(host='0.0.0.0', port=80) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=80) diff --git a/build.sh b/build.sh index 2e6301c..12dd4ff 100644 --- a/build.sh +++ b/build.sh @@ -1,25 +1,38 @@ #!/bin/bash REGISTRY="harbor.seahi.me/stu" -IMAGE_NAME="whoami-for-swarm" +IMAGE_NAME="versions-for-swarm" +PLATFORMS="linux/amd64,linux/386,linux/arm64" -# 构建 v1.0 -docker build --build-arg APP_VERSION=v1.0 \ - -t ${REGISTRY}/${IMAGE_NAME}:v1.0 . -docker push ${REGISTRY}/${IMAGE_NAME}:v1.0 +# 创建并使用支持多平台的 builder(如果不存在) +if ! docker buildx inspect multiplatform-builder >/dev/null 2>&1; then + docker buildx create --name multiplatform-builder --driver docker-container --bootstrap +fi +docker buildx use multiplatform-builder -# 构建 v2.0 -docker build --build-arg APP_VERSION=v2.0 \ - -t ${REGISTRY}/${IMAGE_NAME}:v2.0 . -docker push ${REGISTRY}/${IMAGE_NAME}:v2.0 +echo "🚀 开始构建所有版本..." -# 构建 v2.1 -docker build --build-arg APP_VERSION=v2.1 \ - -t ${REGISTRY}/${IMAGE_NAME}:v2.1 . -docker push ${REGISTRY}/${IMAGE_NAME}:v2.1 +# 并行构建所有版本 +docker buildx build --platform ${PLATFORMS} --build-arg APP_VERSION=v1.0 \ + -t ${REGISTRY}/${IMAGE_NAME}:v1.0 --push \ + --cache-from type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache \ + --cache-to type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache,mode=max . & -# 构建 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 +docker buildx build --platform ${PLATFORMS} --build-arg APP_VERSION=v2.0 \ + -t ${REGISTRY}/${IMAGE_NAME}:v2.0 --push \ + --cache-from type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache \ + --cache-to type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache,mode=max . & -echo "✅ 所有版本构建完成!" +docker buildx build --platform ${PLATFORMS} --build-arg APP_VERSION=v2.1 \ + -t ${REGISTRY}/${IMAGE_NAME}:v2.1 --push \ + --cache-from type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache \ + --cache-to type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache,mode=max . & + +docker buildx build --platform ${PLATFORMS} --build-arg APP_VERSION=v3.0-buggy --build-arg BUGGY=true \ + -t ${REGISTRY}/${IMAGE_NAME}:v3.0-buggy --push \ + --cache-from type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache \ + --cache-to type=registry,ref=${REGISTRY}/${IMAGE_NAME}:buildcache,mode=max . & + +# 等待所有后台任务完成 +wait + +echo "✅ 所有版本构建完成(支持平台: ${PLATFORMS})!" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flask