7.5 CI/CD综合实训

本实验将带你从零开始创建一个简单的 Flask 项目,并综合应用 Gitea、Drone、Harbor 实现完整的 CI/CD 流程:
- 自动构建:代码推送后自动构建 Docker 镜像
- 自动部署:自动将应用部署到目标服务器
- 自动通知:通过邮件通知部署结果
通过本次实验,你将复习上节课学习的自动构建知识,并掌握自动部署和邮件通知的配置方法。
任务一:创建并完善项目
在这个任务中,我们将从零开始创建一个简单的 Flask Web 应用项目。
1. 创建 Git 仓库
打开 Gitea 网页,创建一个新项目,项目名称为 helloflask。
2. 克隆项目到本地
使用 Sublime Merge 将刚创建的项目克隆到本地。
3. 创建 Flask 应用文件
在项目目录中创建 app.py 文件,这是我们的 Flask 应用主文件:
from flask import Flask
import os
app = Flask(__name__)
@app.route("/")
def hello():
return '''
<html>
<head>
<title>Hello Flask</title>
</head>
<body style="text-align: center; padding-top: 100px;">
<h1 style="color: #2196F3;">Flask inside Docker!</h1>
<p>这是一个运行在 Docker 容器中的 Flask 应用</p>
</body>
</html>
'''
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app.run(debug=True, host='0.0.0.0', port=port)
@app.route("/"):定义网站根路径的访问处理函数host='0.0.0.0':允许外部访问,这在 Docker 容器中是必需的port=port:使用环境变量指定的端口,默认为 5000
4. 创建依赖文件
创建 requirements.txt 文件,用于声明项目依赖的 Python 包:
flask>=3.0.0
requirements.txt 是 Python 项目的标准依赖声明文件,Docker 构建时会根据这个文件安装所需的包。5. 创建 Dockerfile
在项目根目录创建 Dockerfile 文件,用于定义如何构建 Docker 镜像:
FROM python:3.9-alpine
# 临时解决网络连通性问题
ENV HTTP_PROXY=http://192.168.192.199:10809
ENV HTTPS_PROXY=http://192.168.192.199:10809
ENV ALL_PROXY=http://192.168.192.199:10809
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
- FROM:指定基础镜像,这里使用 Python 3.9 的精简版
- WORKDIR:设置工作目录为
/app,如果目录不存在会自动创建 - COPY . .:复制项目所有文件
- RUN:安装 Python 依赖包,使用中科大镜像源加速下载
- CMD:指定容器启动时执行的命令
6. 测试手动构建
在配置自动构建之前,我们先测试一下 Dockerfile 是否能正常工作:
docker build -t helloflask:test .
. 表示当前目录是 Docker 的构建上下文(工作目录),Docker 会从这个目录中查找 Dockerfile 和需要复制的文件。如果构建成功,你会看到类似下面的输出:

可以运行容器测试一下:
docker run --rm -p 5000:5000 helloflask:test
然后在浏览器中访问 http://你的服务器IP:5000,看看是否能正常显示页面。
任务二:配置自动构建
现在我们已经有了一个可以正常工作的 Flask 项目,接下来配置 Drone 实现自动构建和推送到 Harbor。
1. 创建 Drone 配置文件
在项目根目录创建 .drone.yml 文件(注意文件名以 . 开头,是隐藏文件):
kind: pipeline
type: docker
name: helloflask-cicd # 任务名称
steps:
# 步骤1:构建并推送镜像到 Harbor
- name: 构建并推送到Harbor
image: plugins/docker
settings:
insecure: true
# 配置国内加速镜像
mirror: https://docker.seahi.me
# 镜像信息
dockerfile: Dockerfile
repo: 你的Harbor地址:9000/library/helloflask
tags: latest
# 注册中心信息,从“秘密”中读取信息
registry: 你的Harbor地址:9000
username:
from_secret: harbor_username
password:
from_secret: harbor_password
你的Harbor地址 替换为实际的 Harbor 服务器 IP 地址!2. 在 Drone 中配置密钥
由于我们在 .drone.yml 中使用了 from_secret 来引用 Harbor 的用户名和密码,需要在 Drone 网页中添加这些秘密。
打开 Drone 网页,进入你的 helloflask 仓库,点击 Settings(设置),然后找到 Secrets(秘密)部分:

添加以下两个秘密:
- 名称:
harbor_username,值:admin - 名称:
harbor_password,值:Harbor12345
.drone.yml 文件中 from_secret 后面的值完全一致,包括大小写。如果名称不匹配,构建时将无法获取到正确的认证信息,导致构建失败。3. 提交代码触发构建
现在所有配置都完成了,我们可以使用 Sublime Merge 将代码提交到 Git 仓库,触发自动构建。
4. 查看构建过程
代码推送后,Drone 会自动检测到代码变化并触发构建。打开 Drone 网页,你可以看到正在执行的构建任务:

点击构建任务可以查看详细的构建日志:

