Parser directive
Parser directiveの実体はDockerfileの先頭行に記述する特殊なコメントで、Dockerfileの後続行の処理方法に影響する。
syntax
とescape
の2種類のパーサーディレクティブが存在する。
syntax
実はDockerfile 内で使用される構文は交換可能で、syntaxで構文の処理方法を指定することができる。例えば、以下のように先頭行に# syntax=docker/dockerfile:1
と記述することで、Dockerfile内でヒアドキュメントを使用できるようになる。
# syntax=docker/dockerfile:1 FROM golang:1.21 as build WORKDIR /src COPY <<-EOF /src/main.go package main import "fmt" func main() { fmt.Println("hello, world") } EOF RUN go build -o /bin/hello ./main.go
docker/dockerfile
イメージにより、BuildKitを使用してイメージをビルドできるようになる。ちなみにBuildKitとは、コンテナをビルドするためのデーモンらしい。
BuildKit とは、コンテナをビルドするためのツールキットであり、 buildkitdというデーモンとbuildctlコマンドで構成されています。 Dockerの標準のビルドと比べて、BuildKitでビルドした場合には以下のようなメリットがあります。
- マルチステージDockerfileの各ステージを並列ビルドできる
- ビルドキャッシュをDockerHubなどに外部保存/再利用ができる
- SSH接続でリモートのファイルを取得
- 秘密鍵などのファイルをイメージ内に残さないようにマウント
また、BuildKitの一部機能はDocker 18.06以降のDocker Engineに統合されており、 Docker単体でもBuildKitの一部機能を利用することができます。
syntaxはDockerfile Frontendとも呼ばれる。syntaxで外部のDockerfile frontend(dockerfile
というDockerイメージ)を指定することで、構文処理の方法を変更することができる。BuildKitやDocker Engineをアップグレードしなくても、最新のDockerfile frontendを使用できる。
BuildKitは不使用のビルドステージを検知し、スキップする。例えば、次のようなDockerfileがあると、最終イメージはstage2
になる。stage2
はbase
ステージから作成され、stage1
は使われないステージになっている。このときBuildKitはbase
とstage2
のみ処理し、依存関係のないstage1
はスキップされる。一方、レガシーのビルダーでは、stage1
も含め全てのステージが処理される。
# syntax=docker/dockerfile:1 FROM ubuntu AS base RUN echo "base" FROM base AS stage1 RUN echo "stage1" FROM base AS stage2 RUN echo "stage2"
escape
escapeは、エスケープ文字を指定するために使用するパサーディレクティブ。デフォルトのエスケープ文字はバックスラッシュ\
で、変更したい場合に使用するが、あまり用途はない気がする。
# escape=\