パイプラインが外部APIにアクセスしようとしたときに、403 ForbiddenやConnection refusedのエラーが発生しますか?おそらく、CI/CDサーバーのIPアドレスがリソース側でブロックされているためです。プロキシはこの問題を解決します。必要なIPを通じてトラフィックをルーティングし、パイプラインが正常に動作します。この記事では、GitHub Actions、GitLab CI、Jenkinsのためのステップバイステップの指示を提供します。
CI/CDにおけるプロキシの必要性: 実際のシナリオ
CI/CDパイプラインは、固定IPアドレスを持つサーバー(GitHub、GitLabのクラウドランナーや独自のJenkinsエージェント)で動作します。これらのIPはよく知られており、多くの外部サービスはそれらをブロックしたり、リクエスト数を制限したりします。以下は、プロキシが必要な具体的な状況です。
ジオ制限されたリソースへのアクセス
多くの企業のnpmレジストリ、Mavenリポジトリ、内部APIは、特定の国やIP範囲からのみアクセス可能です。GitHub Actionsランナーがターゲットサービスのファイアウォールでブロックされている地域にある場合、パイプラインは依存関係をダウンロードしたり、データを送信したりできません。必要なジオロケーションを持つプロキシがこの問題を解決します。
レート制限とIPによるブロック
GitHub ActionsのクラウドランナーはMicrosoft AzureのIPを使用しています。多くの公開APIはこれらの範囲を知っており、厳しい制限を適用するか、完全にブロックします。たとえば、公開データのパース、テスト中の外部APIへのリクエスト、制限されたCDNからの配布物のダウンロードなどは、クラウドランナーのIPのために定期的に失敗します。プロキシを通じたローテーションにより、レート制限を回避できます。
実際のウェブサイトとの統合テスト
統合テストが実際のウェブサイトやマーケットプレイス(Wildberries、Ozon、Avito、Amazon)にアクセスする場合、これらのサイトは毎回ランナーから同じIPを見てすぐにブロックします。IPローテーションを持つプロキシは、テストを安定して通過させ、CAPTCHAやブロックを回避します。
内部企業リソースへのアクセス
企業ネットワークはしばしば外部から閉ざされています。パイプラインが内部サーバーにデプロイする必要がある場合や、閉じたAPIにアクセスする必要がある場合、企業ネットワーク内のプロキシ(またはSOCKS5トンネル)がクラウドランナーと閉じたインフラストラクチャの間の橋となります。
広告およびマーケティング統合のテスト
Facebook Ads API、TikTok Ads API、Google Ads APIを使用するチームは、CI/CDを通じてキャンペーンの作成を自動化することがよくあります。これらのプラットフォームはIPに対して厳しいルールを持っており、データセンターのIPからのリクエストはブロックされるか、追加の認証を要求されることがあります。パイプライン内のレジデンシャルプロキシは、リクエストを通常のユーザートラフィックに似せます。
パイプラインに最適なプロキシの種類
プロキシの種類の選択は、タスクによって異なります。CI/CDパイプラインには、3つのオプションが関連しています。それぞれに利点と制限があります。
| プロキシの種類 | 速度 | サイトの信頼性 | 最適な用途 |
|---|---|---|---|
| データセンターのプロキシ | 非常に高い | 中程度 | 依存関係のダウンロード、内部リポジトリ、厳しいチェックのない高速API |
| レジデンシャルプロキシ | 中程度 | 高い | 実際のサイトとの統合テスト、広告API(Facebook、TikTok)、マーケットプレイス |
| モバイルプロキシ | 中程度 | 最大 | モバイルAPIのテスト、最大のアンチボット保護を持つプラットフォームでの作業 |
実践的なルール:
パッケージをダウンロードしたり、内部サービスにアクセスしたりする場合は、データセンターのプロキシを使用してください。これらは速くて安価です。実際のサイトでのテストや広告プラットフォームでの作業が必要な場合は、レジデンシャルプロキシが必要です。SOCKS5プロトコルはHTTP/HTTPSよりも好ましいです。なぜなら、非標準ポートやプロトコルとの互換性が高いからです。
GitHub Actionsでのプロキシ設定
GitHub Actionsは、現在最も人気のあるCI/CDツールです。ここでのプロキシ設定は、環境変数とリポジトリのシークレットを通じて行われます。ステップバイステップで説明します。
ステップ1: プロキシデータをリポジトリのシークレットに追加
プロキシのログイン情報やパスワードをYAMLワークフローファイルに直接書き込まないでください。GitHub Secretsを使用してください:
- リポジトリを開く → Settings → Secrets and variables → Actions
- New repository secretをクリック
- 次の形式の値を持つシークレット
PROXY_URLを作成します:http://user:[email protected]:port
ステップ2: ワークフローで環境変数を使用
ほとんどのツール(curl、wget、npm、pip、Maven)は、標準の環境変数HTTP_PROXY、HTTPS_PROXY、NO_PROXYを自動的に取得します。ワークフローの例は次のとおりです:
name: Build with Proxy
on: [push]
env:
HTTP_PROXY: ${{ secrets.PROXY_URL }}
HTTPS_PROXY: ${{ secrets.PROXY_URL }}
NO_PROXY: localhost,127.0.0.1,internal.company.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run integration tests
run: npm test
- name: Call external API
run: |
curl -v https://api.example.com/data
ステップ3: GitHub ActionsでのSOCKS5プロキシ
SOCKS5を使用する場合(ほとんどのタスクに推奨)、標準の環境変数だけでは不十分です。ローカルトンネルが必要です。proxychainsユーティリティを使用するか、microsocksを設定します:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Setup SOCKS5 proxy tunnel
run: |
sudo apt-get install -y proxychains4
echo "socks5 proxy.host 1080 user password" >> /etc/proxychains4.conf
- name: Run command through SOCKS5
run: proxychains4 curl https://restricted-resource.com/api
特定のツールのためのプロキシ設定
一部のツールはシステム変数を無視し、個別の設定を必要とします:
| ツール | プロキシの設定方法 |
|---|---|
| npm / yarn | npm config set proxy http://user:pass@host:port |
| pip (Python) | pip install --proxy http://user:pass@host:port package |
| Maven | settings.xmlの<proxies> |
| Gradle | systemProp.https.proxyHost=hostをgradle.propertiesに追加 |
| Git | git config --global http.proxy http://user:pass@host:port |
| Docker build | --build-arg HTTP_PROXY=http://user:pass@host:port |
GitLab CIでのプロキシ設定
GitLab CIは、プロジェクト、グループ、またはインスタンスレベルで環境変数を設定するいくつかのレベルを提供します。これにより、GitHub Actionsに比べてプロキシの管理がより柔軟になります。
ステップ1: GitLab CI/CD Variablesに変数を追加
- プロジェクトを開く → Settings → CI/CD → Variablesセクション
- Add variableをクリック
- タイプMasked(ログに値を隠す)で、
PROXY_URL変数を追加 - 値:
http://user:[email protected]:port
ステップ2: .gitlab-ci.ymlで変数を使用
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
NO_PROXY: "localhost,127.0.0.1,.internal.company.com"
stages:
- build
- test
- deploy
build:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
integration_tests:
stage: test
image: python:3.11
script:
- pip install -r requirements.txt
- pytest tests/integration/
deploy:
stage: deploy
script:
- curl -X POST https://api.external-service.com/deploy
-H "Authorization: Bearer $DEPLOY_TOKEN"
-d '{"version": "$CI_COMMIT_SHA"}'
特定のジョブのみにプロキシを設定
プロキシが必要ない場合(たとえば、統合テストのみに必要で、ビルドには必要ない場合)、変数を特定のジョブレベルで設定し、グローバルには設定しないでください:
integration_tests:
stage: test
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
script:
- pytest tests/integration/
build:
stage: build
# ここではプロキシが設定されていません — 直接接続
script:
- npm ci && npm run build
セルフホストのGitLab Runner: Runnerレベルでのプロキシ設定
自分のGitLab Runnerを使用している場合、Runnerの設定でプロキシをグローバルに設定できます。/etc/gitlab-runner/config.tomlファイルを開き、[runners.env]セクションに追加します:
[[runners]]
name = "my-runner"
url = "https://gitlab.com/"
token = "TOKEN"
executor = "docker"
environment = [
"HTTP_PROXY=http://user:[email protected]:port",
"HTTPS_PROXY=http://user:[email protected]:port",
"NO_PROXY=localhost,127.0.0.1"
]
これにより、このRunner上のすべてのパイプラインがプロキシを使用する必要がある場合、各.gitlab-ci.ymlにプロキシを記述する必要がなくなります。
Jenkinsでのプロキシ設定
Jenkinsは3つのツールの中で最も柔軟ですが、設定が最も複雑です。プロキシは、Jenkins全体、特定のパイプライン、または個々のステップのいずれかで設定できます。
方法1: Jenkinsのグローバルプロキシ設定
- Manage Jenkins → Systemを開く
- HTTP Proxy Configurationセクションを見つける
- サーバー、ポート、ユーザー名、パスワードのフィールドを入力
- No Proxy Hostフィールドに内部アドレスをカンマで区切って指定
- Test URLをクリックして確認し、保存
この設定は、プラグインやJenkins自体の更新のダウンロードに影響しますが、パイプラインの実行環境に自動的に引き継がれるわけではありません。パイプラインには別の設定が必要です。
方法2: Declarative Pipelineでの環境を通じたプロキシ設定
pipeline {
agent any
environment {
HTTP_PROXY = credentials('proxy-url-credential')
HTTPS_PROXY = credentials('proxy-url-credential')
NO_PROXY = 'localhost,127.0.0.1,internal.company.com'
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Integration Tests') {
steps {
sh 'pytest tests/integration/'
}
}
stage('Deploy') {
steps {
sh '''
curl -X POST https://api.external-service.com/deploy \
-H "Authorization: Bearer ${DEPLOY_TOKEN}" \
-d "version=${GIT_COMMIT}"
'''
}
}
}
}
ステップ3: Jenkins Credentialsにプロキシの認証情報を追加
- Manage Jenkins → Credentials → System → Global credentialsを開く
- Add Credentialsをクリック
- タイプ: Secret text
- ID:
proxy-url-credential - Secret:
http://user:[email protected]:port
方法3: JavaプロジェクトのためのJVMパラメータを通じたプロキシ
パイプラインがJavaプロジェクト(Maven、Gradle)をビルドする場合、システム環境変数が機能しないことがあります。JVMは独自のシステムプロパティを使用します。これらをJAVA_OPTSに追加します:
environment {
JAVA_OPTS = '-Dhttps.proxyHost=proxy.host -Dhttps.proxyPort=8080 -Dhttps.proxyUser=user -Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|127.0.0.1|*.internal.com'
}
パイプライン内のDockerコンテナ内のプロキシ
ほとんどの現代のCI/CDパイプラインは、Dockerコンテナ内でステップを実行します。コンテナにプロキシを渡すことは、いくつかの方法で解決される別のタスクです。
イメージビルド時の--build-argを通じたプロキシの渡し方
プロキシがDockerイメージのビルド中のみ必要な場合(たとえば、Dockerfile内でパッケージをインストールするため)、ビルド引数を使用します:
# .github/workflows/build.ymlまたは.gitlab-ci.ymlで
docker build \
--build-arg HTTP_PROXY=$HTTP_PROXY \
--build-arg HTTPS_PROXY=$HTTPS_PROXY \
--build-arg NO_PROXY=$NO_PROXY \
-t myapp:latest .
# Dockerfileで
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=$HTTP_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY
ENV NO_PROXY=$NO_PROXY
RUN apt-get update && apt-get install -y curl
RUN npm ci
⚠️ 注意: イメージビルド時のセキュリティ
ARGやENVをDockerfileで設定した変数は、イメージのメタデータに保存され、docker inspectで見ることができます。プロキシが認証を必要とする場合、完成したイメージが公開レジストリに公開されないようにしてください。そうでないと、認証情報が公開されてしまいます。
Dockerデーモンのプロキシのグローバル設定
セルフホストのランナーでは、Dockerデーモン全体にプロキシを設定できます。これにより、すべてのコンテナがDockerfileの変更なしに自動的にプロキシを取得します:
# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://user:[email protected]:port"
Environment="HTTPS_PROXY=http://user:[email protected]:port"
Environment="NO_PROXY=localhost,127.0.0.1,registry.internal.com"
# 変更を適用するには:
# systemctl daemon-reload
# systemctl restart docker
セキュリティ: プロキシの認証情報を保存する方法
プロキシの認証情報は、APIキーやデータベースのパスワードと同様の秘密です。それらが漏洩すると、誰でもあなたのプロキシをあなたの費用で使用できるようになります。安全に保存するためのルールは次のとおりです:
セキュリティチェックリスト
- ✅ 絶対にプロキシのログイン/パスワードをパイプラインのYAMLファイルに直接書き込まないでください
- ✅ GitLabではMasked variablesを使用し、GitHubではEncrypted secretsを使用してください — これらはログに隠されます
- ✅ Jenkinsでは、Credentials StoreでSecret textまたはUsername with passwordタイプを使用してください
- ✅ 内部アドレスに対して
NO_PROXYを追加してください — 自社のインフラストラクチャへのトラフィックはプロキシを通るべきではありません - ✅ プロキシのパスワードを定期的にローテーションしてください — 秘密のストレージでのみ更新し、パイプラインのコードは変更しないでください
- ✅ プロキシのIP認証を使用してください(ランナーのIPをホワイトリストに追加) — これはパスワードよりも信頼性があります
- ✅ 異常な活動についてプロキシのログを確認してください
プロキシのURL形式: どこに何を挿入するか
| プロトコル | URL形式 | 使用するタイミング |
|---|---|---|
| HTTP | http://user:pass@host:port |
ほとんどのツール、npm、pip、curl |
| HTTPS | https://user:pass@host:port |
プロキシサーバーとの暗号化接続 |
| SOCKS5 | socks5://user:pass@host:port |
非標準ポート、UDPトラフィック、最大の互換性 |
よくあるエラーとその修正方法
正しく設定されていても、問題が発生することがあります。以下は最も一般的なエラーとその解決策です:
エラー: Proxy Authentication Required (407)
原因: 無効なログインまたはパスワード、またはツールによって送信されていない可能性があります。
解決策: URLの形式を確認してください — パスワード内の特殊文字はURLエンコードする必要があります。たとえば、p@ss#word → p%40ss%23word。また、環境変数が実際にステップに渡されていることを確認してください — echo $HTTP_PROXY(最初の数文字)を出力して確認します。
エラー: SSL Certificate Verification Failed
原因: プロキシがSSLインスペクション(MITM)を実行し、証明書を置き換えています。クライアントはプロキシの証明書を信頼していません。
解決策: プロキシのルート証明書を信頼されたものに追加します。curlの場合: --cacert /path/to/proxy-ca.crt。npmの場合: npm config set cafile /path/to/proxy-ca.crt。または、SSLインスペクションなしのプロキシを使用します — CI/CDにはこちらが好ましいです。
エラー: Connection Timeout through proxy
原因: プロキシサーバーがランナーのIPからアクセスできないか、ポートがファイアウォールでブロックされています。
解決策: パイプラインのステップでnc -zv proxy.host portコマンドを使用してプロキシの可用性を確認します。ランナーのIPがプロキシプロバイダーのホワイトリストに追加されていることを確認してください(IP認証を使用している場合)。GitHub ActionsのクラウドランナーのIP範囲はmeta.github.comで公開されています。
エラー: ツールがHTTP_PROXY変数を無視する
原因: 一部のツール(特にJavaベースのもの)は、システム環境変数を読み取らないことがあります。
解決策: 特定のツールのためのネイティブプロキシ設定を使用します(上記の表を参照)。Javaの場合は、JAVA_OPTSを通じてJVMプロパティを追加します。curlの場合は、-x http://proxy:portフラグを明示的に使用します。
エラー: 内部サービスもプロキシを通る
原因: NO_PROXYが設定されていないか、誤って設定されています。
解決策:すべての内部ドメインとIPをNO_PROXYに指定します。ドメインにはワイルドカードを使用します: NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.company.com。注意: 一部のツールはCIDR表記をサポートしていますが、他のツールは正確なドメインのみをサポートしています。
結論
CI/CDパイプラインでのプロキシ設定は、一度限りのタスクではなく、自動化の正しいアーキテクチャの一部です。私たちは、GitHub Actions(Secretsと環境変数を通じて)、GitLab CI(マスキングされたVariablesを通じて)、Jenkins(Credentials StoreとDeclarative Pipelineを通じて)という3つの主要なツールを説明しました。すべてに共通する重要な原則は、コードに認証情報を保存しないこと、内部アドレスに対してNO_PROXYを使用すること、特定のタスクに応じたプロキシの種類を選択することです。
正しいプロキシの種類を選択することは、パイプラインの安定性にとって非常に重要です。依存関係のダウンロードや標準APIへのアクセスには、高速なデータセンターのプロキシで十分です。しかし、パイプラインが実際のサイトでの統合テストを実施したり、広告プラットフォーム(Facebook Ads API、TikTok Ads API)で作業したり、マーケットプレイスにアクセスしたりする場合は、レジデンシャルプロキシを使用してください。これらのIPは通常のユーザートラフィックとして認識され、ブロックやレート制限にかかることは非常に稀です。
重要なルールは、パイプラインの最初のステップでプロキシをテストすることです。これにより、問題を迅速に診断し、長いビルドの最後でエラーを探す時間を無駄にしないことができます。プロキシ設定の直後にcurl -v https://api.ipify.orgステップを追加してください。これにより、リクエストが送信されるIPが表示され、プロキシが正しく機能していることが確認できます。