Dagger の調査と試行錯誤
参考
躓いたところ
dagger project init
& dagger project update
でプロジェクトを作成・更新しないと ./*.cue
が読み込まれない。
公式ドキュメント を読むと、CUE の定義ファイルを作成すると、dagger do --help
に指定したアクションが表示されるようになると記載されているが、何も表示されなかった。
プロジェクトルートで、dagger project init
& dagger project update
を実行すると、cue.mod
ディレクトリが作成され、その中に必要なライブラリが入ってくる。
利用状況によらず、大量の標準ライブラリ(?)がコピーされるので、git 管理せずにCI上では毎回 dagger project init
& dagger project update
を実行するのがいいのではないかと感じたが、まだわからない。
dagger do
で読み込まれる CUE は、カレントディレクトリの(おそらく)すべての *.cue
。
他のパスから読み込みたければ、 -p
オプションでパスを指定することができる。
.output
を取得するときは、一旦代入(?) して使う。
多くの定義済みアクションが .output
メンバーに結果を格納しているので、次のアクションで利用することが多々ある。
この時、無精をして直接アクセスしようとするとうまく行かなかった。
#MyAction {
(省略)
output: core.#Subdir & {
input: _build.output.rootfs
path: "dist"
}.output
}
#MyAction {
(省略)
dir: core.#Subdir & {
input: _build.output.rootfs
path: "dist"
}
output: dir.output
}
docker.#Build
コンテナ上での一連の処理は、 Go 用には、#Build
や #Test
が用意されている (参照)が、
Python向けには Alpine上でPythonスクリプトを実行する #Run しか用意されていない。(参照)
docker.#Build
は、 [#Step, ... #Step]
(#Step
の一つ以上の配列) 型の steps
を指定することで処理を記述できる。(結構面倒。)
docker.#Dockerfile
(参照)または docker.#Pull
(参照)でベースイメージを作成して、 docker.#Copy
でプロジェクトから必要なファイルをコピーして、docker.#Run
を必要な回数実行する流れになるだろう。
import (
"dagger.io/dagger"
"universe.dagger.io/docker"
)
dagger.#Plan {
client: filesystem: ".": {
read: { exclude: [".git", ".github", "cue.mod", "dist"] }
}
actions: {
build: {
docker.#Build & {
steps: [
docker.#Dockerfile & {
source: client.filesystem.".".read.contents
},
docker.#Copy & {
contents: client.filesystem.".".read.contents
},
docker.#Run & {
command: {
name: "pip3"
args: ["install", "."]
}
}
]
}
}
}
}
docker.#Pull
の方のサンプルは、公式の alpine.#Build
が参考になる。
("\(変数)
" で、変数を文字列に埋め込めるのも大変役に立つ情報でした。)
まだうまく行っていない点
✅ Docker 内部で生成したファイル・ディレクトリの外部への出力
dagger.#Plan
の client.filesystem
は、パスを(おそらく)1つのみ指定で、read
と write
をその下にもつ構造になっている。
そのため、柔軟にして指定しづらく、レポジトリからのファイル入力に利用すると、write
の公式サンプルにあるような書き方を実現できない。
追記: 書いてから気が付きましたが、定義が [path=string]
と鉤括弧がついているのでこれは配列が指定できそうかも。
別の手段として、 docker.#Run
の mounts
を利用しようかと思ったが、何を間違えているのかエラーになってしまってうまくできていない。
追記:
dagger.#FS
を action の .output
として clients.filesysten."<path>".write.contents
に渡すと書き出せた。(mounts はまだうまく書き出せていない。。。)
dagger.#Plan & {
client: filesystem: {
"dist": write: contents: actions.wheel.output
}
actions: {
wheel: {
(省略)
}
}
}
クロスコンパイル
dagger が CIプラットフォームに依存しないマルチプラットフォームを謳っているが、そもそも docker のコンテナをベースにしているため、Linux向けのビルド・テストしか実行できなさそう?
(daggerの実装に使われていると思われる) go はたしかクロスコンパイルが簡単だった気がしますが、Python他だとそういうわけにも行かない。
Windows や macOS でのテストやバイナリビルドは依然として、各CIプラットフォームから抜けられない?
私には中々しんどかったので、 dagger.io ではなく次の記事のようにしてみます。