您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center 汽车系统工程   模型库  
会员   
   
企业架构方法与实践
7月27-28日 北京+线上
AI智能体开发技术实践
8月6-7日 上海+线上
敏捷测试-简单而可行
8月14-15日 北京+线上
     
   
 订阅
GitLab CI/CD 全流程实操:代码静态扫描、Docker 构建、镜像安全扫描与部署(安全合规篇)
 
作者:SRE运维小张
  4   次浏览      1 次
 2026-7-28
 
编辑推荐:
本文主要介绍gitlab CICD 配置静态代码扫描和镜像扫描方法,助力高质量代码生成,同时满足安全合规要求。希望对你的学习有帮助。
本文来自于微信公众号SRE运维小张,由火龙果软件Alice编辑推荐。

运维工作中,CI构建需要对代码进行扫描,确保代码规范和漏洞不会影响应用服务正常运行,这篇文章介绍gitlab CICD 配置静态代码扫描和镜像扫描方法,助力高质量代码生成,同时满足安全合规要求。

一、构建部署逻辑

文章基于上篇《Gitlab CICD流水线搭建》,实现下面5个步骤(侧重安全扫描过程)

阶段1:代码安全扫描(使用Semgrep,可自定义扫描规则)

阶段2:安装Python/Flask依赖,验证依赖可用性

阶段3:构建Docker镜像

阶段4:扫描Docker镜像安全漏洞(trivy工具)

阶段5:本地停止旧容器,启动新构建的Docker镜像

整体构建部署逻辑:使用两个runner 做执行端,构建使用的配置和项目代码全在项目仓库里;代码提交自动触发流水线作业,代码被执行器为docke的runner拉取做Semgrep扫描,结果有生成日志和扫描报告文件,扫描通过后,在执行器为shell的runner上(后面步骤都在这个runner执行),安装构建依赖包,实施构建docker操作,接着进行docker镜像扫描,最后是本地部署,展示结果。

二、GitLabCICD 配置

1、注册GitLab Runner

GitLab Runner 注册执行器为docker,是因为gitlab内置的代码扫描工具Semgrep需要使用它,可以在同一个节点上注册多个runner,方法和结果如下图

2、安装镜像扫描工具(gitlab内置的镜像扫描工具就是基于trivy命令封装的)

# 下载 trivy 命令并安装
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
su - gitlab-runner -c "trivy --version"
# 拉取最新的漏洞库
trivy image mirror.gcr.io/aquasec/trivy-db:2

 

3、提前拉取代码扫描镜像文件

# 提前拉取镜像,避免第一次构建拉取时间过长
docker pull registry.gitlab.com/security-products/semgrep:6
docker pull registry.gitlab.com/security-products/container-scanning:8
docker images #查看拉取情况

4、配置代码和ci工具文件

代码app.py文件,设定几个代码bug

from flask import Flask
# 新增:导入request用于获取用户输入(为XSS漏洞做准备)
from flask import request
app = Flask(__name__)
# Bug 1:硬编码敏感API密钥(Semgrep高风险漏洞,关键字「secret」「key」触发扫描)
# 符合Semgrep内置规则 python.security.secrets.hardcoded-api-key
HARDCODED_SECRET_KEY = "flask_secret_123456_unsafe" # 硬编码敏感数据
app.config['SECRET_KEY'] = HARDCODED_SECRET_KEY # 有效使用,确保Semgrep能识别
@app.route('/')
def hello():
   # 后续测试可修改此内容,验证流程闭环
   return "Hello Flask! 容器部署成功~ v2 "

@app.route('/greet')
def greet():
    user_name = request.args.get('name', 'Guest')
   return f"Hello, {user_name}! 欢迎访问~"
if __name__ == '__main__':
    # Bug 2:Flask开启调试模式(Semgrep中风险漏洞)
    # 符合Semgrep内置规则 python.flask.security.debug-mode.enabled
    app.run(host='0.0.0.0', port=5000, debug=True)

 CI文件 .gitlab-ci.yml

# ======================================================
# GitLab CI/CD 配置文件
# 用途:Python Flask应用的安全扫描与部署流水线
# 包含阶段:代码扫描 → 依赖安装 → 镜像构建 → 镜像扫描 → 部署
# ======================================================
# ==================== 模板引入 ====================
# 引入GitLab官方安全扫描模板,简化配置
include:
    # SAST:静态应用安全测试,自动扫描代码中的安全漏洞
   - template: Security/SAST.gitlab-ci.yml
    # 容器扫描:扫描Docker镜像中的安全漏洞
    - template: Security/Container-Scanning.gitlab-ci.yml
# ==================== 流水线阶段定义 ====================
# 定义全流程五个阶段,按顺序执行
stages:
    - code-scan # 阶段1:代码安全扫描(使用Semgrep)
   - install # 阶段2:安装Python/Flask依赖,验证依赖可用性
   - build # 阶段3:验证应用语法,构建Docker镜像
   - image-scan # 阶段4:扫描Docker镜像安全漏洞
   - deploy # 阶段5:本地停止旧容器,启动新构建的Docker镜像
# ==================== 阶段1:代码安全扫描 ====================
# 使用GitLab SAST功能进行静态代码安全分析
sast:
   stage: code-scan # 绑定到code-scan阶段
    tags:
      - scanning # 使用带有scanning标签的Runner执行
   # SAST扫描配置变量
    variables:
       # 指定使用Semgrep作为默认分析器
       SAST_DEFAULT_ANALYZERS: "semgrep"
       # 使用官方安全规则集:p/security(通用安全)+ p/python(Python专用)
       SAST_SEMGREP_RULESETS: "p/security,p/python"
       # 排除不需要扫描的目录
      SAST_EXCLUDED_PATHS: "vendor/, node_modules/, .git/"
      # 引入自定义Semgrep规则文件(关键:增强扫描能力)
      SAST_SEMGREP_ADDITIONAL_RULES: "./semgrep-rules/custom-python-rules.yml"
# 扫描前执行的脚本,主要用于调试和验证
before_script:
      # 查看项目目录结构,确认文件存在
      - echo "=== 列出Docker容器内项目目录文件 ==="
      - ls -la /builds/root/app-demo-src/
      # 确认自定义规则文件存在
      - echo "=== 列出semgrep-rules文件夹内文件 ==="
      - ls -la /builds/root/app-demo-src/semgrep-rules/
      # 验证自定义规则文件是否存在
      - echo "=== 验证自定义规则文件是否存在 ==="
      - test -f /builds/root/app-demo-src/semgrep-rules/custom-python-rules.yml && echo "自定义规则文件存在" || echo "自定义规则文件不存在"
      # 新增:手动执行Semgrep扫描,用于调试和详细日志输出
      - echo "=== 手动执行Semgrep原生扫描 ==="
      - semgrep scan --config /builds/root/app-demo-src/semgrep-rules/custom-python-rules.yml --verbose /builds/root/app-demo-src/app.py
# ==================== 阶段2:安装依赖 ====================
# 安装Python和Flask项目所需的依赖包
install_flask_deps:
      stage: install # 绑定到install阶段
      tags:
         - docker # 使用带有docker标签的Runner执行
      # 缓存配置:缓存pip下载的包,提升后续运行效率
      cache:
         paths:
            - ~/.cache/pip/
      # 主要执行脚本
      script:
          # 升级pip到最新版本
         - echo "===== 开始升级pip ====="
         - pip3 install --upgrade pip --user
         # 安装requirements.txt中指定的所有依赖
         - echo "===== 开始安装Flask项目依赖 ====="
         - pip3 install --no-cache-dir -r requirements.txt --user
         # 验证Flask依赖是否安装成功
         - echo "===== 验证依赖安装结果 ====="
         - python3 -c "import flask; print('Flask依赖安装成功,版本:', flask.__version__)"
# 工件(artifacts)配置:保存安装成功的依赖信息
artifacts:
      paths:
         - requirements.txt # 保存依赖列表文件
       when: on_success # 仅当任务成功时保存
       expire_in: 1 hour # 工件保存1小时后过期
# ==================== 阶段3:构建镜像 ====================
# 构建应用的Docker镜像
build_flask_docker:
      stage: build # 绑定到build阶段
      tags: [docker] # 使用带有docker标签的Runner执行
      dependencies: [install_flask_deps] # 依赖install_flask_deps阶段成功完成
      script:
         # 验证Python代码语法正确性
         - echo "===== 验证 app.py 语法正确性 ====="
         - python3 -m py_compile app.py # 语法检查,报错则终止CI
         # 构建Docker镜像并标记为latest
         - echo "===== 构建本地 Docker 镜像(flask-app:latest) ====="
         - docker build -t flask-app:latest .
         # 查看构建成功的镜像信息
          - echo "===== 本地镜像构建成功,查看镜像信息 ====="
          - docker images | grep flask-app # 打印本地镜像信息
      # 不允许失败:如果构建失败,整个流水线应该停止
       allow_failure: false
# ==================== 阶段4:镜像安全扫描 ====================
# 使用Trivy扫描Docker镜像中的安全漏洞
container_scanning:
      stage: image-scan # 绑定到image-scan阶段
       tags: [docker] # 使用带有docker标签的Runner执行
      dependencies: [build_flask_docker] # 依赖build_flask_docker阶段成功完成
       # 不允许失败:如果扫描失败,整个流水线应该停止
      allow_failure: false
       script:
         # 验证环境工具版本
         - echo "===== 1. 验证环境与 Docker 守护进程 ====="
          - docker --version # 验证Docker客户端可用
         - trivy --version # 验证Trivy工具可用
          # 执行容器安全扫描,生成GitLab标准格式的JSON报告
          - echo "===== 2. 生成漏洞扫描报告(GitLab 标准格式) ====="
         - trivy image --skip-version-check --skip-db-update --severity CRITICAL,HIGH --format json -o gl-container-scanning-report.json flask-app:latest
         # 生成软件物料清单(SBOM),CycloneDX格式
          - echo "===== 3. 生成 SBOM 报告(CycloneDX 格式) ====="
          - trivy image --skip-version-check --skip-db-update --format cyclonedx -o gl-sbom-flask-app.cdx flask-app:latest
          # 验证报告文件已正确生成
         - echo "===== 4. 验证报告文件已生成 ====="
          - ls -l
# ==================== 阶段5:部署应用 ====================
# 在本地部署Flask应用
deploy_flask_local:
       stage: deploy # 绑定到deploy阶段
tags: [docker] # 使用带有docker标签的Runner执行
dependencies: [build_flask_docker] # 依赖build_flask_docker阶段成功完成
# 限制部署条件:仅在master或main分支执行
only:
      - main
script:
      # 定义容器配置变量
       - echo "===== 开始本地部署Flask应用 ====="
      - CONTAINER_NAME="flask-container"       # 容器名称
      - PORT_MAPPING="5000:5000" # 端口映射:主机端口:容器端口
      # 停止并删除已存在的同名容器(避免端口冲突)
      - echo "===== 停止并删除已存在的同名容器(避免端口占用/冲突) ====="
      - docker stop ${CONTAINER_NAME} || true # 如果容器不存在,忽略错误
      - docker rm ${CONTAINER_NAME} || true # 如果容器不存在,忽略错误
      # 使用构建的镜像启动新容器
      - echo "===== 本地启动Docker容器 ====="
      - docker run -d --name ${CONTAINER_NAME} -p        ${PORT_MAPPING} flask-app:latest
       # 验证容器运行状态
      - echo "===== 验证容器运行状态 ====="
      - docker ps | grep ${CONTAINER_NAME} # 查找运行中的容器
      # 打印访问地址信息
      - echo "===== 打印应用访问地址 ====="
      - LOCAL_IP=$(hostname -I | awk '{print $1}')        # 获取本机局域网IP
      - echo "======================================"
      - echo "Flask应用本地部署成功!"
      - echo "本地访问地址:http://localhost:5000"
      - echo "局域网访问地址:http://${LOCAL_IP}:5000"
       - echo "容器名称:${CONTAINER_NAME}"
       - echo "镜像名称:flask-app:latest"

 

代码扫描规则的文件 semgrep-rules/custom-python-rules.yml(可根据实际情况自定义)

