Gitea + Drone によるセルフホストCI環境構築

ここでは、GiteaとDroneの組み合わせで、Drone Runnerを用いてコンテナのビルドを確認します。

目次

関連

GiteaとDrone

CI / CD

ソフトウェア開発におけるビルドやテスト・デリバリー・デプロイメントを自動化し、継続的に行うアプローチを指す名称です。自動化することで、開発時の工数や開発者の負担を減らし、少ない人数での開発効率の向上やヒューマンエラーの防止に役立つ。1人で開発しているときも、テストやビルドが自動化されれば、コードを書く時間を増やすことができる。

  • CI:継続的インテグレーションのこと。

    • システムやアプリケーションの追加や変更について、常に自動でテストやビルドを行うことを意味する。通常、コードを書いた後に、手動でテストし、問題がなければリポジトリにプッシュすることを行うが、こうした手動の作業を自動化することで、開発者の負担を減らし、作業の効率化やコスト削減に寄与する。

  • CD:継続的デリバリーのこと。

    • 自動で本番環境にデプロイ(実装)することを意味する。多くは、AWS等のパブリッククラウドコンピューティング環境(特にPaaSやIaaS)であることが多い。CDを使わない場合は、原則手動作業となるため、手順書を用意し、デプロイ担当エンジニアが、手順書を使って作業を行い、作業毎に証跡を記録(画面ショット等)するとともに、時には作業ミスや作業ミスによるエラー対応を実施し、エラーを起因とする障害報告書を作成、作成した報告書について上司や顧客の責任者に承認をもらわないといけなかったことを、自動化すること多くの手間を削減する。CDを用いた自動化により、関係者の負担削減、ヒューマンエラーの防止、コスト削減等に寄与する。

工数

ある作業を完了させるために必要となる時間のこと。

ジョブ

コマンドなど自動で実施する作業のことを「ジョブ」と言います。

Gitea

Giteaは、Githubに近い機能を持ち、好みのサーバーやクラウドサービス、仮想マシンでホスティング(運用)するためのソフトウェアです。Githubのように、Gitを用いてソースコードのバージョン管理やWikiによる情報共有、issue機能によるチケット管理などを行うことができます。
https://about.gitea.com/

Drone

競合としてJenkinsやCircle CIなどがあります。GiteaやGithubと連携することができる、Dockerコンテナ内でジョブを実行することに特化したCIツールです。
https://www.drone.io/

Drone Runner

Drone Runner を用いることで、Dockerやkubernetes環境を用いて、コマンド実行やコンテナイメージ、Pythonなどの環境をビルドし、実行可能な状態にします。
https://docs.drone.io/runner/overview/

仮想サーバー(仮想マシン)の用意

例として、https://www.virtualbox.org/ (Windows , Linux , Intel CPU搭載Mac )を仮想環境としてを使っていますが、他の仮想環境でも構いません。

< 以下は、VirtualBoxを使った場合の例 >

仮想サーバーのスペック

  • OS:Ubutnu Server 22.04

  • 仮想CPU割り当て数 : 推奨は、2。1つの場合はなんとか動くレベル。

  • 仮想メモリ割り当て:推奨は、8192MB(8GB)以上。4096MB(4GB)はなんとか動くレベル。

  • 仮想ディスク:64GB以上

  • ネットワーク設定:NAT + ホストオンリーアダプタの構成。ホストオンリーアダプタには、固定IPを割り当てること。

  • デスクトップ環境:なし

  • SSH接続:必須 ( ユーザー名 + パスワードでもOK )

仮想サーバー の設定

  • ホストオンリーアダプタの固定IP例:192.168.56.103

  • Your server’s name (ホスト名):ubuntu1ci

  • ユーザー名 : vboxuser

  • パスワード:任意のもの

M1 / M2 / M3 といったApple Silicon CPUの場合は、VirtualBoxは使えないため、UTM や Parallels Desktop を使って、上記に相当する仮想マシンを作成してください。 はWebサイトからからインストーラーをダウンロードしてインストールする場合は無料で使用可能です。

マルチキャストDNS対応設定

を参考に、マルチキャストDNSで、お使いのパソコンから、仮想マシンに接続できるようにします。

Docker EngineおよびDocker Compose の用意

既にインストール済みの場合は、飛ばしてください。

次のコマンドを実行します。

curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh

Dockerグループを作成します。既に作成済みの場合もあります。

sudo groupadd docker

