返回博客

在CI/CD流水线中集成代理:GitHub Actions、GitLab和Jenkins的设置

开发者的完整指南:在CI/CD管道中集成代理,设置GitHub Actions、GitLab CI、Jenkins,包含代码示例和常见问题解决方案。

📅2026年2月17日
```html

在自动化部署和测试过程中,通常需要在 CI/CD 流程中使用代理服务器。这可能与企业安全政策、地理位置功能的测试或在下载依赖项时绕过速率限制有关。在本指南中,我们将探讨如何为流行的 CI/CD 平台设置代理,并提供现成的配置示例。

为什么在 CI/CD 流程中需要代理

在自动化部署过程中使用代理服务器可以解决几个关键问题。首先,许多企业网络要求所有出站流量通过企业代理进行安全控制和日志记录。如果没有正确配置,CI/CD 管道将无法下载依赖项或连接到外部服务。

其次,在测试具有地理位置逻辑的应用程序时,需要从不同国家检查其工作情况。例如,如果您正在开发一个具有区域内容或定价的服务,自动化测试必须模拟来自不同位置的用户。在这里,住宅代理 提供来自所需地区的 IP 地址。

第三个原因是绕过速率限制和封锁。在频繁运行管道时,尤其是在大型团队中,CI/CD 服务器可能会受到外部服务 API 的限制。例如,GitHub API 或包注册表在超过请求限制时可能会暂时阻止 IP。代理轮换有助于分散负载。

重要: 对于 CI/CD 流程,连接的稳定性至关重要。使用正常运行时间不低于 99.5% 且响应时间快(少于 200 毫秒)的代理。不稳定的代理会导致构建意外失败,并浪费团队的时间进行调查。

在 GitHub Actions 中设置代理

GitHub Actions 是最流行的 CI/CD 平台之一。这里的代理设置通过环境变量完成,可以在工作流或整个组织的级别上设置。我们将探讨几种集成方法。

通过环境变量进行基本设置

最简单的方法是在作业开始时设置 HTTP_PROXY 和 HTTPS_PROXY 环境变量。大多数工具(curl、wget、npm、pip)会自动使用这些变量:

name: CI with Proxy

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    
    env:
      HTTP_PROXY: http://proxy.example.com:8080
      HTTPS_PROXY: http://proxy.example.com:8080
      NO_PROXY: localhost,127.0.0.1,.internal.domain
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm install
      
      - name: Run tests
        run: npm test

NO_PROXY 变量至关重要——它将本地地址和内部服务排除在代理之外。如果没有它,可能会出现连接到 localhost 或内部 Docker 容器的问题。

通过 GitHub Secrets 安全存储凭据

如果代理需要身份验证,请不要在工作流文件中以明文形式存储用户名和密码。请使用 GitHub Secrets:

name: CI with Authenticated Proxy

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Configure Proxy
        run: |
          echo "HTTP_PROXY=http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}" >> $GITHUB_ENV
          echo "HTTPS_PROXY=http://${{ secrets.PROXY_USER }}:${{ secrets.PROXY_PASS }}@${{ secrets.PROXY_HOST }}:${{ secrets.PROXY_PORT }}" >> $GITHUB_ENV
          echo "NO_PROXY=localhost,127.0.0.1" >> $GITHUB_ENV
      
      - name: Test proxy connection
        run: curl -I https://api.github.com
      
      - name: Install dependencies
        run: npm ci

在存储库设置中创建 secrets:Settings → Secrets and variables → Actions → New repository secret。添加 PROXY_USER、PROXY_PASS、PROXY_HOST 和 PROXY_PORT。这些值将被加密,并且在日志中不可用。

为特定步骤设置代理

有时只需要在特定操作中使用代理,例如仅在下载依赖项时,而不是在部署时。在特定步骤的级别上设置变量:

steps:
  - name: Download dependencies via proxy
    env:
      HTTP_PROXY: http://proxy.example.com:8080
      HTTPS_PROXY: http://proxy.example.com:8080
    run: npm install
  
  - name: Deploy without proxy
    run: ./deploy.sh

与 GitLab CI/CD 集成代理

GitLab CI/CD 提供了多个级别的代理设置:在 runner 级别、项目级别和特定作业级别。选择取决于代理是否需要用于所有项目或仅用于特定项目。

在 GitLab Runner 级别设置代理

如果使用自托管的 GitLab Runner 并且所有项目都必须通过代理工作,请在 runner 的配置中进行设置。编辑文件 /etc/gitlab-runner/config.toml

[[runners]]
  name = "docker-runner"
  url = "https://gitlab.com/"
  token = "YOUR_TOKEN"
  executor = "docker"
  
  [runners.docker]
    image = "alpine:latest"
    privileged = false
    
  [runners.docker.services_environment]
    HTTP_PROXY = "http://proxy.example.com:8080"
    HTTPS_PROXY = "http://proxy.example.com:8080"
    NO_PROXY = "localhost,127.0.0.1,.gitlab.com"

修改配置后,重启 runner:sudo gitlab-runner restart。现在该 runner 上的所有作业将自动使用代理。

通过 .gitlab-ci.yml 设置代理

要在特定项目级别设置代理,请在 .gitlab-ci.yml 文件中使用变量。这是一种更灵活的方法,允许不同项目使用不同的代理:

variables:
  HTTP_PROXY: "http://proxy.example.com:8080"
  HTTPS_PROXY: "http://proxy.example.com:8080"
  NO_PROXY: "localhost,127.0.0.1,.internal"

stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - echo "Proxy configured: $HTTP_PROXY"
    - npm install
    - npm run build
  artifacts:
    paths:
      - dist/

test:
  stage: test
  script:
    - npm test
  dependencies:
    - build

使用 GitLab CI/CD Variables 存储凭据

为了存储敏感数据,请在项目设置中使用 CI/CD Variables:Settings → CI/CD → Variables。创建受保护和掩码变量:

  • PROXY_URL — 包含凭据的完整 URL(掩码)
  • PROXY_HOST — 代理服务器的主机
  • PROXY_PORT — 端口
  • PROXY_USERPROXY_PASS — 用于单独存储

然后在 .gitlab-ci.yml 中使用它们:

build:
  stage: build
  before_script:
    - export HTTP_PROXY="http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}"
    - export HTTPS_PROXY="http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}"
  script:
    - npm install
    - npm run build

在 Jenkins 中配置代理

Jenkins 提供了多种设置代理的方法,具体取决于架构:Jenkins master 的全局设置、特定代理的设置或单个管道的设置。

Jenkins 的全局代理设置

要设置 Jenkins 用于插件更新和其他内部操作的代理,请转到 Manage Jenkins → Manage Plugins → Advanced。在 HTTP Proxy Configuration 部分中指定:

  • Server: proxy.example.com
  • Port: 8080
  • User name 和 Password(如果需要身份验证)
  • No Proxy Host: localhost,127.0.0.1,.internal

此设置仅影响 Jenkins 本身,而不影响作业。作业需要单独配置。

为 Jenkins Pipeline 设置代理

在 Jenkinsfile 中,可以为整个管道或特定阶段设置环境变量:

pipeline {
    agent any
    
    environment {
        HTTP_PROXY = 'http://proxy.example.com:8080'
        HTTPS_PROXY = 'http://proxy.example.com:8080'
        NO_PROXY = 'localhost,127.0.0.1,.internal'
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }
        
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
    }
}

使用 Jenkins Credentials 存储代理凭据

为了安全存储代理凭据,请使用 Jenkins Credentials Store。在 Manage Jenkins → Manage Credentials 中创建类型为“Username with password”的凭据,然后在管道中使用它们:

pipeline {
    agent any
    
    stages {
        stage('Build with Authenticated Proxy') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'proxy-credentials',
                    usernameVariable: 'PROXY_USER',
                    passwordVariable: 'PROXY_PASS'
                )]) {
                    sh '''
                        export HTTP_PROXY="http://${PROXY_USER}:${PROXY_PASS}@proxy.example.com:8080"
                        export HTTPS_PROXY="http://${PROXY_USER}:${PROXY_PASS}@proxy.example.com:8080"
                        npm install
                    '''
                }
            }
        }
    }
}

为 Jenkins 代理设置代理

如果使用单独的 Jenkins 代理(节点),请为每个代理单独设置代理。在代理的配置中(Manage Jenkins → Manage Nodes → Configure)添加环境变量:

HTTP_PROXY=http://proxy.example.com:8080
HTTPS_PROXY=http://proxy.example.com:8080
NO_PROXY=localhost,127.0.0.1

CI/CD 中的 Docker 代理

Docker 是现代 CI/CD 流程中不可或缺的一部分。为 Docker 设置代理有其特殊性,因为需要为 Docker daemon 和容器设置代理。

为 Docker daemon 设置代理

为了让 Docker daemon 能够通过代理下载镜像,请创建 systemd drop-in 文件。在 Linux 系统上创建目录和文件:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf

添加以下内容:

[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.internal,docker.io"

重新加载配置并重启 Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker

在构建期间为容器设置代理

如果容器在构建期间需要通过代理访问(例如,安装包),请通过 build args 在 Dockerfile 中传递变量:

FROM node:18-alpine

ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}
ENV NO_PROXY=${NO_PROXY}

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .

# 在运行时删除代理变量
ENV HTTP_PROXY=
ENV HTTPS_PROXY=

CMD ["npm", "start"]

在 CI/CD 管道中传递 build args:

# GitHub Actions
- name: Build Docker image with proxy
  run: |
    docker build \
      --build-arg HTTP_PROXY=${{ secrets.PROXY_URL }} \
      --build-arg HTTPS_PROXY=${{ secrets.PROXY_URL }} \
      --build-arg NO_PROXY=localhost,127.0.0.1 \
      -t myapp:latest .

# GitLab CI
docker build:
  script:
    - docker build 
        --build-arg HTTP_PROXY="${PROXY_URL}"
        --build-arg HTTPS_PROXY="${PROXY_URL}"
        -t myapp:latest .

使用 Docker Compose 设置代理

在 CI/CD 中使用 Docker Compose 时,通过 docker-compose.yml 中的 environment 设置代理:

version: '3.8'

services:
  app:
    build:
      context: .
      args:
        - HTTP_PROXY=${HTTP_PROXY}
        - HTTPS_PROXY=${HTTPS_PROXY}
    environment:
      - HTTP_PROXY=${HTTP_PROXY}
      - HTTPS_PROXY=${HTTPS_PROXY}
      - NO_PROXY=localhost,127.0.0.1
    ports:
      - "3000:3000"

为包管理器设置代理

包管理器通常需要额外的代理设置,特别是如果使用自己的配置文件。我们将探讨流行包管理器的设置。

NPM 和 Yarn

NPM 可以使用 HTTP_PROXY/HTTPS_PROXY 环境变量,也可以使用自己的配置。要在 CI/CD 中明确设置:

# 在 GitHub Actions 或 GitLab CI 中
- name: Configure npm proxy
  run: |
    npm config set proxy http://proxy.example.com:8080
    npm config set https-proxy http://proxy.example.com:8080
    npm config set noproxy "localhost,127.0.0.1"

- name: Install dependencies
  run: npm install

# 对于 Yarn
- name: Configure yarn proxy
  run: |
    yarn config set proxy http://proxy.example.com:8080
    yarn config set https-proxy http://proxy.example.com:8080

另一种方法是在项目根目录创建 .npmrc 文件(但不要提交凭据!):

# .npmrc(在 CI 中生成)
proxy=http://proxy.example.com:8080
https-proxy=http://proxy.example.com:8080
noproxy=localhost,127.0.0.1

Python pip 和 Poetry

Pip 使用环境变量,但也可以通过配置进行设置:

# 通过环境变量(推荐用于 CI)
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
pip install -r requirements.txt

# 或通过 pip 参数
pip install --proxy http://proxy.example.com:8080 -r requirements.txt

# 对于 Poetry
poetry config http-basic.proxy http://proxy.example.com:8080
poetry install

Maven 和 Gradle

对于 Java 项目,代理设置需要创建配置文件。对于 Maven,在 CI 管道中创建 settings.xml:

- name: Configure Maven proxy
  run: |
    mkdir -p ~/.m2
    cat > ~/.m2/settings.xml << EOF
    <settings>
      <proxies>
        <proxy>
          <id>http-proxy</id>
          <active>true</active>
          <protocol>http</protocol>
          <host>proxy.example.com</host>
          <port>8080</port>
          <nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
        </proxy>
      </proxies>
    </settings>
    EOF

- name: Build with Maven
  run: mvn clean install

对于 Gradle,将设置添加到 gradle.properties:

systemProp.http.proxyHost=proxy.example.com
systemProp.http.proxyPort=8080
systemProp.https.proxyHost=proxy.example.com
systemProp.https.proxyPort=8080
systemProp.http.nonProxyHosts=localhost|127.0.0.1

安全存储代理凭据

存储代理凭据是 CI/CD 安全的关键方面。这些数据的泄露可能导致代理的未经授权使用和财务损失。我们将探讨不同平台的最佳实践。

GitHub Actions Secrets

GitHub Actions 提供了三种级别的秘密:repository、environment 和 organization。对于代理凭据,请使用:

  • Repository secrets — 仅在一个存储库中需要代理的项目
  • Organization secrets — 如果一个代理在组织的所有项目中使用
  • Environment secrets — 用于 staging/production 环境中的不同代理

重要的安全规则:

  • 永远不要在日志中输出秘密:GitHub 会自动掩盖它们,但最好避免 echo
  • 为不同的环境使用不同的凭据
  • 定期轮换代理密码(至少每 90 天一次)
  • 通过分支保护规则限制对秘密的访问

GitLab CI/CD Variables

GitLab 提供了额外的变量保护选项:

  • Protected — 变量仅在受保护的分支(main、production)中可用
  • Masked — 值在日志中自动隐藏
  • Environment scope — 限制在特定环境中使用

推荐的代理凭据配置:

# Settings → CI/CD → Variables
PROXY_USER: myuser (Protected: Yes, Masked: Yes)
PROXY_PASS: secret123 (Protected: Yes, Masked: Yes)
PROXY_HOST: proxy.example.com (Protected: No, Masked: No)
PROXY_PORT: 8080 (Protected: No, Masked: No)

Jenkins Credentials Store

Jenkins Credentials Store 支持多种凭据存储类型。对于代理,建议:

  • 使用“Username with password”存储代理的用户名/密码
  • 为不同团队/项目设置 Folder-level credentials
  • 启用 Credentials Binding Plugin 以安全地在 Pipeline 中使用
  • 设置审计日志以跟踪凭据的使用

外部秘密管理系统

对于企业环境,建议使用专门的秘密管理系统:HashiCorp Vault、AWS Secrets Manager、Azure Key Vault 或 Google Secret Manager。以下是与 HashiCorp Vault 在 GitHub Actions 中集成的示例:

- name: Import Secrets from Vault
  uses: hashicorp/vault-action@v2
  with:
    url: https://vault.example.com
    token: ${{ secrets.VAULT_TOKEN }}
    secrets: |
      secret/data/proxy proxy_user | PROXY_USER ;
      secret/data/proxy proxy_pass | PROXY_PASS ;
      secret/data/proxy proxy_host | PROXY_HOST

- name: Configure Proxy
  run: |
    export HTTP_PROXY="http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:8080"
    npm install

解决常见问题

在 CI/CD 中集成代理时,常常会遇到相同的问题。我们将探讨最常见的问题及其解决方案。

问题:加载依赖项时连接超时

症状: npm install、pip install 或 docker pull 在 30-60 秒后以超时错误结束。

原因:

  • 代理服务器不可用或过载
  • 代理 URL 格式不正确(开头忘记加 http://)
  • 代理需要身份验证,但未传递凭据
  • 防火墙阻止了 CI/CD runner 与代理的连接

解决方案:

# 1. 检查代理的可用性
- name: Test proxy connectivity
  run: |
    curl -v -x http://proxy.example.com:8080 https://www.google.com
    echo "Proxy test completed"

# 2. 增加 npm 的超时
- name: Install with increased timeout
  run: |
    npm config set fetch-timeout 300000
    npm install

# 3. 检查 URL 格式
- name: Debug proxy configuration
  run: |
    echo "HTTP_PROXY: $HTTP_PROXY"
    echo "HTTPS_PROXY: $HTTPS_PROXY"
    # 应该是:http://user:pass@host:port

问题:SSL 证书验证失败

症状: 出现“SSL certificate problem: unable to get local issuer certificate”或“CERT_UNTRUSTED”之类的错误。

原因: 企业代理通常执行 SSL 检查,替换证书。CI/CD runner 不信任企业 CA。

解决方案:

# 选项 1:添加企业 CA 证书
- name: Install corporate CA certificate
  run: |
    sudo cp corporate-ca.crt /usr/local/share/ca-certificates/
    sudo update-ca-certificates

# 选项 2:禁用 SSL 验证(不推荐用于生产!)
- name: Install with SSL verification disabled
  run: |
    npm config set strict-ssl false
    npm install
  env:
    NODE_TLS_REJECT_UNAUTHORIZED: 0

# 选项 3:仅对 HTTP 使用代理,HTTPS 直接连接
- name: Selective proxy usage
  run: npm install
  env:
    HTTP_PROXY: http://proxy.example.com:8080
    # 不设置 HTTPS_PROXY

警告: 禁用 SSL 证书验证会带来严重的安全风险。仅在内部企业网络中使用此方法,并确保将企业 CA 添加到受信任的列表中。

问题:代理对某些命令有效,但对其他命令无效

症状: npm install 通过代理工作,但 git clone 或 docker pull 忽略代理设置。

原因: 不同工具使用不同的代理设置机制。Git 和 Docker 有自己的配置文件。

解决方案:

# 配置 Git 代理
- name: Configure Git proxy
  run: |
    git config --global http.proxy http://proxy.example.com:8080
    git config --global https.proxy http://proxy.example.com:8080

# 配置 Docker 代理(参见上面的 Docker 部分)
# 对于 wget/curl
- name: Configure wget/curl
  run: |
    echo "use_proxy = on" >> ~/.wgetrc
    echo "http_proxy = http://proxy.example.com:8080" >> ~/.wgetrc
    echo "https_proxy = http://proxy.example.com:8080" >> ~/.wgetrc

问题:启用代理后内部服务不可用

症状: 在设置代理后,无法连接到 localhost、内部 Docker 容器或企业服务。

原因: NO_PROXY 变量设置不正确,所有请求都通过代理,包括本地请求。

解决方案:

# 正确设置 NO_PROXY
env:
  HTTP_PROXY: http://proxy.example.com:8080
  HTTPS_PROXY: http://proxy.example.com:8080
  NO_PROXY: |
    localhost,
    127.0.0.1,
    0.0.0.0,
    .internal,
    .local,
    .corp.example.com,
    docker.internal,
    host.docker.internal

# 对于 Docker Compose 也添加
services:
  app:
    environment:
      - NO_PROXY=localhost,127.0.0.1,db,redis
      # db 和 redis 是 compose 中其他服务的名称

问题:代理凭据出现在日志中

症状: CI/CD 日志中明文显示代理密码。

原因: 通过 echo 或命令的详细模式输出环境变量。

解决方案:

# ❌ 不好 - 日志中的凭据
- name: Debug proxy
  run: |
    echo "Proxy: $HTTP_PROXY"  # 会显示 http://user:pass@host:port
    curl -v ...  # 详细模式显示凭据

# ✅ 好 - 安全输出
- name: Debug proxy (safe)
  run: |
    echo "Proxy host configured: $(echo $HTTP_PROXY | cut -d'@' -f2)"
    # 只会显示 host:port
    
# 使用 secrets 进行掩码
- name: Configure proxy
  env:
    PROXY_URL: ${{ secrets.PROXY_URL }}  # GitHub 会自动掩码
  run: |
    export HTTP_PROXY="$PROXY_URL"

结论

在 CI/CD 管道中集成代理是自动化的重要方面,确保安全、符合企业政策并能够测试地理位置功能。在本指南中,我们探讨了如何为 GitHub Actions、GitLab CI、Jenkins、Docker 和流行的包管理器设置代理的实用方法。

设置代理时需要记住的关键点:始终通过平台内置的秘密机制安全存储凭据,正确设置 NO_PROXY 以排除本地和内部服务,在主要操作之前测试与代理的连接,并监控日志以防敏感数据泄露。对于关键的生产环境,建议使用外部秘密管理系统,如 HashiCorp Vault。

选择代理类型取决于您的需求:对于企业网络,通常使用现有的 HTTP/HTTPS 代理;对于地理位置功能的测试,适合使用 住宅代理,而对于高速下载依赖项,可以使用 数据中心代理。确保代理服务器的高正常运行时间,因为它们的不可用性将导致所有构建失败并阻碍开发团队的工作。

遇到问题时,从检查代理的基本可用性开始,使用 curl 或 wget,然后检查 URL 和凭据的格式,最后再进行特定工具的设置。大多数问题通过正确设置 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY 环境变量即可解决。

```