rules:
- id: insecure-eval-use
   patterns:
   - pattern: eval($VAR)
   - pattern-not: eval("...")
   fix: secure_eval($VAR)
   message: Calling 'eval' with user input
   languages: [python]
   severity: MEDIUM
   - id: custom-flask-hardcoded-secret
    pattern: HARDCODED_SECRET_KEY = "flask_secret_123456_unsafe"
   message: "自定义规则:检测到Flask硬编码敏感密钥,存在信息泄露风险(对应Bandit B105)"
    severity: LOW
   languages: [python]
   metadata:
      category: security
      cwe: "CWE-798: Use of Hard-coded Credentials"
       bandit_id: B105
# 规则3:自定义Flask绑定所有接口扫描(已包含pattern,符合schema规范)
- id: custom-flask-bind-all-interfaces
    pattern: app.run(host='0.0.0.0', port=5000, debug=True)
    message: "自定义规则:检测到Flask绑定所有网络接口,可能导致未授权访问(对应Bandit B104)"
   severity: MEDIUM
   languages: [python]
    metadata:
       category: security
      cwe: "CWE-605: Multiple Binds to the Same Port"
      bandit_id: B104

 

构建镜像Dockerfile文件

# 基础镜像
FROM python:3.9-slim
# 工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用源码
COPY app.py .
# 暴露端口
EXPOSE 5000
# 启动命令
CMD ["python", "app.py"]

 

确保依赖的命令和配置文件验证正常后,可触发流水线

三、触发构建

Gitlab CICD 5个阶段可以在流水看到分成5个作业执行,下面是具体过程截图

代码扫描日志,正常扫描到代码bug

浏览器验证:浏览器展示是app.py的代码信息

流水线构建的结果,有日志和扫描报告,可实现问题追溯、复盘、定位和持续优化

结果说明:设定的几个bug是可以配置是否拦截中断构建过程的,这里为了测试bug扫描的过程,设定允许失败继续构建的,代码bug不影响构建和结果,只是有潜在漏洞风险。

附镜像扫描报告

四、总结

1. 左移安全,提前拦截风险,大幅降低线上整改成本

2. 全链路层层验证,提升部署成功率,减少线上故障

3. 全程自动化,减少人工干预,提升研发部署效率

4. 标准化流程,保障环境一致性,解决「本地能跑,线上不能跑」的痛点

5. 可追溯、可复盘,便于问题定位和持续优化

核心优点是 全链路、自动化、标准化、安全化,既实现了从代码到容器的全流程验证和部署,又提前拦截了安全风险和运行故障,大幅提升了部署成功率和研发效率,同时保障了环境一致性和业务连续性。

   
4   次浏览       1 次
相关文章

DevOps转型融入到企业文化
DevOps 能力模型、演进及案例剖析
基于 DevOps 理念的私有 PaaS 平台实践
微软开发团队的DevOps实践启示
相关文档

DevOps驱动应用运维变革与创新
运维管理规划
如何实现企业应用部署自动化
运维自动化实践之路
相关课程

自动化运维工具(基于DevOps)
互联网运维与DevOps
MySQL性能优化及运维培训
IT系统运维管理

最新活动计划
UAF架构体系与实践 7-23[北京]
SysML和EA系统设计与建模 7-16[深圳]
Spec 驱动开发(SDD)实战 7-28[北京]
AI辅助软件测试方法与实践 7-31[在线]
AI智能体开发技术实践 8-6[上海]
基于UML和EA系统分析设计 8-20[上海]
 
 
最新文章
DevOps 道法术器,立体化实施框架
DevOps 中高效测试基础架构的最佳实践
DevOps 在公司项目中的实践落地
如何基于 Kubernetes 构建完整的 DevOps 流水线
阿里云Kubernetes实战
最新课程
DevOps体系实践、工具与平台
基于Kubernetes的DevOps实践
互联网运维与DevOps
基于Kubernetes构建企业容器云
企业级DevOps工作体系与平台
更多...   
成功案例
北京 DevOps体系实践、工具与平台
神龙汽车 DevOps体系实践、工具与平台
中国移动通信 网络规划与管理
某航空公司 IT规划与企业架构
某金融公司 IT服务管理(ITIL V3)
更多...