بازگشت به وبلاگ

پروکسی برای پایپ‌لاین‌های CI/CD: تنظیم GitHub Actions، GitLab CI و Jenkins برای دسترسی به منابع خصوصی

راهنمای کامل تنظیم پروکسی در پایپ‌لاین‌های CI/CD: GitHub Actions، GitLab CI و Jenkins. چگونه از مسدودسازی‌های جغرافیایی عبور کنیم، به API‌های بسته دسترسی پیدا کنیم و ساخت را از طریق پروکسی تسریع کنیم.

📅۲۶ اردیبهشت ۱۴۰۵
```html

آیا خط لوله شما با خطای 403 Forbidden یا Connection refused هنگام تلاش برای دسترسی به API خارجی یا دانلود وابستگی مواجه می‌شود؟ احتمالاً مشکل این است که آدرس IP سرور CI/CD شما در سمت منبع مسدود شده است. پروکسی این مشکل را حل می‌کند: شما ترافیک را از طریق IP مورد نظر مسیریابی می‌کنید و خط لوله بدون مشکل کار می‌کند. در این مقاله — دستورالعمل‌های مرحله به مرحله برای GitHub Actions، GitLab CI و Jenkins.

چرا پروکسی در CI/CD: سناریوهای واقعی

خطوط لوله CI/CD بر روی سرورهایی با آدرس‌های IP ثابت — رنرهای ابری GitHub، GitLab یا بر روی عوامل Jenkins خودتان کار می‌کنند. این IP‌ها به خوبی شناخته شده‌اند و بسیاری از خدمات خارجی یا آنها را مسدود می‌کنند یا تعداد درخواست‌ها را محدود می‌کنند. در اینجا سناریوهای خاصی وجود دارد که بدون پروکسی نمی‌توان از آنها عبور کرد:

دسترسی به منابع جغرافیایی محدود

بسیاری از ثبت‌نام‌های npm شرکتی، مخازن Maven و API‌های داخلی تنها از کشورهای خاص یا دامنه‌های IP قابل دسترسی هستند. اگر رنر GitHub Actions شما در منطقه‌ای باشد که در سطح firewall سرویس هدف مسدود شده است، خط لوله نمی‌تواند وابستگی‌ها را دانلود کند یا داده‌ها را ارسال کند. پروکسی با موقعیت جغرافیایی مناسب این مشکل را بدون تغییر زیرساخت حل می‌کند.

محدودیت نرخ و مسدودیت‌های IP

رنرهای ابری GitHub Actions از IP‌های موجود در دامنه‌های Microsoft Azure استفاده می‌کنند. بسیاری از API‌های عمومی این دامنه‌ها را می‌شناسند و محدودیت‌های سختی را بر روی آنها اعمال می‌کنند — یا به طور کامل مسدود می‌شوند. به عنوان مثال، تجزیه داده‌های عمومی، درخواست‌ها به API‌های خارجی در حین تست، دانلود توزیع‌ها از CDN‌های محدود — همه اینها به طور منظم به دلیل IP‌های رنرهای ابری خراب می‌شوند. چرخش از طریق پروکسی اجازه می‌دهد تا از محدودیت نرخ عبور کنیم.

تست یکپارچه‌سازی با وب‌سایت‌های واقعی

اگر تست‌های یکپارچه‌سازی شما به وب‌سایت‌های واقعی یا بازارها (Wildberries، Ozon، Avito، Amazon) مراجعه می‌کنند، این وب‌سایت‌ها هر بار که اجرا می‌شوند، یک IP مشابه از رنر را مشاهده می‌کنند و به سرعت آن را مسدود می‌کنند. پروکسی با چرخش IP اجازه می‌دهد تا تست‌ها به طور پایدار بدون CAPTCHA و مسدودیت‌ها انجام شوند.

دسترسی به منابع داخلی شرکتی

شبکه‌های شرکتی اغلب از دنیای خارجی بسته هستند. اگر خط لوله باید بر روی سرور داخلی مستقر شود یا به API بسته مراجعه کند، پروکسی (یا تونل SOCKS5) درون شبکه شرکتی به عنوان پلی بین رنر ابری و زیرساخت بسته عمل می‌کند.

تست ادغام تبلیغاتی و بازاریابی

تیم‌هایی که با API تبلیغات Facebook، API تبلیغات TikTok یا API تبلیغات Google کار می‌کنند، اغلب ایجاد کمپین‌ها را از طریق CI/CD خودکار می‌کنند. این پلتفرم‌ها قوانین سختی در مورد IP دارند: درخواست‌ها از IP‌های مراکز داده ممکن است مسدود شوند یا نیاز به تأیید اضافی داشته باشند. پروکسی‌های مقیم در خط لوله درخواست‌ها را شبیه به ترافیک کاربر عادی می‌کنند.

کدام نوع پروکسی برای خط لوله انتخاب کنیم

انتخاب نوع پروکسی بستگی به وظیفه دارد. برای خطوط لوله CI/CD سه گزینه مرتبط وجود دارد — هر کدام مزایا و محدودیت‌های خود را دارند:

نوع پروکسی سرعت اعتماد سایت‌ها بهترین برای
پروکسی‌های دیتاسنتر بسیار بالا متوسط دانلود وابستگی‌ها، مخازن داخلی، API‌های سریع بدون بررسی‌های سخت
پروکسی‌های مقیم متوسط بالا تست‌های یکپارچه‌سازی با وب‌سایت‌های واقعی، API‌های تبلیغاتی (Facebook، TikTok)، بازارها
پروکسی‌های موبایل متوسط حداکثر تست‌های API موبایل، کار با پلتفرم‌هایی با حداکثر حفاظت‌های ضد ربات

قاعده عملی:

اگر وظیفه دانلود بسته‌ها یا دسترسی به سرویس داخلی است، از پروکسی‌های دیتاسنتر استفاده کنید — آنها سریع و ارزان‌تر هستند. اگر وظیفه تست در وب‌سایت‌های واقعی یا کار با پلتفرم‌های تبلیغاتی است — به پروکسی‌های مقیم نیاز دارید. پروتکل SOCKS5 نسبت به HTTP/HTTPS ترجیح داده می‌شود، زیرا با پورت‌ها و پروتکل‌های غیر استاندارد بهتر کار می‌کند.

تنظیم پروکسی در GitHub Actions

GitHub Actions — محبوب‌ترین ابزار CI/CD در حال حاضر است. تنظیم پروکسی در اینجا از طریق متغیرهای محیطی و رازهای مخزن انجام می‌شود. بیایید مرحله به مرحله بررسی کنیم.

مرحله 1: افزودن اطلاعات پروکسی به رازهای مخزن

هرگز نام کاربری و رمز عبور پروکسی را مستقیماً در فایل YAML workflow وارد نکنید. از رازهای GitHub استفاده کنید:

  1. مخزن را باز کنید → تنظیماترازها و متغیرهاعملیات
  2. روی راز جدید مخزن کلیک کنید
  3. راز PROXY_URL را با مقداری به شکل http://user:[email protected]:port ایجاد کنید

مرحله 2: استفاده از متغیرهای محیطی در workflow

اکثر ابزارها (curl، wget، npm، pip، Maven) به طور خودکار متغیرهای محیطی استاندارد HTTP_PROXY، HTTPS_PROXY و NO_PROXY را شناسایی می‌کنند. مثال workflow:

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: پروکسی SOCKS5 در GitHub Actions

اگر از 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

  1. پروژه را باز کنید → تنظیماتCI/CD → بخش متغیرها
  2. روی افزودن متغیر کلیک کنید
  3. متغیر PROXY_URL را با نوع Masked (مقدار را در لاگ‌ها پنهان می‌کند) اضافه کنید
  4. مقدار: 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 خود میزبان: تنظیم پروکسی در سطح رنر

اگر از GitLab 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"
  ]

این کار راحت است زمانی که همه خطوط لوله در این رنر باید از پروکسی استفاده کنند — نیازی به نوشتن آن در هر .gitlab-ci.yml نیست.

تنظیم پروکسی در Jenkins

Jenkins از سه ابزار دیگر انعطاف‌پذیرتر است، اما تنظیم آن نیز پیچیده‌تر است. پروکسی را می‌توان در چندین سطح تنظیم کرد: به طور جهانی برای کل Jenkins، برای یک Pipeline خاص یا برای یک مرحله خاص.

روش 1: تنظیمات جهانی پروکسی در Jenkins

  1. به مدیریت Jenkinsسیستم بروید
  2. بخش پیکربندی پروکسی HTTP را پیدا کنید
  3. فیلدها را پر کنید: سرور، پورت، نام کاربری، رمز عبور
  4. در فیلد No Proxy Host آدرس‌های داخلی را با کاما مشخص کنید
  5. روی آزمایش URL کلیک کنید تا بررسی کنید و ذخیره کنید

این تنظیم بر بارگذاری پلاگین‌ها و به‌روزرسانی‌های خود Jenkins تأثیر می‌گذارد، اما به طور خودکار به محیط اجرای خطوط لوله منتقل نمی‌شود. برای خطوط لوله به پیکربندی جداگانه نیاز است.

روش 2: پروکسی در 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

  1. به مدیریت Jenkinsاعتبارنامه‌هاسیستماعتبارنامه‌های جهانی بروید
  2. روی افزودن اعتبارنامه‌ها کلیک کنید
  3. نوع: متن مخفی
  4. ID: proxy-url-credential
  5. مخفی: http://user:[email protected]:port

روش 3: پروکسی از طریق پارامترهای JVM برای پروژه‌های Java

اگر خط لوله شما پروژه 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 daemon برای پروکسی

در رنرهای خود میزبان می‌توان پروکسی را برای کل Docker daemon تنظیم کرد — در این صورت، همه کانتینرها به طور خودکار پروکسی را بدون تغییر در 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 و رازهای رمزگذاری شده در GitHub استفاده کنید — آنها در لاگ‌ها پنهان می‌شوند
  • ✅ در Jenkins از نوع متن مخفی یا نام کاربری با رمز عبور در فروشگاه اعتبارنامه‌ها استفاده کنید
  • 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، حداکثر سازگاری

خطاهای رایج و نحوه رفع آنها

حتی پس از تنظیم صحیح ممکن است مشکلاتی پیش بیاید. در اینجا رایج‌ترین خطاها و راه‌حل‌های آنها آورده شده است:

خطا: نیاز به احراز هویت پروکسی (407)

دلیل: نام کاربری یا رمز عبور نادرست است، یا آنها توسط ابزار منتقل نمی‌شوند.

راه‌حل: فرمت URL را بررسی کنید — کاراکترهای خاص در رمز عبور باید URL-encode شوند. به عنوان مثال، p@ss#wordp%40ss%23word. همچنین اطمینان حاصل کنید که متغیر محیطی واقعاً به مرحله منتقل می‌شود — آن را از طریق echo $HTTP_PROXY (حروف اول) برای بررسی چاپ کنید.

خطا: تأیید اعتبار گواهی SSL ناموفق بود

دلیل: پروکسی بازرسی SSL (MITM) را انجام می‌دهد و گواهی را تغییر می‌دهد. مشتری به گواهی پروکسی اعتماد ندارد.

راه‌حل: گواهی ریشه پروکسی را به لیست اعتماد اضافه کنید. برای curl: --cacert /path/to/proxy-ca.crt. برای npm: npm config set cafile /path/to/proxy-ca.crt. یا از پروکسی بدون بازرسی SSL استفاده کنید — این برای CI/CD ترجیح داده می‌شود.

خطا: زمان اتصال از طریق پروکسی

دلیل: سرور پروکسی از IP رنر در دسترس نیست، یا پورت توسط firewall مسدود شده است.

راه‌حل: با استفاده از دستور nc -zv proxy.host port در مرحله خط لوله، دسترسی پروکسی را بررسی کنید. اطمینان حاصل کنید که IP رنر به لیست سفید پروکسی ارائه‌دهنده اضافه شده است (اگر از احراز هویت IP استفاده می‌شود). برای رنرهای ابری GitHub Actions، دامنه‌های IP در meta.github.com منتشر می‌شوند.

خطا: ابزار متغیرهای HTTP_PROXY را نادیده می‌گیرد

دلیل: برخی ابزارها (به ویژه ابزارهای مبتنی بر Java) متغیرهای محیطی سیستمی را نمی‌خوانند.

راه‌حل: از تنظیمات بومی پروکسی برای ابزار خاص استفاده کنید (به جدول بالا مراجعه کنید). برای Java، خواص JVM را از طریق JAVA_OPTS اضافه کنید. برای curl، به طور صریح از پرچم -x http://proxy:port استفاده کنید.

خطا: خدمات داخلی نیز از طریق پروکسی عبور می‌کنند

دلیل: متغیر NO_PROXY تعیین نشده یا به درستی تعیین نشده است.

راه‌حل: همه دامنه‌ها و IP‌های داخلی را در NO_PROXY مشخص کنید. از wildcard برای دامنه‌ها استفاده کنید: NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.company.com. توجه داشته باشید: برخی ابزارها از Notation CIDR پشتیبانی می‌کنند، در حالی که دیگران فقط دامنه‌های دقیق را می‌پذیرند.

نتیجه‌گیری

تنظیم پروکسی در خط لوله CI/CD یک وظیفه یک‌باره نیست، بلکه بخشی از معماری صحیح اتوماسیون است. ما سه ابزار اصلی را بررسی کردیم: GitHub Actions (از طریق Secrets و متغیرهای محیطی)، GitLab CI (از طریق Variables با ماسک کردن) و Jenkins (از طریق فروشگاه اعتبارنامه‌ها و Pipeline اعلامی). اصول کلیدی برای همه یکسان است: هرگز اطلاعات حساب را در کد ذخیره نکنید، از NO_PROXY برای آدرس‌های داخلی استفاده کنید و نوع پروکسی را بر اساس وظیفه خاص انتخاب کنید.

انتخاب نوع پروکسی صحیح برای ثبات خط لوله حیاتی است. برای دانلود وابستگی‌ها و درخواست به API‌های استاندارد، پروکسی‌های سریع دیتاسنتر کافی است. اما اگر خط لوله شما تست‌های یکپارچه‌سازی را در وب‌سایت‌های واقعی انجام می‌دهد، با پلتفرم‌های تبلیغاتی (API تبلیغات Facebook، API تبلیغات TikTok) کار می‌کند یا به بازارها مراجعه می‌کند — از پروکسی‌های مقیم استفاده کنید: IP‌های آنها به عنوان ترافیک کاربر عادی درک می‌شوند و به ندرت تحت مسدودیت‌ها یا محدودیت نرخ قرار می‌گیرند.

قاعده اصلی: پروکسی را در یک مرحله جداگانه در ابتدای خط لوله تست کنید — این کار به شما اجازه می‌دهد تا به سرعت مشکلات را تشخیص دهید و زمان خود را برای جستجوی خطا در انتهای یک ساخت طولانی هدر ندهید. یک مرحله curl -v https://api.ipify.org بلافاصله بعد از تنظیم پروکسی اضافه کنید — این مرحله IP‌ای را که درخواست‌ها از آن ارسال می‌شوند نشان می‌دهد و تأیید می‌کند که پروکسی به درستی کار می‌کند.

```