sudoなしで実行できるように、作業用ユーザーをDockerグループに所属させます。

sudo usermod -aG docker $USER

GUIを使わずに、SSH接続でインストール作業した場合

一度ログアウト

その後、再度SSH接続を行います。

GUIを使ってインストール作業した場合

再起動します。

同一仮想マシンにおけるGiteaおよびDroneの起動制御ファイルの作成

起動制御ファイル(start.sh)の作成とバックアップ作成

次のコマンドを実行し、作業用ディレクトリを作成するとともに、start.sh を作成します。

start.sh を作成

次のコマンドを実行します。

start.shの中身

GITEA_IP は、仮想マシンの固定IPアドレスになります。ホストから接続する際に用います。GITEA_HOSTNAME は、仮想マシンのホスト名と同じにしましょう。

権限付与

バックアップの作成

起動用docker-compose.yml の作成

次のコマンドを実行して作成します。

中身は次のとおり。

start.shによるGiteaの初期設定

start.sh を使って、GiteaとDrone環境を起動

実行結果

Giteaの初期設定

Webブラウザで、Giteaにアクセス。LinuxでGUIを使っている場合は、Linux内のWebブラウザで、下記にアクセス。

http://仮想マシンの固定IPアドレス:3000/(例 http://192.168.56.103:3000/)

Giteaの初期設定画面が表示される。

< 初期設定 >

< 基本設定 >

< オプション設定 >

画面下に移動し、「オプション設定」下の「管理者アカウントの設定」をクリック。以下の値を入力した。

  • 管理者ユーザー名 : adminuser (前述のstart.shで指定したものと同じ)

  • パスワード : zxcvfr45 (好みのパスワードでOK)

  • メールアドレス : adminuser@ubuntu1ci.local (任意のもの)

    • マルチキャストDNS対応にしたことで、ホスト名.local で通信が通るようになっている。通信が通らないと、Droneでエラーがでる。実在のドメインを適用したサーバーを用意できれば、マルチキャストDNSは不要。

「Giteaをインストール」をクリックする。エラーがでることがあるので、エラーが出た場合は、Webブラウザの再読み込みを行うか、http://仮想マシンの固定IPアドレス:3000/(例 http://192.168.56.103:3000/) にアクセスし直す。

管理者アカウントでログインした状態で、Giteaが表示される。

GiteaのOAuth2設定

http://仮想マシンの固定IPアドレス:3000/user/settings/applications にアクセスする(例 http://192.168.56.103:3000/user/settings/applications)。もしくは、画面右上のアバターアイコンをクリックし、「設定」>>「アプリケーション」の順にクリックしても良い。
「OAuth2アプリケーションの管理」にて、新しいOAuth2アプリケーションの作成を実施。下記を入力し、「アプリケーション作成」をクリック。

  • アプリケーション名 : Drone

  • リダイレクトURI : http://仮想マシンの固定IPアドレス:3001/login(例 http://192.168.56.103:3001/login)

表示された「クライアントID」と「クライアントシークレット」をメモしておきます。Linux内に、nano か vi コマンドを使って、メモとして残しておくと良いでしょう。その後、「保存」をクリックします。

保存したことで、「OAuth2アプリケーションの管理」に「Drone」が加わりました。「編集」をクリックすることで、「クライアントID」は表示されますが、「クライアントシークレット」は非表示です。「クライアントシークレット」を忘れた場合は、「削除」を実行し、OAuth2アプリケーションの作成し直します。

GiteaとDroneの再起動

起動制御ファイルの「start.sh」に、Giteaで発行した「クライアントID」と「クライアントシークレット」を追記し、GiteaとDroneを再起動します。

start.shの編集

start.sh を編集

start.shの「DRONE_GITEA_CLIENT_ID」と「DRONE_GITEA_CLIENT_SECRET」を編集。下記の「DRONE_GITEA_CLIENT_ID」と「DRONE_GITEA_CLIENT_SECRET」の値は例のため、Giteaで発行した各自の値を挿入してください。

つまり、上記をコピペしても動きません。「DRONE_GITEA_CLIENT_ID」と「DRONE_GITEA_CLIENT_SECRET」の値は例のため、Giteaで発行した各自の値を挿入してください。

start.sh を再び実行

実行結果

Droneの初期設定

Webブラウザで、Droneにアクセス。LinuxでGUIを使っている場合は、Linux内のWebブラウザで、Giteaとは別にタブを作り、下記にアクセス。

