ドッカーファイルのヘアドキュメントの紹介

Dockerコミュニティメンバーのジャスティンチャデルによるゲスト投稿。 この投稿はもともと掲載されました ここは.

数週間前の時点で、DockerファイルをビルドするためのDockerのBuildKitツールが heredoc構文をサポートするようになりました! これらの新しい改善により、各行の最後に厄介なバックスラ ッシュを必要とせずに 、複数行 RUN のsや小さなインライン構成ファイルの作成など、以前は困難だったあらゆる種類のことを実行できます。

この投稿では、これらのヒアドキュメントとは何かの基本、さらに重要なことに、それらを何に使用できるか、そしてそれらを使い始める方法について説明します。 🎉

クジラ ロゴ332 5

ビルドキット (クイック リフレッシャー)

BuildKit 独自の github から:

BuildKit は、ソースコードを変換して、効率的で表現力豊かで反復可能な方法でアーティファクトを構築するためのツールキットです。

基本的に、これはDockerイメージ用の次世代ビルダーであり、メインのDockerランタイムの残りの部分からきちんと分離されています。Dockerイメージまたは他のOCIランタイムのイメージの構築に使用できます。

きちんとしたビルドログ出力、より高速でキャッシュ効率の高いビルド、同時ビルド、簡単な拡張性を可能にする 非常に 柔軟なアーキテクチャなど、基本的なビルダーがサポートするものを超える多くの便利な(そしてきれいな)機能が付属しています(私は間違いなくそれをやっていません正義)。

あなたはおそらくすでにそれを使用しているか、おそらく使用したいと思っています! 実行時に環境変数 DOCKER_BUILDKIT=1 docker buildを設定してローカルで有効にするか、new(ish) docker buildx コマンドを使用するように切り替えることができます。

もう少し技術的なレベルでは、buildkitを使用すると、ローカルまたはリモート、Dockerデーモン自体、Dockerコンテナ、さらにはKubernetesポッド内の複数の異なる「ビルダー」を簡単に切り替えることができます。 ビルダー自体は、フロントエンドとバックエンドの2つの主要な部分に分かれています:フロントエンドは中間の低レベルビルダー(LLB)コードを生成し、バックエンドによってイメージに構築されます。

LLB から BuildKit への変換は、LLVM IR が Clang に対するものと考えることができます。

buildkitを非常に素晴らしいものにしている理由の一部は、柔軟性です–これらのコンポーネントは互いに完全に切り離されているため、どのイメージでも任意のフロントエンドを使用できます。 たとえば、既定の Dockerfile フロントエンドを使用したり、独自の自己完結型 ビルドパックをコンパイルしたり、 Mockerfile などの独自の代替ファイル形式を開発したりすることもできます。

セットアップ

ヒアドキュメントの使用を開始するには、まず ビルドキットでセットアップしていることを確認してください。 buildkitに切り替えると、ビルドセットアップにすぐに使用できる多くの改善が加えられ、古いビルダーとの完全な互換性がある はずです (気に入らない場合はいつでも元に戻すことができます)。

buildkitを適切にセットアップすると、このファイルの先頭に新しいもの Dockerfile: を作成できますが、ディレクティブを含める #syntax= 必要があります。 このディレクティブは、特定のフロントエンド(この場合はDocker Hubにあるフロントエンド docker/dockerfile:1.3-labs )を使用するようにパーサーに通知します。

# 構文=ドッカー/ドッカーファイル:1.3-ラボ

この行(最初の行でなければなりません)を使用すると、buildkitは適切なイメージを見つけてダウンロードし、それを使用してイメージをビルドします。

次に、ビルド元の基本イメージを指定します (通常どおり)。

から: 20.04

これらすべてが邪魔にならないように、ヒアドキュメントを使用して、同じコマンドで2つのコマンドを実行できます RUN!

RUN <<EOF
echo "Hello" >> /hello
echo "World!" >> /hello
EOF

なぜでしょうか。

heredocsが機能している今、あなたは疑問に思うかもしれません–なぜすべての大騒ぎ? さて、この機能は、これまで、Dockerfilesに欠けていました。