5. 验证镜像是否推送成功
构建成功后,打开 Harbor 网页,进入 library 项目,查看是否有新推送的 helloflask 镜像:

恭喜!你已经成功配置了自动构建流程。现在每当你向 Git 仓库推送代码时,Drone 都会自动构建 Docker 镜像并推送到 Harbor 仓库。
但这只是 CI/CD 的第一步,接下来我们要实现自动部署功能。
任务三:配置自动部署
有了自动构建的镜像,下一步就是自动部署到服务器上运行。这样就实现了完整的 CI/CD 流程。
1. 修改 Drone 配置文件
编辑 .drone.yml 文件,在 steps 数组中添加部署步骤:
# 步骤2:部署到目标服务器
- name: 部署应用
pull: if-not-exists
image: appleboy/drone-ssh
settings:
host: 你的目标服务器IP
port: 22
username: root
password: # 从秘密中读取
from_secret: ssh_password
script:
- echo "========== 开始部署 =========="
- echo "1. 停止并删除旧容器"
- docker stop helloflask || true
- docker rm helloflask || true
- echo "2. 删除旧镜像"
- docker rmi 你的Harbor地址:9000/library/helloflask:latest || true
- echo "3. 从 Harbor 拉取最新镜像"
- docker pull 你的Harbor地址:9000/library/helloflask:latest
- echo "4. 启动新容器"
- docker run --name helloflask -p 5000:5000 -d 你的Harbor地址:9000/library/helloflask:latest
- echo "========== 部署成功 =========="
请将配置文件中的以下内容替换为实际值:
你的Harbor地址:Harbor 服务器的 IP 地址你的目标服务器IP:应用要部署到的服务器 IP 地址(可以和 Harbor 是同一台)
这个部署步骤使用 appleboy/drone-ssh 插件,它会通过 SSH 连接到目标服务器并执行一系列命令:
- 停止并删除旧容器:使用
|| true确保即使容器不存在也不会报错 - 删除旧镜像:清理旧版本的镜像,节省磁盘空间
- 拉取最新镜像:从 Harbor 拉取刚刚构建好的最新镜像
- 启动新容器:使用新镜像启动容器,对外暴露 5000 端口
这个过程实现了"零停机部署"的简化版本,在生产环境中可能需要更复杂的滚动更新策略。
2. 在 Drone 中添加 SSH 密钥
由于部署步骤需要通过 SSH 连接到目标服务器,我们需要在 Drone 中添加 SSH 密码。
回到 Drone 网页的 Secrets(密钥)设置页面,添加:
- 名称:
ssh_password,值:目标服务器的 root 密码(admin@123)

3. 提交并测试自动部署
使用 Sublime Merge 将修改后的 .drone.yml 文件提交到仓库:
推送后,Drone 会自动触发构建和部署流程。打开 Drone 网页观察执行过程:

4. 验证应用是否正常运行
在浏览器中打开 http://目标服务器IP:5000,你应该能看到 Flask 应用的页面:

任务四:配置邮件通知
最后一步,我们添加邮件通知功能,让系统在部署完成后自动发送通知邮件,这样即使不盯着 Drone 网页,也能知道部署结果。
1. 修改 Drone 配置文件
编辑 .drone.yml 文件,添加邮件通知步骤:
# 步骤3:发送邮件通知
- name: 邮件通知
pull: if-not-exists
image: drillster/drone-email
settings:
recipients_only: true
host: smtp.larksuite.com
port: 465
subject: "【HelloFlask项目】部署完成通知"
username: # 邮箱用户名
from_secret: email_username
password: # 邮箱密码
from_secret: email_password
from: # 发件人
from_secret: email_username
recipients: # 收件人
from_secret: email_recipients
- image: drillster/drone-email:使用 Drone 的邮件插件
- recipients_only: true:只发送给指定的收件人,不发送给 Git 提交者
- host/port:SMTP 服务器地址和端口,这里使用飞书邮箱的 SMTP 服务
- subject:邮件主题
- from_secret:从密钥中读取邮箱配置信息
2. 在 Drone 中添加邮件配置密钥
回到 Drone 网页的 Secrets 设置页面,添加以下四个密钥:
- 名称:
email_username,值:教师提供 - 名称:
email_password,值:老师提供 - 名称:
email_recipients,值:收件人邮箱(填自己的邮箱)
3. 提交并测试邮件通知
使用 Sublime Merge 将修改后的配置文件提交到仓库。

等待 Drone 执行完整个流程后,检查你的收件箱,应该能收到部署通知邮件:

恭喜你!到此为止,你已经完成了一个完整的 CI/CD 流程配置:
- ✅ 代码管理:使用 Gitea 管理代码
- ✅ 自动构建:代码推送后 Drone 自动构建 Docker 镜像
- ✅ 镜像存储:构建的镜像自动推送到 Harbor
- ✅ 自动部署:自动将应用部署到目标服务器
- ✅ 状态通知:通过邮件通知部署结果
这就是现代软件开发中的持续集成/持续部署(CI/CD)流程!