http://仮想マシンの固定IPアドレス:3001/login(例 http://192.168.56.103:3001/login)

「アプリケーションを許可」をクリックします。

Droneに登録します。入力後、「SUBMIT」をクリックします。例として、次のように入力しています。

  • Your Email : adminuser@ubuntu1ci.local (Giteaの管理者アカウントメールアドレスと同じもの)

  • Your Full Name : admin user (任意のもの)

  • Company Name : mydev Inc. (任意のもの)

次のように表示されます。

Giteaのタブに戻ります。

新規リポジトリ(レポジトリ)の作成

Giteaのタブに移動し、緑色のGitea(緑色のカップ)のアイコンをクリックします。緑色のGitea(緑色のカップ)のアイコンをクリックすることで、Giteaのダッシュボード画面に戻ります。

Giteaのダッシュボード画面で、「+」>>「新しいリポジトリ」の順にクリックします。

「新しいリポジトリ」画面が表示されます。下図のように「リポジトリ名」と「説明」を入力します。画面下に移動します。

「ライセンス」は任意のものを選んでください。オープンソースソフトウェアの場合は、商用で使いやすいものとして認識されているライセンスでは、「Apache-2.0」や「MIT」などがあります。「リポジトリの初期設定」にチェックを入れます。ここはとても重要です。「リポジトリを作成」をクリックします。

リポジトリが作成され、「README.md」も作成されていることがわかります。作成直後のブランチは、「main」になっています。Github等と同じで、前はmasterでしたが、今はmainになっています。

GiteaとDroneの同期

Droneのタブに戻ります。

Droneの画面で「SYNC」をクリックします。

Droneに表示されたリポジトリ名をクリックします。ここでは、「adminuser/hello-world」をクリックしましょう。

「Settings」タブで、「ACTIVATE REPOSITORY」をクリックします。

「Project Settings」で、「Trusted」をクリックし、有効化します。「Project Visibility」は「Public」を指定します。「SAVE CHANGES」をクリックします。

DroneによるCIの動作確認 ( 例として、Docker パイプラインの場合 )

Docker パイプラインの場合は、なにもエラーがなければ、コンテナイメージが作成されます。またコンテナレジストリ(例 Docker Hub)にプッシュしたり、docker run や docker compose up などで、コンテナを起動することもできます。

  • Docker パイプラインのオンラインドキュメント : << 英語が公式。なにかあったときは、まず公式ドキュメントを読むことが鉄則。公式ドキュメント以外は、情報が古いことがあるので、そのことを理解しておくこと。

  • Drone 日本語情報サイト、Docker パイプラインドキュメント : << 株式会社Digital Stacks が公開している。

定義ファイル、「.drone.yml」の作成

Giteaのタブに切り替えます。

Giteaに作成したリポジトリで、「ファイル追加」>>「新規ファイル」の順にクリックします。

下図のように「.drone.yml」を作成します。作成するファイル名の読み方は、ドットドローンワイエムエルです。

.drone.yml の記述内容

入力後、画面下に移動し、コミットの内容を入力し、「変更をコミット」をクリックします。

コミットしました。リポジトリ名(ここでは、hello-world)をクリックし、リポジトリのトップ画面に戻ります。「コード」タブ下の「コミット」と表示されているタブ(下図では、2コミットと表示)をクリックします。

コミット一覧が表示され、各コミットを確認することができます。

メッセージをクリックすることで、コミットの詳細が表示されます。コミットの内容を入力しておくことで、あとで見返すことができます。

たとえば、「'.drone.yml' を追加」というメッセージをクリックした場合

最初のビルドの実行

Droneのタブに戻ります(下図では、Settingsと表示されているタブ)。

画面上部の「+NEW BUILD」をクリックします。

「Create a New Build」が表示されます。Branchとして、Giteaで「.drone.yml」が作成してある「main」を指定します。「Create」をクリックします。

最初のビルドが実行されます。

画面上部の「Builds」タブをクリックします。

ビルドの進捗状況(Status)が表示されます。成功すれば、Success と表示されます。

画面下の「EXECUTIONS」では、ビルドが成功すると緑色のチェックボックスで表示されます。

なお、処理中の場合は、黄色のアイコンが表示されます。

「EXECUTIONS」内のビルド名(例 '.drone.yml' を追加 docker パイプラインを使った、CIの動作確認)をクリックすることで、ログが表示されます。

