RAMの無駄遣いをやめる:DroneとGiteaで軽量なCI/CDパイプラインを構築する

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

肥大化したCI/CDの問題

以前、小さなPythonプロジェクトを管理するために、月額5ドルのDigitalOcean dropletでJenkinsを実行しようとしたことがありますが、それは悲劇でした。数分もしないうちに、Jenkinsがアイドル状態で1.5GB近いRAMを消費したため、LinuxのOOM (Out of Memory) killerによってプロセスが強制終了されました。個人開発者や小規模なチームにとって、従来のCI/CDツールは「牛刀をもって鶏を割く」ようなものに感じられることがよくあります。

ほとんどのエンタープライズ向けツールは、軽量なVPS環境ではなく、大規模なクラスター向けに設計されています。もしGiteaのようなGitサーバーをセルフホストしているなら、それと同じくらい効率的なパイプラインが欲しくなるはずです。待機中のRAM消費が100MB未満で、実際にコードをビルドするときだけCPUサイクルを消費するような、邪魔にならないシステムが必要です。

そこでDrone CIの出番です。これは完全にコンテナファーストのアーキテクチャで構築されています。パイプラインのすべてのステップは単なるDockerコンテナであり、起動してジョブを実行し、終了すると消えます。Giteaと組み合わせることで、合計RAMがわずか1GBのサーバーでも、GitHubのような体験を得ることができます。

なぜDrone CIとGiteaなのか?

GiteaはGoで書かれた軽量なGitサービスです。Raspberry Piでも動作するほど高速でありながら、洗練されたUIを提供します。Drone CIもこの哲学を共有しています。複雑なプラグインのネットワークの代わりに、Droneはリポジトリのルートにあるシンプルな.drone.ymlファイルを使用します。

この「Pipeline as Code」モデルにより、ビルドロジックはソフトウェアと共に進化します。Droneはコンテナネイティブであるため、ホストサーバーにNode.js、Python、Goなどを手動でインストールする必要はありません。プロジェクトでNode 20が必要な場合は、そのステップでnode:20イメージを指定するだけです。この分離により「自分のマシンでは動くのに」という問題を回避し、ホストOSをクリーンに保つことができます。

このスタックをマスターすることは大きなアドバンテージになります。Kubernetesのような急峻な学習曲線を辿ることなく、コンテナオーケストレーションと環境分離の基本原則を学ぶことができます。

軽量スタックのセットアップ

Docker Composeを使用して、GiteaとDrone CIの両方を1台のサーバーにデプロイします。共有ブリッジネットワークを使用することで、すべてのポートを外部に公開することなく、コンテナ間で安全に通信できます。

ステップ1:システム要件

1GBのRAMと1つのCPUコアを備えた基本的なUbuntu 22.04サーバーがあれば、このセットアップには十分です。DockerとComposeプラグインがインストールされていることを確認してください。また、OAuthコールバックを正しく処理するために、ドメイン名(例:ci.yourdomain.com)も必要です。

ステップ2:Docker Composeの設定

専用のディレクトリを作成し、設定ファイルを初期化します:

mkdir devops-stack && cd devops-stack
touch docker-compose.yml

以下の設定を挿入します。このセットアップでは、Giteaサービス、Drone Server(頭脳)、Drone Runner(実行部)を定義します。

version: '3.8'

services:
  gitea:
    image: gitea/gitea:1.21
    container_name: gitea
    restart: always
    networks:
      - ci-network
    ports:
      - "3000:3000"
      - "222:22"
    volumes:
      - ./gitea:/data

  drone-server:
    image: drone/drone:2
    container_name: drone-server
    ports:
      - "8080:80"
    volumes:
      - ./drone:/data
    restart: always
    networks:
      - ci-network
    environment:
      - DRONE_GITEA_CLIENT_ID=${GITEA_CLIENT_ID}
      - DRONE_GITEA_CLIENT_SECRET=${GITEA_CLIENT_SECRET}
      - DRONE_GITEA_SERVER=http://gitea:3000
      - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
      - DRONE_SERVER_HOST=ci.yourdomain.com
      - DRONE_SERVER_PROTO=http

  drone-runner:
    image: drone/drone-runner-docker:1
    container_name: drone-runner
    restart: always
    networks:
      - ci-network
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_RPC_PROTO=http
      - DRONE_RPC_HOST=drone-server
      - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
      - DRONE_RUNNER_CAPACITY=2
      - DRONE_RUNNER_NAME=main-runner

networks:
  ci-network:
    driver: bridge

ステップ3:GiteaとDroneの連携

Droneは独自のユーザーデータベースを持たず、認証をGiteaに依存します。まず、Giteaを起動します:

docker-compose up -d gitea
  1. http://your-ip:3000 にアクセスし、初期設定を完了させます。
  2. ログインし、設定 -> アプリケーション -> OAuth2アプリケーション に移動します。
  3. 「Drone CI」という名前で新しいアプリケーションを作成します。
  4. リダイレクトURIhttp://ci.yourdomain.com/login に設定します。
  5. クライアントIDクライアント機密情報 をすぐにメモしておきます。

ステップ4:シークレットの保護

.env ファイルを作成します。これにより、機密情報をメインのComposeファイルから分離できます。RunnerとServerが安全に通信できるように、RPCシークレットには強力なランダム文字列を使用してください。

GITEA_CLIENT_ID=your_id_here
GITEA_CLIENT_SECRET=your_secret_here
DRONE_RPC_SECRET=$(openssl rand -hex 16)

ステップ5:デプロイ

単一のコマンドでスタック全体を起動します:

docker-compose up -d

http://ci.yourdomain.com にアクセスしてください。Droneは認証のためにGiteaにリダイレクトします。「承認」をクリックすると、GiteaのリポジトリがDroneのダッシュボードに表示され、有効化できるようになります。

ステップ6:最初のパイプラインの作成

システムをテストするために、任意のリポジトリのルートに .drone.yml ファイルを追加します。以下は、Node.jsアプリケーションの実用的な例です:

kind: pipeline
type: docker
name: test-and-deploy

steps:
- name: install-dependencies
  image: node:20-slim
  commands:
  - npm install
  - npm test

- name: notify-success
  image: plugins/webhook
  settings:
    urls: https://discord.com/api/webhooks/your-id
    content: "ビルド成功!"

このコードをプッシュした瞬間、GiteaはDroneにWebhookを送信します。Droneは node:20-slim イメージをプルし、テストを実行し、終了後に後片付けを行います。このビルド中の総リソース使用量は?通常、200MBのRAM未満です。

まとめ

CI/CDをセルフホストするために、高額な費用や大量のリソースは必要ありません。Docker、Drone、Giteaを組み合わせることで、プライベートで高速、かつ驚くほど効率的なプロフェッショナルグレードのパイプラインを構築できました。もうクラウドプロバイダーのクレジットや、肥大化したJavaアプリケーションに縛られることはありません。

さらにステップアップするには、CaddyやNginxなどのリバースプロキシとLet’s Encryptの導入を検討してください。これによりHTTPSが提供され、標準の443ポートですべてを実行できるようになります。YAML構文に慣れたら、並列ビルドステップやプライベートレジストリへの自動Dockerイメージアップロードなどの高度な機能を試してみてください。

Share: