DockerでWoodpecker CIをセルフホストする:軽量でセキュアなGitHub Actionsの代替案

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

肥大化したCI/CDパイプラインの負担

モダンなソフトウェア開発において、スムーズなCI/CDパイプラインの実行は不可欠ですが、私たちがよく利用するツールには大きなトレードオフが伴います。GitHub Actionsは公開リポジトリには最適ですが、プライベートな自己管理型のインフラに移行すると、コストやプライバシーの懸念が増大し始めます。

一方で、GitLabやJenkinsのような重量級のツールは、実際にビルドするアプリケーションそのものよりも多くのRAMやCPUを要求することがよくあります。2GBのRAMを搭載した小規模なVPS(仮想専用サーバー)が、CI/CDコントローラーがバックグラウンドタスクを実行しようとしただけでクラッシュしてしまう場面に何度も遭遇してきました。

このリソースを大量に消費する性質は、DevOpsの世界における多くの不満の根本原因です。作業を自動化するためのツール自体がメンテナンスの負担になってしまったら、より軽量な代替手段を探すべき時です。Drone CIのコミュニティフォークであるWoodpecker CIは、驚くほど軽量なコンテナネイティブのパイプラインエンジンを提供することで、この問題を解決します。Go言語で書かれているため、メモリ消費を最小限に抑えつつ、GitHub Actionsと同じようなYAMLベースの体験を提供します。

私はこのアプローチを本番環境に適用してきましたが、結果は一貫して安定しています。肥大化したCIシステムからDocker上で動作するWoodpeckerに移行することで、ビルド環境の完全な制御を維持しながら、インフラ의 オーバーヘッドを削減することができました。

なぜWoodpecker CIがあなたのインフラに適しているのか

コマンドの説明に入る前に、なぜこのスタックがうまく機能するのかを理解することが重要です。Woodpeckerは「サーバー・エージェント」アーキテクチャを採用しています。サーバーはWebインターフェース、ユーザー認証、API呼び出しを処理し、エージェント(または複数のエージェント)がDockerコンテナ内でのビルドステップの実行という重労働を担います。この分離により、ビルドの負荷が増えた場合に、別のサーバーにエージェントを追加して水平方向にスケールさせることが可能になります。

インストール:Docker Composeによるデプロイ

開始するには、DockerとDocker Composeがインストールされたサーバーが必要です。Woodpeckerの設定ファイルとデータベースファイルを保存するための専用ディレクトリを作成します。

mkdir ~/woodpecker-ci
cd ~/woodpecker-ci
touch docker-compose.yml .env

Woodpeckerでは、サーバーとエージェント間の通信に秘密鍵が必要です。opensslを使用して生成してください:

openssl rand -hex 32

次に、docker-compose.ymlファイルを構成しましょう。このセットアップでは簡素化のためにSQLiteを使用していますが、大規模なプロジェクトではPostgreSQLに簡単に切り替えることができます。

version: '3'

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    volumes:
      - ./woodpecker-data:/var/lib/woodpecker/
    environment:
      - WOODPECKER_OPEN=true
      - WOODPECKER_HOST=${WOODPECKER_HOST}
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT}
      - WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
    ports:
      - "8000:8000"
    restart: always

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    command: agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:8000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
    restart: always
    depends_on:
      - woodpecker-server

設定:GitHubへの接続

Woodpeckerがリポジトリを認識できるようにするには、GitHubでOAuthアプリケーションとして登録する必要があります。GitHubプロフィール -> Settings -> Developer Settings -> OAuth Apps -> New OAuth Appに移動します。

  • Application Name: My Woodpecker CI
  • Homepage URL: http://your-server-ip:8000
  • Authorization callback URL: http://your-server-ip:8000/authorize

登録されると、Client IDとClient Secretが発行されます。これらを.envファイルに入力してください:

WOODPECKER_HOST=http://your-server-ip:8000
WOODPECKER_AGENT_SECRET=your_generated_hex_key
WOODPECKER_GITHUB_CLIENT=your_github_client_id
WOODPECKER_GITHUB_SECRET=your_github_client_secret

1つのコマンドでサービスを開始します:

docker-compose up -d

最初のパイプラインの作成

WoodpeckerのUIにログインし、リポジトリを有効化した後、プロジェクトに設定ファイルを追加する必要があります。Woodpeckerはリポジトリのルートにある.woodpecker.ymlという名前のファイルを探します。以下はPythonプロジェクトの実用的な例です:

pipeline:
  test:
    image: python:3.11-slim
    commands:
      - pip install -r requirements.txt
      - pytest

  build:
    image: docker:24
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    commands:
      - docker build -t my-app:latest .
    when:
      branch: main
      event: push

すべてのステップが独自のコンテナで実行されることに注目してください。これにより、ビルド環境が毎回クリーンであることが保証されます。ホストマシン上でプラグインやツールのバージョンを手動で管理しなければならないことが多いJenkinsとは異なり、WoodpeckerはすべてをDockerイメージ内に隔離して保持します。

検証とモニタリング

コードをリポジトリにプッシュすると、WoodpeckerはWebhookを受信してパイプラインを開始します。Webインターフェースを通じて進捗を確認できます。しかし、システム管理者の視点からは、コンテナのヘルス状態をチェックすることも同様に重要です。

もしパイプラインが開始されない場合、最初に確認すべき場所はエージェントのログです。エージェントはイメージのプルとコマンドの実行を担当しています。Dockerソケットやサーバーに接続できない場合、ログですぐに原因が分かります:

docker logs -f woodpecker-agent

長期的な安定性のために、NginxやTraefikなどのリバースプロキシをSSL付きで設定することをお勧めします。平文のHTTP経由でCI/CDを実行することは、特にDocker Hubの認証情報やAPIキーなどの機密情報をパイプラインのステップ内で渡す場合に、大きなセキュリティリスクとなります。WoodpeckerはUIを通じたシークレット管理をサポートしており、バージョン管理にコミットすることなく環境変数をコンテナに注入できます。

セルフホストのCIシステムを維持するには、少しの規律が必要です。エージェントホスト上のDockerシステムを定期的にクリーンアップ(prune)して、古いビルドイメージがディスク容量を使い果たさないようにしてください。週に一度 docker system prune -f を実行する単純なcronジョブを設定するだけで、システムを軽量かつ高速に保つのに十分です。

Share: