RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

Daggerを使ったprogrammable CI/CD

はじめに

こんにちは! エンジニア2年目のTKDSです!
この記事ではDaggerについて紹介します。
この記事は課内で行ったLTをもとにしたものです。

Daggerとは?

  • CIの関数(Dagger Function)化
  • 関数をCLISDK、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の特徴は以下の三点です。

  1. 再現性(Reproducibility) 毎回同じ方法で実行され、実行環境外との依存関係が発生しません。
  2. キャッシュ(Caching) 実行結果をキャッシュすることで、実行を高速化できます。
  3. セキュリティ(Security) デフォルトではホスト環境(ホストファイル、ディレクトリ、環境変数など)にアクセスできません。

特に便利なのは、再現性とセキュリティの特徴です。
Daggerはコンテナ内で実行され、デフォルトで実行可能な操作の権限が制限されているため、セキュリティが強化されます。
また、CI実行環境がコンテナ単位で独立しているため、ホスト環境や他のコンテナに依存せず、実行環境外との依存関係が発生しません。

Dagger Module

前述のDagger Functionをまとめたものです。
他の人が作ったものを利用することもでき、CIの再利用性を高めてくれます。

実際につかってみる

現在のドキュメントでは以下のSDKが記載されています。

今回はこの中で一番好きな言語である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の起動状態を意識することなくテストが実行可能です。
また、コンテナを破棄すれば状態をリセットできるため、フレーキーテストなどの削減などにも役に立つのではないかと感じました。
今回の記事は以上です。
ここまで読んでいただきありがとうございました!

Copyright © RAKUS Co., Ltd. All rights reserved.