タイトルは「実行可能な Docker イメージ」の間違いではありません。「実行可能な Dockerfile」で正解です。実行するとこのようにイメージのビルドが走ります:
chmod +x Dockerfile
./Dockerfile
仕掛けは単純で、シバンで docker build
を呼び出しているだけです:
#!/usr/bin/env -S docker build . -f
# syntax=docker/dockerfile:1.5.0
FROM busybox
Dockerfile は #
で始まる行がコメントとして扱われるため、1 行目のコメントとしてシバンを仕込めるわけですね。
env
コマンドの -S
オプションはシバン行で複数の引数を渡すのに使用されます。このオプションを付加しないと docker build . -f
で 1 コマンド扱いとなり No such file or directory
となります。
/usr/bin/env: `docker build . -f': そのようなファイルやディレクトリはありません
/usr/bin/env: shebang 行でオプションを渡すには -[v]S を使ってください
docker build
の -f
オプションは Dockerfile のパスを指定するものです。シバン行で指定されたインタプリタには実行されたファイルのパスが渡されるので、これを -f
オプションで受けられる順番にしています。
syntax
ディレクティブとの相性問題(解決済み)
このトリックは以前から使用可能だったのですが、syntax
ディレクティブとの相性問題がありました。syntax
ディレクティブは通常 1 行目にありますが、シバンを書くと 2 行目に移動してしまいます。この結果、Buildkit はその行を syntax
ディレクティブではなく通常のコメントとして理解し、拡張構文が使用できない状態になってました。
この点について、2023-01-10 リリースの Dockerfile v1.5.0 で syntax
ディレクティブの拡張が行われ、シバン行の次にある場合でも理解されるようになりました。同時に // syntax = ...
や { "syntax": "..." }
といった形式の表記も理解されるようになっています:
// DetectSyntax returns the syntax of provided input.
//
// The traditional dockerfile directives '# syntax = ...' are used by default,
// however, the function will also fallback to c-style directives '// syntax = ...'
// and json-encoded directives '{ "syntax": "..." }'. Finally, starting lines
// with '#!' are treated as shebangs and ignored.
//
// This allows for a flexible range of input formats, and appropriate syntax
// selection.
Buildkit には同日リリースの v0.11.0 でビルトインされ、Docker Engine には 2023-05-17 リリースの v24.0 で取り込まれました。
Dockerfile が実行可能であることのメリットは正直あまりないですが、タグ等 docker build
に渡してほしいオプションを明示する際には使えそうです:
#!/usr/bin/env -S docker build --no-cache --progress plain --tag tag --build-arg KEY=build-time . -f
# syntax=docker/dockerfile:1.5.0
FROM busybox
ARG KEY
RUN echo $KEY
なお、ARG
についてはこんなことをしなくても ARG KEY=value
形式でデフォルト値を明示可能です。