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

image.png


二、各配置选项详解

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 私有仓库,添加凭据步骤:

  1. 点击 AddJenkins
  2. 填写:
字段 内容
Kind Username with password
Username Gitee 用户名
Password Gitee 登录密码
ID gitee-creds(自定义标识)

image.png

注意: 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() 等命令,需要安装插件。

操作步骤:

  1. Jenkins 首页 → Manage JenkinsPlugins
  2. 切换到 Available plugins 选项卡
  3. 搜索 Docker Pipeline
  4. 勾选 → 点击 Install without restart
  5. 安装完成后,如有提示则重启 Jenkins

image.png

如果不安装此插件,会报如下错误:

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 失败时触发
  • 可以扩展: 发送钉钉通知、邮件通知等

八、构建结果验证

构建成功后:

  1. 查看控制台输出: 点构建记录 → Console Output,确认各 stage 都是绿色通过
  2. 检查容器状态: 在服务器上执行 docker ps 查看容器是否运行
  3. 访问接口验证: 浏览器打开 http://<服务器IP>:8858/docs

结果截图

image.png

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,实现了:

代码推送 → 自动构建 → 自动部署 → 服务可用
全程不需要手动登录服务器执行命令

核心知识点

  1. Jenkins Pipeline 使用 Declarative Groovy 语法,stage/steps 结构化编排任务
  2. Docker Pipeline 插件 提供了 docker.build() 等便捷方法
  3. 容器化 Jenkins 需要挂载宿主机 Docker socket 和 docker 二进制文件才能执行 docker 命令
  4. Jenkinsfile 与代码同仓库管理,方便版本控制和团队协作
  5. Discard old buildsdocker image prune 都是必要的运维策略,防止磁盘占满
posted @ 2026-08-05 22:29  PC2005-cloud  阅读(37)  评论(0)    收藏  举报