はじめに
こんにちは!
エンジニア2年目のTKDSです!
この記事ではDaggerについて紹介します。
この記事は課内で行ったLTをもとにしたものです。
Daggerとは?
- CIの関数(Dagger Function)化
- 関数をCLI、SDK、HTTPリクエストなどから実行可能
- 関数→モジュールにして再利用可能
- 既存のモジュール(自分や他人が作ったもの)を再利用可能
- 一度書けばどこでも(ローカルPC、Actionsなど)実行可能
以上の特徴を持つ、コンテナ内でパイプラインを実行する、プログラム可能なCI/CD エンジンです。
アーキテクチャ概要
Daggerを構成する要素は以下の図のとおりです。
GraphQL ServerがDagger Engine内の各要素を操作します。
コンテナの実行、ファイルやディレクトリとのやり取りなど基本的な操作はCore APIとして用意してあり、そこに作成したDagger Module(CI の塊:Dagger Function)を追加して、CIを実行可能にします。
Dagger Function
CIの手順はDagger Engineが生成したコンテナ内で実行されます。
Dagger Functionの特徴は以下の三点です。
- 再現性(Reproducibility) 毎回同じ方法で実行され、実行環境外との依存関係が発生しません。
- キャッシュ(Caching) 実行結果をキャッシュすることで、実行を高速化できます。
- セキュリティ(Security) デフォルトではホスト環境(ホストファイル、ディレクトリ、環境変数など)にアクセスできません。
特に便利なのは、再現性とセキュリティの特徴です。
Daggerはコンテナ内で実行され、デフォルトで実行可能な操作の権限が制限されているため、セキュリティが強化されます。
また、CI実行環境がコンテナ単位で独立しているため、ホスト環境や他のコンテナに依存せず、実行環境外との依存関係が発生しません。
Dagger Module
前述のDagger Functionをまとめたものです。
他の人が作ったものを利用することもでき、CIの再利用性を高めてくれます。
実際につかってみる
- Go
- Python
- TypeScript
今回はこの中で一番好きな言語であるGoを使います。
インストール方法などは公式ドキュメントを参考にしてください。
ユースケース1:テストのパイプラインを記述
1つめは操作の流れをコードに書き、Dagger CLIから実行する使い方です。
以下の画像のようにGoのコードで行う操作を記述します。各操作は次のとおりです。
- Container().From : 新規のコンテナ作成
- WithExec():コンテナ内で実行されるコマンド. 引数に変数の値を引き渡せる
- Container.Stdout() : 標準出力
dagger call scan-image --image-ref alpine:latest
上記のコマンドを実行すると結果は以下のように出力されます。
alpine:latest (alpine 3.19.1) ============================= Total: 2 (UNKNOWN: 0, LOW: 2, MEDIUM: 0, HIGH: 0, CRITICAL: 0) ┌────────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬───────────────────────────────────────────────────────────┐ │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │ ├────────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼───────────────────────────────────────────────────────────┤ │ libcrypto3 │ CVE-2024-2511 │ LOW │ fixed │ 3.1.4-r5 │ 3.1.4-r6 │ openssl: Unbounded memory growth with session handling in │ │ │ │ │ │ │ │ TLSv1.3 │ │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2024-2511 │ ├────────────┤ │ │ │ │ │ │ │ libssl3 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴───────────────────────────────────────────────────────────┘
脆弱性チェックのCIを実行することができました。
ユースケース2:DB依存の単体テストでDBのコンテナを用意する
2つ目は、コンテナの操作を直接テストコード内に書く使い方です。
実はDaggerのgo sdkはGoのコード内に記述しておくことで、Dagger CLIを使わずに実行することが可能です。
以下のようにテストコードを用意します。
実行結果は以下のとおりです。 Daggerを使って、単体テストのコード内にDBを用意するコードを記述して実行することができました!
まとめ
今回はDaggerを紹介しました。
個人的には、ユースケース2のDB依存のテストケースにコンテナ起動まで記述する使い方がおすすめです!
今までは、別でコンテナを起動してテストを実行する必要がありましたが、Daggerを使えば、特にDBの起動状態を意識することなくテストが実行可能です。
また、コンテナを破棄すれば状態をリセットできるため、フレーキーテストなどの削減などにも役に立つのではないかと感じました。
今回の記事は以上です。
ここまで読んでいただきありがとうございました!