Jenkins学习笔记:Pipeline流水线自动拉取代码部署到docker
概述
本文档记录了使用 Jenkins Pipeline 配合 Docker 实现自动化 CI/CD 的完整过程。目标是从 Git 仓库(Gitee)拉取代码 → 构建 Docker 镜像 → 部署运行容器,全程自动化。
项目架构:
- 语言:Python FastAPI
- 包管理:uv(基于 pyproject.toml)
- 构建:Docker 多阶段构建
- 部署:Docker 容器运行
- CI/CD:Jenkins Pipeline(Declarative Pipeline)
前置条件
| 组件 | 说明 |
|---|---|
| Jenkins 服务 | 已安装并正常运行(本文使用 docker-compose 部署 Jenkins) |
| 代码仓库 | Gitee(或其他 Git 仓库),仓库内已有 Dockerfile 和 Jenkinsfile |
| Docker 环境 | Jenkins 所在节点能执行 docker 命令 |
一、创建管道流水线
Jenkins 首页 → New Item → 输入任务名称(如 fastapi-demo) → 选择 Pipeline → OK

二、各配置选项详解
1. Discard old builds(丢弃旧构建)
作用: 自动清理旧的构建记录,防止磁盘被撑爆。
推荐配置:
- Strategy: Log Rotation
- Days to keep builds:
7(保留最近 7 天的构建) - Max # of builds to keep:
20(最多保留 20 次构建记录)
2. GitHub project(项目链接)
作用: 在 Jenkins 任务页面显示一个跳转到仓库的快捷链接,方便快速查看源码。
Project url: 填你的仓库地址(如 https://gitee.com/peng-chao2005/test)
此字段非必填,纯辅助功能。
3. Triggers(构建触发器)
触发器决定 什么时候自动开始构建,有几种方式:
3.1 Build periodically(定时构建)
不管代码有没有变化,到点就执行一次。
Schedule 语法(Cron 表达式):
H 2 * * *
# 分段:分钟 小时 日期 月份 星期
# H 是 Jenkins 的哈希分散机制,防止所有任务同时触发
常用示例:
| 表达式 | 含义 |
|---|---|
H/5 * * * * |
每 5 分钟构建一次 |
H * * * * |
每小时构建一次 |
H 2 * * * |
每天凌晨 2 点构建一次 |
H 9 * * 1-5 |
工作日(周一至周五)早上 9 点 |
@daily |
每天一次 |
3.2 Poll SCM(轮询代码仓库)
每隔一段时间自动检查 Git 仓库有没有新提交,有则触发构建。
H/5 * * * *
# 每 5 分钟检查一次仓库变更
3.3 GitHub hook trigger / GitLab webhook(Webhook 触发)
代码 push 时由仓库主动通知 Jenkins,立即触发构建,实时性最高。
需要配合在仓库 Settings → Webhooks 中配置 Jenkins 地址:
- GitHub:
http://<Jenkins-IP>:8080/github-webhook/ - Gitee: 在仓库 → 管理 → WebHooks 中添加
本文使用 Build periodically,适合学习和测试场景。生产环境推荐 Webhook 方式。
三、Pipeline 部分配置
Pipeline 区域是整个任务的核心,定义了 Jenkins 要去哪里拿代码 以及 按什么脚本执行。
Definition(定义方式)
有两种选择:
| 方式 | 说明 | 适用场景 |
|---|---|---|
| Pipeline script | 直接在 Jenkins 网页里写构建脚本 | 临时测试、快速验证 |
| Pipeline script from SCM(推荐 ✅) | 从 Git 仓库读取 Jenkinsfile | 版本化管理、团队协作 |
本文使用 Pipeline script from SCM。
关键字段说明
Repository URL(仓库地址)
填你的 Git 仓库地址:
https://gitee.com/你的用户名/你的仓库.git
Credentials(凭据)
- 公开仓库: 可以不填凭据
- 私有仓库: 需要添加登录凭据
本文拉取的是 Gitee 私有仓库,添加凭据步骤:
- 点击 Add → Jenkins
- 填写:
| 字段 | 内容 |
|---|---|
| Kind | Username with password |
| Username | Gitee 用户名 |
| Password | Gitee 登录密码 |
| ID | gitee-creds(自定义标识) |

注意: Gitee 的默认分支是
master(不是main),所以 Branches to build 要填*/master。
Branch Specifier(分支指定)
*/master
如果不填,默认使用仓库的 HEAD 分支。
也可以指定为 */develop、*/feature/* 等。
Script Path(脚本路径)
Jenkinsfile 在仓库中的路径:
- 在根目录: 填
Jenkinsfile
⚠️ 这是最容易出错的地方,必须和仓库里的实际路径完全一致,包括大小写。
本文的 Jenkinsfile 在仓库根目录,所以填 Jenkinsfile。
Lightweight checkout(轻量级检出)
勾选后,Jenkins 先只下载 Jenkinsfile 本身来解析流水线结构,解析完成后再全量拉取代码。
建议勾选,可以节省一次不必要的全量下载。
四、安装 Docker Pipeline 插件
Jenkins 默认不认识 docker.build() 等命令,需要安装插件。
操作步骤:
- Jenkins 首页 → Manage Jenkins → Plugins
- 切换到 Available plugins 选项卡
- 搜索 Docker Pipeline
- 勾选 → 点击 Install without restart
- 安装完成后,如有提示则重启 Jenkins

如果不安装此插件,会报如下错误:
groovy.lang.MissingPropertyException: No such property: docker for class: groovy.lang.Binding
五、Docker 环境配置
问题:docker: not found
如果 Jenkins 是以容器方式运行的,容器内部默认没有 docker 命令,执行 docker build 会报错:
/var/jenkins_home/workspace/xxx: docker: not found
解决方法
在 Jenkins 容器的 docker-compose.yml 中挂载宿主机 Docker:
name: "Jenkins"
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
user: root
ports:
- "34560:8080"
- "34561:50000"
volumes:
- /volume/Jenkins/jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
三行 volumes 的作用:
| 挂载项 | 作用 |
|---|---|
/var/run/docker.sock |
让容器内的 Docker CLI 连接宿主机的 Docker 守护进程 |
/usr/bin/docker |
把宿主机上的 docker 二进制文件共享到容器内 |
/volume/Jenkins/jenkins_home |
持久化 Jenkins 配置和数据,重启不丢失 |
注意: 修改 docker-compose.yml 后,不能只用
restart,必须docker-compose down && docker-compose up -d重新创建容器,volumes 配置才会生效。Jenkins 的配置数据会保留,因为挂载了持久化目录。
六、完整的 Jenkinsfile
pipeline {
// 在哪台机器上跑
agent any
// 环境变量
environment {
// ===== 按你的项目修改 =====
IMAGE_NAME = 'fastapi-demo'
IMAGE_TAG = "${BUILD_NUMBER}"
CONTAINER_NAME = 'fastapi-demo'
HOST_PORT = '8858'
CONTAINER_PORT = '8000'
// ===========================
}
// 流水线阶段
stages {
stage('拉取代码') {
steps {
checkout scm
}
// 从配置的 Git 仓库拉取最新代码
}
stage('构建 Docker 镜像') {
steps {
script {
docker.build("${IMAGE_NAME}:${IMAGE_TAG}")
// 也打 latest 标签,方便回滚时指定
sh "docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:latest"
}
}
// 等价于: docker build -t fastapi-demo:3 . && docker tag fastapi-demo:3 fastapi-demo:latest
}
stage('停止并删除旧容器') {
steps {
script {
sh """
docker stop ${CONTAINER_NAME} || true
docker rm ${CONTAINER_NAME} || true
"""
}
}
// || true 确保第一次部署没有旧容器时也不会报错终止
}
stage('启动新容器') {
steps {
script {
sh """
docker run -d \\
--name ${CONTAINER_NAME} \\
--restart unless-stopped \\
-p ${HOST_PORT}:${CONTAINER_PORT} \\
${IMAGE_NAME}:${IMAGE_TAG}
"""
}
}
// 等价于: docker run -d --name fastapi-demo --restart unless-stopped -p 8858:8000 fastapi-demo:3
}
stage('清理旧镜像(保留最近 5 个)') {
steps {
script {
sh """
docker image prune -f --filter "until=24h" || true
"""
}
}
// 删除 24 小时前的不再使用的镜像,节省磁盘空间
}
}
// 构建完成后的操作
post {
success {
echo "✅ 部署成功!访问 http://<服务器IP>:${HOST_PORT}"
sh "docker ps --filter name=${CONTAINER_NAME} --format '容器状态: {{.Status}}'"
}
failure {
echo "❌ 部署失败,请查看构建日志"
}
}
}
完整执行流程
代码 Push 到 Gitee
│
▼
Jenkins 触发构建
│
├── [1] checkout scm 从 Gitee 拉取最新代码
├── [2] docker build 构建镜像 fastapi-demo:3
│ (多阶段构建,用 uv 安装依赖)
├── [3] docker stop 停止旧容器(首次无则跳过)
├── [4] docker rm 删除旧容器(首次无则跳过)
├── [5] docker run 启动新容器,映射 8858:8000
├── [6] docker prune 清理 24 小时前的旧镜像
└── [7] post 输出 ✅ 或 ❌ 结果
七、流水线常用命令解析
checkout scm
- 作用: 从任务配置的 Git 仓库拉取代码
- 说明: Jenkins 自动生成,等价于
git clone+ 切换到指定分支 - 无需手动写参数,仓库地址、凭据、分支都在配置界面填好了
docker.build()
- 作用: 构建 Docker 镜像
- 等价于:
docker build -t <name> . - 来源: Docker Pipeline 插件提供的 Groovy 方法
- 注意: 不装插件会报
No such property: docker
sh """..."""
- 作用: 在 Jenkins 节点上执行 Shell 命令
- 三引号: Groovy 的多行字符串,可以换行写命令
- ${变量}: 引用在 environment 中定义的变量
docker run -d
| 参数 | 作用 |
|---|---|
-d |
后台运行 |
--name |
指定容器名,方便后续管理 |
--restart unless-stopped |
自动重启策略,除非手动 stop |
-p 宿主机端口:容器端口 |
端口映射 |
|| true
- 作用: 命令执行失败时忽略错误,流水线继续执行
- 场景:
docker stop时容器不存在会报错,加上|| true让流水线不被中断
post
- 作用: 所有 stage 执行完毕后执行
- success: 全部成功时触发
- failure: 任意 stage 失败时触发
- 可以扩展: 发送钉钉通知、邮件通知等
八、构建结果验证
构建成功后:
- 查看控制台输出: 点构建记录 → Console Output,确认各 stage 都是绿色通过
- 检查容器状态: 在服务器上执行
docker ps查看容器是否运行 - 访问接口验证: 浏览器打开
http://<服务器IP>:8858/docs
结果截图

FastAPI 项目接口一览
| 接口 | URL | 说明 |
|---|---|---|
| 根路径 | http://IP:8858/ |
返回基础信息 |
| 健康检查 | http://IP:8858/health |
{"status": "ok"} |
| 接口信息 | http://IP:8858/api/info |
服务版本和时间戳 |
| API 文档 | http://IP:8858/docs |
Swagger 交互式文档 |
| 回声测试 | POST http://IP:8858/api/echo |
传入 {"message": "hello"} 返回回声 |
九、常见问题排查
| 报错 | 原因 | 解决 |
|---|---|---|
No such property: docker for class: groovy.lang.Binding |
未安装 Docker Pipeline 插件 | Manage Jenkins → Plugins → 安装 Docker Pipeline |
docker: not found |
Jenkins 容器内没有 docker 命令 | 在 docker-compose.yml 挂载 /usr/bin/docker |
permission denied 连接 Docker socket |
Jenkins 用户无权限 | 使用 user: root 或在宿主机将 Jenkins 用户加入 docker 组 |
Script not found: xxx/Jenkinsfile |
Script Path 路径错误 | 检查 Jenkinsfile 在仓库中的实际路径 |
port is already allocated |
端口被占用 | 修改 HOST_PORT,或先 docker stop 占用端口的容器 |
Could not find credentials |
Git 凭据无效 | 重新添加凭据,检查 Token 是否过期 |
十、总结
通过 Jenkins Pipeline + Docker,实现了:
代码推送 → 自动构建 → 自动部署 → 服务可用
全程不需要手动登录服务器执行命令
核心知识点
- Jenkins Pipeline 使用 Declarative Groovy 语法,stage/steps 结构化编排任务
- Docker Pipeline 插件 提供了
docker.build()等便捷方法 - 容器化 Jenkins 需要挂载宿主机 Docker socket 和 docker 二进制文件才能执行 docker 命令
- Jenkinsfile 与代码同仓库管理,方便版本控制和团队协作
- Discard old builds 和 docker image prune 都是必要的运维策略,防止磁盘占满

浙公网安备 33010602011771号