エラーの場合エラーメッセージが表示されます。エラーメッセージに従って、問題を解決します。下図のエラーは、mydev.example.jp というホスト名をIPアドレスに変換できなかった、つまり通信ができなかったことを意味します。たとえば、hostsファイルに、IPアドレスとホスト名を書くことや、マルチキャストDNSを使えるホスト名に変更するなどが解決策としてあげられます。

CRONによる定期実行

定期的にビルドを実行するには、CRONの機能を使います。CRONは、Linux環境であれば、UbuntuやRedHat系問わず、使用可能です。

ビルドのログ画面が表示されている場合は、リポジトリ名の左隣の「←」をクリックしましょう。

Drone側のリポジトリ設定を変更します。

Drone側のリポジトリで、「Settings」タブ内の「Cron Jobs」で、CRON設定を作成します。CRONにより、自動実行が行われます。「+NEW CRON JOB」をクリックすることで、時間毎や日毎、週毎に定期的に実行することができます。

「1stcron」という1時間毎に実行するcronjob を作成します。Branchは、「main」を入力します。Scheduleは、@hourlyで1時間毎を意味します。@daily(日毎)なども指定することができます。

作成したCron Job の例。Cron Jobは、「NEXT EXECUTION」に次の実行予定の時間が書かれていますが、同時に処理しているプロセス等の都合で10分程度遅れることがあります。

また、ジョブの実行対象となるファイル「.drone.yml」に対して、作成したCRONを実行条件とすることを記述しておくことも必要です。この作業は、Gitea側で行います。

Giteaタブに切り替えます。

Giteaの画面で、hello-worldリポジトリで、「.drone.yml」をクリックします。「ファイルを編集」と表示されるペン型のアイコンをクリックします。

Drone側で、1stcron というCRON JOBを作成したので、Gitea側で「.drone.yml」に、1stcronをジョブのトリガーに指定する設定を追記した例。

対象のブランチをmasterとし、Droneで作成したCRON定義「1stcron」をDrone Runnerの実行トリガーとして追加した「.drone.yml」の記述例

入力後、画面下に移動し、コミットの内容を入力し、「変更をコミット」をクリックします。コミット後、Drone側で、Cron Job が実行されるまで待ちます。同時に処理しているプロセス等の都合で予定時間よりも10分程度遅れることがあります。

Droneタブに切り替えます。

画面上部の「Builds」タブをクリックします。Cron Job が実行されるまで待ちます。待っている間に、後述の「課題:Dockerfileを用いて、コンテナをビルドしよう」を進めると時間つぶしになります。

Drone側での実行結果

「EXECUTIONS」内のビルド名(例 '.drone.yml' を更新 Droneで作成したCron Job「1stcron」のトリガーを追加)をクリックし、ログを確認します。

課題:Dockerfileを用いて、コンテナをビルドしよう

Giteaにリポジトリを作成し、Droneで、オリジナルのコンテナをビルドしてください。ビルドするにためには、「.drone.yml」と「Dockerfile」の2つの作成が必要です。Gitea側に「 で用いたDockerfile を使って構いません。

< .drone.yml の記述例 >

< Dockerfile の記述例 >

< Drone でビルド際のログ >

ビルドすると、仮想マシン上に「.drone.yml」で指定したコンテナイメージが作成されます。

手動でビルドしていますが、Cron Job を使用可能であることはわかっていますので、ビルドを自動化することができます。CI を活用することで、コンテナのビルドや実行が自動化できるわけです。また、エラー時もどこでエラーになったか記録に残るため、CIツールを整備することは、チーム開発の際には大きな助けになります。

Gitea および Drone 環境の停止と終了、再起動

コンテナの停止

本資料では、GiteaとDroneは、同一環境に共存し、Docker Compose を使っているため、作業用ディレクトリの「mycicdenv」下で、次のコマンドを実行します。

コンテナの終了

これで、GiteaとDroneのコンテナが停止します。コンテナを終了するため、続けて、次のコマンドを実行します。

GiteaとDroneのコンテナが削除されました。docker ps で確認してみましょう。

実行結果

GiteaとDroneのコンテナは動いていないことがわかります。

GiteaとDrone環境の再起動

もし、GiteaとDroneを再び使いたい場合は、作業用ディレクトリの「mycicdenv」下で、次のコマンドを実行します。

docker ps を実行すると、起動したコンテナを確認することができます。

実行結果

作業用ディレクトリの「mycicdenv」下の「drone」と「gitea」の両ディレクトリが消えていなければ、以前の状態で、GiteaとDroneを再利用することができます。