ksaitoの日記

日々試したことの覚え書き

Dockerfileでexitステータスが0以外を返す処理を扱う

Dockerfileで外部のシェルを実行する場合に、そのシェルが正常終了したのに終了ステータスが0以外を返すことがあります。 dockerは、0以外のステータスが返されるとビルドが失敗したと判断して処理を中断してしまいます。

Dockerfileを下記のように記載することで、ステータスを正しく認識してビルドを完了させることができます。

サンプル

lsコマンドで存在しないファイル名を指定すると終了ステータスは、2になります。

$ ls sadfasf
ls: 'sadfasf' にアクセスできません: そのようなファイルやディレクトリはありません
$?
2
$

このコマンドを外部シェルに見立ててDockerfileを作成します。 3行目の|| RET=$?で終了ステータスをRETに保持し、|| trueで終了ステータスに関係なく処理を正常終了させます。 4行目の&& test $RET -eq 2で0以外で正常と判断するステータスを検査します。

$ cat -n Dockerfile
     1  FROM oraclelinux:7-slim
     2
     3  RUN ls sadfasf || RET=$? || true \
     4   && test $RET -eq 2
$

下記のように正しくビルドできます。

$ docker build -t test .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM oraclelinux:7-slim
 ---> c0feb50f7527
Step 2/2 : RUN ls asdfa || RET=$? || true  && test $RET -eq 2
 ---> Using cache
 ---> cb6a5b73e7a1
Successfully built cb6a5b73e7a1
$

2行目を書き換えて、存在するパスを指定します。

$ cat -n Dockerfile
     1  FROM oraclelinux:7-slim
     2
     3  RUN ls / || RET=$? || true \
     4   && test $RET -eq 2
$

終了ステータスが0になるとエラーと判断してビルドに失敗します。 これで、どのようなステータスを返すシェルであっても正しく扱うことができます。

$ docker build -t test .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM oraclelinux:7-slim
 ---> c0feb50f7527
Step 2/2 : RUN ls / || RET=$? || true  && test $RET -eq 2
 ---> Running in 444fb925563a
/bin/sh: line 0: test: -eq: unary operator expected
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
The command '/bin/sh -c ls / || RET=$? || true  && test $RET -eq 2' returned a non-zero code: 2
$