Dockerfileのテンプレートを作るCLIを作った話

August 27, 2022


初めに

個人開発で Docker を使っているのですが、毎回 Dockerfile を作るのが めんどくさくなったのでテンプレを用意しました。

とりあえずソースコードです https://github.com/komisan19/kuzira

使い方

initコマンドを叩くと空の Dockerfile が作成でき、 createコマンド+言語を指定するとテンプレートの言語が作成されます。

$ kuzira init
$ ls Dockerfile
Dockerfile

---

$ kuzira create go
create Dockerfile for Golang

仕組み

CLI は以下のライブラリを使っていますが、テンプレートは embed を使ってみました。 https://github.com/urfave/cli

go:embed

Go1.16 から追加された機能です。 go:embed はその意味の通り埋め込みができます。1.16 以前もosio/ioutilで読み込みなどできましたが、embed を使うとgo build時にバイナリに埋め込むことができます。

工夫点

上記でも記載しましたが、go:embed を使っています。 そのため、今回はこのような形でテンプレートファイルをおいて参照するようにしました。

.
├── README.md
├── action
│   ├── cli.go
│   └── cookbook
│       ├── go-dockerfile
│       └── python-dockerfile
---

cookboo k内にテンプレートファイルを置くようにしました。 そして cli.go にこのような形で書きました。

package action

import (
        "embed"
        "fmt"
        "github.com/urfave/cli"
        "log"
        "os"
)

//go:embed cookbook/*
var cookbook embed.FS

func Create(c *cli.Context) {
        switch os.Args[2] {
        case "go":
                rd, err := cookbook.ReadFile("cookbook/go-dockerfile")
                if err != nil {
                        log.Fatal(err)
                }
                err = os.WriteFile("Dockerfile", rd, 0644)
                if err != nil {
                        log.Fatal(err)
                }
                fmt.Println("create Dockerfile for Golang")
...
}

embed の特徴はここです

//go:embed cookbook/*
var cookbook embed.FS

//go:embed cookbook/*を指定することでその参照したいファイルを選択できます。 例えば//go:embed index.htmlとすることで実行ファイルの index.html を参照することができます。参照ができたら、以下のように書くことでファイルの中身を読み込むことができます。

rd, err := cookbook.ReadFile("cookbook/go-dockerfile")

改善点

今後はこのあたりを改善していこうと思います。

  1. テンプレートが少ない(Go,python のみ)
  2. 言語が増えると switch が増えてしまう
  3. 自分でカスタマイズできない。

まとめ

久しぶりに CLI を作成したのですが、embed ができてからテンプレートの埋め込みがだいぶ楽になりました。 まだまだ改善点が多いですが、今後も CLI を作っていこうと思います。




© 2023 komisan19 All Rights Reserved.