tl; dr
- Dockerfile の heredoc 機能の中で凝ったことをやるときはコマンド群の最初に
set -e
とか書くのが無難そう
近年 Dockerfile 内で heredoc 記法が使えるようになったことが知られていて、
割と凝ったことができる機能で、シンプルには以下のように RUN
にずらずら書くときシュッと書けて便利、というのがわかりやすいと思う。
思うんだけど、こういうふうに heredoc の中でなんかミスってしまったときに何が起こるかというと、
# syntax=docker/dockerfile:1.3-labsFROM debian RUN <<EOF apt-get install packagewhichdoesnotexists ls EOF
こういう感じで docker build
は成功扱いになってしまう。
% docker build --no-cache . [+] Building 2.2s (10/10) FINISHED => [internal] load build definition from Dockerfile 0.0s (中略) => CACHED [1/2] FROM docker.io/library/debian@sha256:2ce44bbc00a79113c296d9d25524e15d423b23303fdbbe20190d2f96e0aeb251 0.0s => [2/2] RUN <<EOF (apt-get install packagewhichdoesnotexists...) 0.3s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:e62007bb070cd3bacbf16cb21cdca776022865ee5f8a7b7ca4f037dd712f1230 0.0s
Debianに packagewhichdoesnotexists パッケージが存在するわけもなく、直感的には docker build
が失敗してほしいと思うんだけど、成功扱いになってしまう……。
実装された p-r を見てみると、上記のように RUN
に素朴に heredoc を渡した場合は、その中身が sh -c
で実行される、という雰囲気になっているように見えた。heredoc の中身がそのままシェルスクリプトとして実行されるようなものと捉えればよいだろうか。
という話を同僚の id:dekokunさんとしていて、set -e
してみたらどうなるかという話になるわけだけど、こうするとしっかり docker build は失敗してくれた。
# syntax=docker/dockerfile:1.3-labsFROM debian RUN <<EOF set -e apt-get install packagewhichdoesnotexists ls EOF
% docker build --no-cache . [+] Building 3.2s (9/9) FINISHED => [internal] load build definition from Dockerfile 0.0s (中略) => CACHED [1/2] FROM docker.io/library/debian@sha256:2ce44bbc00a79113c296d9d25524e15d423b23303fdbbe20190d2f96e0aeb251 0.0s => ERROR [2/2] RUN <<EOF (set -e...) 0.3s ------ > [2/2] RUN <<EOF (set -e...): #9 0.229 Reading package lists... #9 0.237 Building dependency tree... #9 0.239 Reading state information... #9 0.241 E: Unable to locate package packagewhichdoesnotexists ------ executor failed running [/bin/sh -c set -e apt-get install packagewhichdoesnotexists ls ]: exit code: 100
完全に忘れてたけどこういう話もある!
Dockerfile の RUN instruction で heredoc 記法を使うときには set -e しないとコマンドが non-zero exit status で死んでも docker build が成功してしまう - polamjaggy nikkib.hatena.ne.jp-o pipefail とかも欲しくなるやつ?(わかってない)
2022/07/27 20:05
これも docker build
成功してしまうけど、
# syntax=docker/dockerfile:1.3-labsFROM debian RUN <<EOF set -e apt-get install packagewhichdoesnotexists | cat ls EOF
Debianではこれは dash で実行されていて、こういう話になってしまう!
マジで /bin/shが決め打ちで呼び出されてるんだけど、Debianだとそいつは dash で、dash には -o pipefail とか無いっぽいという感じになってきて盛り上がりを感じる https://t.co/RMTwfp51kF
— ガソリン車 (@polamjag) 2022年7月27日
Dockerfile 内でこれをやりたい人はいないでしょって感じで厳しい……。