kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Dockerfile で新しく使えるようになった構文「ヒアドキュメント」で複数行の RUN をシュッと書く

2021年7月30日に Docker Blog に公開された以下の記事を参考にDockerfile で新しく使えるようになった構文 "heredocs"」を試す.Dockerfile「ヒアドキュメント」を使うと,今まで RUN&& \ を組み合わせて複数コマンドを 1 レイヤーにまとめていた Tips を使わずにシュッと書けるようになる.なんと!

www.docker.com

なお RUN&& \ を組み合わせる Tips は Intro Guide to Dockerfile Best Practices「Tip #3: Identify cacheable units such as apt-get update & install」として紹介されていたり,とてもよく知られていると思う.

www.docker.com

検証用 Dockerfile

今回は以下のように3種類の検証用 Dockerfile を作った.あくまで検証として Amazon Linux 2 をベースに yum コマンドで適当にパッケージをインストールをしている.ヒアドキュメントを使うと 3-heredocs/Dockerfile のようにシュッと Dockerfile を書けるようになる.大きく差はなく見えるかもしれないけど,可読性は高くなるし,今まで \ を書き忘れるとエラーになっていたし,とても便利だと思う!

  • 1-base/Dockerfile : コマンドごとに RUN を書く
  • 2-backslash/Dockerfile : RUN&& \ を組み合わせる
  • 3-heredocs/Dockerfile : ヒアドキュメントを使う
$ tree .
.
├── 1-base
│   └── Dockerfile
├── 2-backslash
│   └── Dockerfile
└── 3-heredocs
    └── Dockerfile

3 directories, 3 files

🐳 1-base/Dockerfile

FROM amazonlinux:2

RUN yum update -y
RUN yum install -y git
RUN yum install -y tree
RUN yum install -y jq
RUN yum install -y wget
RUN rm -rf /var/cache/yum

🐳 2-backslash/Dockerfile

FROM amazonlinux:2

RUN yum update -y && \
    yum install -y git && \
    yum install -y tree && \
    yum install -y jq && \
    yum install -y wget && \
    rm -rf /var/cache/yum

🐳 3-heredocs/Dockerfile

# syntax = docker/dockerfile:1.3-labs
FROM amazonlinux:2

RUN <<EOF
  yum update -y
  yum install -y git
  yum install -y tree
  yum install -y jq
  yum install -y wget
  rm -rf /var/cache/yum
EOF

BuildKit を使ってビルドをする

「ヒアドキュメント」を使った Dockerfile をビルドするためには BuildKit を使う必要がある.以下のように DOCKER_BUILDKIT=1 環境変数を有効化して docker build コマンドを実行したり,docker buildx build コマンドを実行する.またデフォルトで BuildKit を有効化するなら /etc/docker/daemon.json に設定を追加することもできる.詳しくは以下のサイトに載っている!

$ DOCKER_BUILDKIT=1 docker build .
$ docker buildx build .

docs.docker.com

実際にビルドをすると 2-backslash3-heredocsRUN&& \ を組み合わせなくても同じイメージサイズになっていた.docker history コマンドの結果も参考までに載せておく.レイヤー数もまとまっている!

$ docker build -t my-image:1-base 1-base/.

$ docker build -t my-image:2-backslash 2-backslash/.

$ DOCKER_BUILDKIT=1 docker build -t my-image:3-heredocs 3-heredocs/.

$ docker images my-image
REPOSITORY   TAG           IMAGE ID       CREATED             SIZE
my-image     1-base        16997f0cd75b   About an hour ago   1.62GB
my-image     2-backslash   de739b8af746   About an hour ago   330MB
my-image     3-heredocs    c0ec07c5bc12   About an hour ago   330MB

$ docker history my-image:2-backslash
IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
de739b8af746   About an hour ago   /bin/sh -c yum update -y &&     yum install …   167MB
d85ab0980c91   5 days ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>      5 days ago          /bin/sh -c #(nop) ADD file:4cbe5850096b1ae39…   163MB

$ docker history my-image:3-heredocs
IMAGE            CREATED             CREATED BY   SIZE      COMMENT
c0ec07c5bc12     About an hour ago   RUN /bin/sh -c   yum update -y
  yum install…   167MB               buildkit.dockerfile.v0
<missing>        5 days ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>        5 days ago          /bin/sh -c #(nop) ADD file:4cbe5850096b1ae39…   163MB

ヒアドキュメントを活用して Dockerfile でファイルを作る

Docker Blog の記事を読んでいたら「ヒアドキュメント」を活用して「インラインファイル」を作れると書いてあった.具体的には以下のように nginx に置く index.html をファイルとして COPY するのではなく,直接 Dockerfile に書くことができる.ようするに「ヒアドキュメント」RUN だけでなく COPY にも使える.過剰に使うと読みにくくなるだろうけど,簡単に試す場面なら良さそう.

# syntax = docker/dockerfile:1.3-labs
FROM nginx:1.21-alpine

COPY <<EOF /usr/share/nginx/html/index.html
  <html>
    <body>
      <h1>kakakakakku blog</h1>
    </body>
  </html>
EOF

まとめ

Dockerfile で新しく使えるようになった構文「ヒアドキュメント」を試した.今まで RUN&& \ を組み合わせて複数コマンドを 1 レイヤーにまとめていた Tips を使わずにシュッと書けて便利💡

関連記事

レイヤーを減らすために docker build コマンドで --squash オプションを使うこともできる.2019年に紹介したけど,現在も「Experimental(実験的機能)」のままだった.参考に載せておく!

kakakakakku.hatenablog.com