2017年にヒアドキュメントを提案した元の問題については、moby /moby#34423 を参照してください。

セットアップに 多くの コマンドを必要とするイメージを構築するとします。 たとえば、かなり一般的なパターン Dockerfiles では、システムを更新してから、いくつかの追加の依存関係、つまり一度にすべてをインストールします。 apt update, upgrade install

素朴に、これらすべてを別々の RUNsとして配置するかもしれません:

RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y ...

しかし、悲しいことに、あまりにも多くの直感的なソリューションのように、これは私たちが望むことを完全には行いません。 それは確かに機能しますが、それぞれ RUNに新しいレイヤーを作成し、画像を必要以上に大きくします(ビルドにははるかに時間がかかります)。

したがって、これを単一の RUN コマンドに押しつぶすことができます。

RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y ...

そして、それは、公式のDockerイメージから私が自分のために書いた厄介なものまで、今日ほとんどの Dockerfile人が行っていることです。 それはうまく動作し、画像は小さく、構築が高速です...しかし、それは少し醜いように見えます。 また、誤って行連結記号\を忘れると、構文エラーが発生します。

ヒアドキュメントはこれを改善するための次のステップです! 今、私たちはただ書くことができます:

RUN <<EOF
apt-get update
apt-get upgrade -y
apt-get install -y ...
EOF

<<EOF を使用してヒアドキュメントを紹介し(sh / bash / zsh /選択したシェルのように)、 EOF 最後にそれを閉じます。それらの間に、シェルによって実行されるスクリプトのコンテンツとしてすべてのコマンドを配置します。

その他の実行方法...

ここまでは、いくつかの基本的な構文を見てきました。 ただし、新しいheredocサポートでは、簡単な例だけでなく、他にも楽しいことがたくさんあります。

完全を期すために、すでに見たのと同じ構文を使用したhello worldの例:

RUN <<EOF
echo "Hello" >> /hello
echo "World!" >> /hello
EOF

しかし、セットアップスクリプトがより複雑になり、Pythonなどの別の言語を使用したいとします。 まあ、問題ありません、あなたは接続することができます heredocs 他のプログラムに!

RUN python3 <<EOF
with open("/hello", "w") as f:
    print("Hello", file=f)
    print("World", file=f)
EOF

実際、heredocsを使用すると、複雑なコマンドを好きなだけ使用して、上記を次のように簡略化できます。

RUN python3 <<EOF > /hello
print("Hello")
print("World")
EOF

それが少し面倒または複雑になっているように感じる場合は、いつでもシバンを使用することもできます。

RUN <<EOF
#!/usr/bin/env python3
with open("/hello", "w") as f:
    print("Hello", file=f)
    print("World", file=f)
EOF

heredocsをRUNに接続するにはさまざまな方法があり、将来的にはさらにいくつかの方法と改善が行われることを願っています。

...そしていくつかのファイルの楽しみ!

sのheredocs Dockerfileでは、インラインファイルをいじくり回すこともできます。 nginxサイトを構築していて、カスタムインデックスページを作成したいとします。

FROM nginx

COPY index.html /usr/share/nginx/html

そして、別のファイルで index.html、 あなたはあなたのコンテンツを置きます。 しかし、インデックスページが本当に単純な場合、すべてを分離する必要があるのはイライラします:heredocsを使用すると、必要に応じてすべてを同じ場所に保持できます。

FROM nginx

COPY <<EOF /usr/share/nginx/html/index.html
(your index page goes here)
EOF

複数のファイルを一度に 1 つのレイヤーにコピーすることもできます。

COPY <<robots.txt <<humans.txt /usr/share/nginx/html/
(robots content)
robots.txt
(humans content)
humans.txt

仕上げ

うまくいけば、私はあなたができるときにheredocsを試してみるようにあなたを説得することができました! 今のところ、それらはまだステージングフロントエンドでのみ利用可能ですが、 すぐに リリースに入るはずですので、必ず見てフィードバックをお寄せください!興味があれば、公式のビルドキットDockerfile 構文ガイドから詳細を知ることができます。