act を使ってローカルマシンで CI/CD:Linux 使い(略)Advent Calendar 2024
はじめに
これは「Linux 使いになりたい人のための Advent Calendar 2024」の記事です。
筆者は、Web エンジニアを志望する人には、セルフホスト Git サービスを稼働させて利用することをオススメしています。もし Git を使ったことがないなら、Git を学ぶときに、セルフホスト Git サービスを稼働させることも視野に含めながら学習するのが効率的だと考えています。
セルフホスト Git サービスを稼働させると良い理由については、これまでもいくつか説明してきていますが、個人的に一番大きかったのは、個人開発でも CI/CD 環境が必須となる時代になっていると感じたからです。
そのため、個人開発で使える CI/CD 環境について、ここまで紹介してきたように、いろいろと調べてきたのですが、最近は act
を採用するのも良いかもしれないと検討しているところです。
今回は、ローカルマシンで CI/CD を実行可能とする act
について紹介します。
act を使ってローカルマシンで CI/CD
ここまで、GitBucket や GitLab で CI/CD 環境を用意する方法について紹介してきました。実際に動かすことで、CI/CD(継続的インテグレーションと継続的デリバリー)とはどういうものか、具体的なイメージが持てるようになったはずです。
ここで、世の中で普及している GitHub での CI/CD 環境としては「GitHub Actions」というものがあります。これは、GitHub でビルド、テスト、デプロイのパイプラインを自動化できる CI/CD のプラットフォームになります。
GitHub Actions では、Git リポジトリの .github/workflows/
ディレクトリーにあるワークフローファイルを使ってパイプラインの自動処理を実行する仕組みが導入されています。GitLab CI/CD の .gitlab-ci.yml
ファイルと似たような感じです。
このワークフローファイルをローカルマシンでも実行可能とするツールが act
です。次の URL で公開されています。
公式サイトでの act
の謳い文句は Run your GitHub Actions locally!
です。次の2つの理由で act
は開発されているとのこと。
- 高速なフィードバック
- ローカルのタスクランナー
GitHub Actions 向けの処理を開発するにあたっては、ローカルマシンで、その処理を実行できる環境があった方が効率よく開発ができます。act
を使うと、GitHub Actions 向けの処理について高速なフィードバックを得ることができます。
また、GitHub Actions 向けに処理の自動化ができたなら、それをローカルマシンでも再利用したくなるはずです。同じ処理をするコードについて、ローカルマシン環境と CI/CD 環境とで、別々に用意するのは無駄に感じることでしょう。act
を使うと、GitHub Actions 用のワークフローファイルをローカルマシンで利用できるので、ローカルのタスクランナーとして活用可能となります。
なお、act
を使うには Docker Engine がインストールされたマシンが必要なので用意しておいてください。ここでは Docker Engine のインストール方法については紹介しません。
用意するファイルのディレクトリー構成
ここで用意するファイルのディレクトリー構成は次のようになります。
act/
├── compose.yaml
└── script/
├── container/
│ └── run.sh
├── install.sh
└── setup_demo.sh
なお、ここでは act
を ${ACT_DIR}
と表記します。
act 試用のための Docker コンテナー
最初に、act 試用のための Docker コンテナーを用意します。${ACT_DIR}/compose.yaml
は次のようになります。
name: act
services:
act:
image: ubuntu:24.04
container_name: act
hostname: act
tty: true
entrypoint: /bin/bash
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
Docker を使うため、/var/run/docker.sock
をバインドマウントしている点に注意してください。
compose.yaml
を用意したら起動します。
cd ${ACT_DIR}
docker compose up -d
それから docker compose exec
コマンドで act
コンテナーへアタッチします。
docker compose -p act exec act bash
ここで、compose.yaml
を使わずに docker container
コマンドを使って、act
コンテナーへアタッチするところまで一気に実行することもできます。
docker container run --rm -it \
--name act \
--hostname act \
--volume /var/run/docker.sock:/var/run/docker.sock \
ubuntu:24.04 bash
このコマンドは Docker に慣れてくると compose.yaml
から簡単に変換して実行できるようになります。そのため、筆者はできるだけ compose.yaml
で宣言的にコンテナーを定義しておいて、実際にコンテナーの起動が必要な場面で docker compose
コマンドを使うか、docker container
コマンドを使うか決めています。
入力が面倒なのでスクリプトファイル ${ACT_DIR}/script/container/run.sh
にしておいても良いでしょう。
act のインストール
act をインストールするには、リリースされているバイナリーファイルをダウンロードするのが単純です。これを実行するスクリプトが公式サイトで用意されているので、これを使います。
Docker イメージの ubuntu:24.04
では、このファイルを実行するにあたって必要な curl
、git
コマンドが足りないので、apt
コマンドでインストールします。また、今回作業時に tree
コマンドも使うので、それもインストールします。
これらの作業をスクリプト ${ACT_DIR}/script/install.sh
にすると、次のようなスクリプトになります。
#!/bin/sh
SCRIPT_URL=https://raw.githubusercontent.com/nektos/act/master/install.sh
apt-get update && apt-get -y install curl git tree
curl --proto '=https' --tlsv1.2 -sSf ${SCRIPT_URL} | bash
スクリプトを用意したらコンテナーへコピーして、コンテナー内で実行します。
cd ${ACT_DIR}
docker compose -p act cp ./script/install.sh act:/usr/local/src/
docker compose -p act exec act sh /usr/local/src/install.sh
インストールができると、act:/usr/bin/act
に act
コマンドがインストールされます。次のように act
コンテナー内で確認して実行してみましょう。
$ docker compose -p act exec act which act
/usr/bin/act
$ docker compose -p act exec act /usr/bin/act --version
act version 0.2.70
デモ用リポジトリのクローン
act
コマンドの動作確認するには、デモ用リポジトリを利用します。具体的には act
の公式サイトで紹介されている https://github.com/cplee/github-actions-demo にあるものを使います。これには Node.js のプロジェクトで使われる GitHub Actions 用のワークフローファイルの雛形が含まれています。
デモ用リポジトリのクローンをしてセットアップするスクリプトを ${ACT_DIR}/script/setup_demo.sh
に次の内容で用意します。
#!/bin/sh
git -C /usr/local/src/ clone \
https://github.com/cplee/github-actions-demo.git
スクリプトを用意したらコンテナーへコピーして、コンテナー内で実行します。
cd ${ACT_DIR}
docker compose -p act cp ./script/setup_demo.sh act:/usr/local/src/
docker compose -p act exec act sh /usr/local/src/setup_demo.sh
クローンができたら、tree
コマンドでファイルの確認をしておきます。
docker compose -p act exec \
--workdir=/usr/local/src/github-actions-demo act \
tree -aI .git
実行結果は次のようになります。
.
|-- .eslintrc.yml
|-- .github
| `-- workflows
| `-- main.yml
|-- .gitignore
|-- LICENSE
|-- README.md
|-- index.js
|-- package-lock.json
|-- package.json
`-- tests
`-- test-app.js
4 directories, 9 files
デモの実行
それでは、デモの実行をしてみましょう。
まず、どんな処理が実行されるのか、.github/workflows/main.yml
の内容を確認します。
docker compose -p act exec \
--workdir=/usr/local/src/github-actions-demo act \
cat .github/workflows/main.yml
実行結果は次のようになります。
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- run: npm install
- run: npm test
ここではジョブの test
が用意されていて、実行環境は runs-on: ubuntu-latest
と指定されています。steps:
に実行する処理のステップが指定されています。各ステップについては、uses:
を使って実行するアクション、run:
を使って実行するコマンドが指定されています。
このことから、リポジトリからコードをチェックアウトし、Node.js 環境を用意し、npm install
を実行、npm test
を実行というステップを踏むことがわかります。
実行してみましょう。
docker compose -p act exec \
--workdir=/usr/local/src/github-actions-demo act \
act
使用する Docker イメージについて、Large
、Medium
、Micro
から選択するようにプロンプトが次のように表示されます。矢印キーの上下で >
が移動するので、これで選択してから Enter キーで確定できます。ここではサイズが小さい Micro
を指定します。
INFO[0000] Using docker host 'unix:///var/run/docker.sock' (略)
? Please choose the default image you want to use with act:
- Large size image: ca. 17GB download + 53.1GB storage (略)
- Medium size image: ~500MB (略)
- Micro size image: <200MB (略)
Default image and other options can be changed manually in /root/.config/act/actrc (略)
Large
Medium
> Micro
すると、main.yml
に指定した処理が実行されます。
[CI/test] 🚀 Start image=node:16-buster-slim
[CI/test] 🐳 docker pull image=node:16-buster-slim platform= username= forcePull=true
(略)
[CI/test] ☁ git clone 'https://github.com/actions/setup-node' # ref=v1
[CI/test] ⭐ Run Main actions/checkout@v2
[CI/test] 🐳 docker cp src=/usr/local/src/github-actions-demo/. dst=/usr/local/src/github-actions-demo
[CI/test] ✅ Success - Main actions/checkout@v2
[CI/test] ⭐ Run Main actions/setup-node@v1
[CI/test] 🐳 docker cp src=/root/.cache/act/actions-setup-node@v1/ dst=/var/run/act/actions/actions-setup-node@v1/
[CI/test] 🐳 docker exec cmd=[/usr/local/bin/node /var/run/act/actions/actions-setup-node@v1/dist/index.js] user= workdir=
(略)
[CI/test] ✅ Success - Main actions/setup-node@v1
[CI/test] ⚙ ::add-path:: /opt/hostedtoolcache/node/10.24.1/x64/bin
[CI/test] ⭐ Run Main npm install
[CI/test] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/2] user= workdir=
| added 280 packages from 643 contributors and audited 280 packages in 2.989s
(略)
| run `npm audit fix` to fix them, or `npm audit` for details
[CI/test] ✅ Success - Main npm install
[CI/test] ⭐ Run Main npm test
[CI/test] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/3] user= workdir=
(略)
| 1 passing (16ms)
|
[CI/test] ✅ Success - Main npm test
[CI/test] Cleaning up container for job test
[CI/test] 🏁 Job succeeded
使用する Docker イメージの指定
act
コマンド実行時に Micro を指定した後に、/root/.config/act/actrc
ファイルが作成されているので、中身を確認すると、次のようになっていました。
-P ubuntu-latest=node:16-buster-slim
-P ubuntu-22.04=node:16-bullseye-slim
-P ubuntu-20.04=node:16-buster-slim
-P ubuntu-18.04=node:16-buster-slim
このファイルで main.yml
内の runs-on: ubuntu-latest
で指定したプラットフォームに対して実際に使用する Docker イメージを指定できるようです。
参考までに、Medium を指定した場合の /root/.config/act/actrc
は次のようになっていました。
-P ubuntu-latest=catthehacker/ubuntu:act-latest
-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
-P ubuntu-20.04=catthehacker/ubuntu:act-20.04
-P ubuntu-18.04=catthehacker/ubuntu:act-18.04
こちらについては、catthehacker/docker_images: GitHub を参照すると、次のタグが紹介されています。Docker Hub ではなく、GitHub の Docker レジストラを使うなら、修正しても良いでしょう。
ghcr.io/catthehacker/ubuntu:act-20.04
ghcr.io/catthehacker/ubuntu:act-22.04
ghcr.io/catthehacker/ubuntu:act-latest
使用する Docker イメージは、/root/.config/act/actrc
で決まりますが、自分が作成したカスタムイメージを使うこともできます。その場合は、act
コマンド実行時に -P
オプションで指定します。 actrc
ファイルにあるのと同じようにすれば良いです。
なお、Docker レジストラに push していない、ローカルでビルドしただけの Docker イメージを使うには --pull
オプションを指定すれば良さそうです。
おわりに
act
コマンドと Docker Engine 環境をローカルマシンに用意すると、GitHub Actions をローカルマシンでも実行できることがわかりました。なお、Gitea Act Runner や Forgejo Runner では、この act
をベースとした CI/CD 用ランナーが採用されています。
筆者は GitHub、Gitea、Forgejo で使えるワークフローファイルがローカルマシンでも利用できるのなら、ローカルマシンでの CI/CD に act
コマンドを採用するのは良さそうだと考えています。まだきちんと確認していませんが、GitBucket + CI Plugin でも利用できそうな印象です。
少し気になるのは git clone 'https://github.com/actions/setup-node'
のように、uses:
で指定されたアクションは git clone
で取得している点です。ローカルマシンでは毎回 git clone
がされることはないでしょうが、GitBucket + CI Plugin などで使用する場合には何か対策が必要だったりするかもしれません。
いずれにせよ、今後の CI/CD のワークフローファイルについては、デファクトスタンダードが何になるのかわからないところです。ですから、こうやって、いろいろなワークフローファイルを見ておくことは良いことだと考えています。
Discussion