Help us understand the problem. What is going on with this article?

DockerfileをLintする

More than 3 years have passed since last update.

DockerfileをLintする場合はHadolintがオススメです。
Haskell Dockerfile Linterの略で、文字通りHaskellで実装されています。

Macで使ってみる

$ brew install hadolint
$ hadolint Dockerfile

これだけでDockerfileの静的解析が可能です。
特定のルールだけ除外してチェックしたい場合は下記のように実行します。

$ hadolint --ignore DL3003 --ignore DL3006 Dockerfile

ルール

DL3000

WORKDIRを使用する際は絶対パスを使う。

# BAD
WORKDIR usr/src/app

# GOOD
WORKDIR /usr/src/app

DL3001

意味のないbashコマンド(ssh, vim, shutdown, service, ps, free, top, kill, mount, ifconfig)を使わない。

# BAD
FROM busybox
RUN top

# GOOD
FROM busybox

DL3002

rootユーザを使わない。

# BAD
FROM busybox
USER root

# GOOD
FROM busybox

DL3003

ディレクトリの変更はWORKDIRを使う。

# BAD
FROM busybox
RUN cd /usr/src/app

# GOOD
FROM busybox
WORKDIR /usr/src/app

DL3004

sudoを使わない。

# BAD
FROM busybox
RUN sudo apt-get install

# GOOD
FROM busybox
RUN apt-get install

DL3005

apt-getupgrade, dist-upgradeを使わない。

# BAD
FROM debian
RUN apt-get update && apt-get upgrade 

# GOOD
FROM debian
RUN apt-get update

DL3006

イメージのバージョンには明示的にタグを付ける。

# BAD
FROM debian

# GOOD
FROM debian:jessie

DL3007

イメージタグにlatestを使わず明示的にリリースタグを使う。

# BAD
FROM debian:latest

# GOOD
FROM debian:jessie

DL3008

apt get installをする際はバージョンを固定する。

# BAD
RUN apt-get install python

# GOOD
RUN apt-get install python=2.7

DL3009

apt-get installの後にlistを削除する。

# BAD
RUN apt-get update && apt-get install -y python

# GOOD
RUN apt-get update && apt-get install -y python \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

DL3011

0から65535のポートを使う。

# BAD
EXPOSE 80000

# GOOD
EXPOSE 65535

DL3012

メンテナの連絡先を記述する。

# BAD
MAINTAINER ktsujichan

# GOOD
MAINTAINER ktsujichan <ktsujichan@example.com>

DL3013

pipを使う際はバージョンを固定する。

# BAD
RUN pip install django

# GOOD
RUN pip install django==1.9

DL3014

-yを使う。

# BAD
RUN apt-get install python=2.7

# GOOD
RUN apt-get install -y python=2.7

DL3015

--no-install-recommendsを使う。

# BAD
RUN apt-get install -y python=2.7

# GOOD
RUN apt-get install -y --no-install-recommends python=2.7

DL3020

ADDよりCOPYを使う。

# BAD
ADD requirements.txt /usr/src/app/

# GOOD
COPY requirements.txt /usr/src/app/

DL4000

メンテナを記述する。

# BAD
FROM busybox

# GOOD
FROM busybox
MAINTAINER ktsujichan <ktsujichan@example.com>

DL4001

wgetcurlを併用しない。

# BAD
RUN wget http://google.com
RUN curl http://bing.com

# GOOD
RUN curl http://google.com
RUN curl http://bing.com

DL4003

複数のCMDを使わない。

# BAD
FROM busybox
CMD /bin/true
CMD /bin/false

# GOOD
FROM busybox
CMD /bin/true

DL4004

複数のENTRYPOINTを使わない。

# BAD
FROM busybox
ENTRYPOINT /bin/true
ENTRYPOINT /bin/false

# GOOD
FROM busybox
ENTRYPOINT /bin/true

DL4005

デフォルトのシェルを変更する場合はSHELLを使う。

# BAD
RUN apk add --update-cache bash=4.3.42-r3
RUN ln -sfv /bin/bash /bin/sh

# GOOD
RUN apk add --update-cache bash=4.3.42-r3
SHELL ["/bin/bash", "-c"]

SC1000

$はエスケープして使う。

# BAD
echo "$"

# GOOD
echo "\$"

SC1007

=の後のスペースを削除する。

# BAD
LANGUAGE= nl

# GOOD
LANGUAGE=nl

SC1010

doneの前にセミコロンまたは改行をする。

# BAD
for f in *; do echo "$f" done

# GOOD
for f in *; do echo "$f"; done

SC1035

スペースを入れる。

# BAD
if ![-z foo ]; then true; fi

# GOOD
if ! [ -z foo ]; then true; fi

SC1045

&;を併用しない。

# BAD
foo &; bar

# GOOD
foo & bar

SC1065

引数の処理は$nを使う。

# BAD
foo(input) {
  echo "$input"
}
foo("hello world");

# GOOD
foo() {
  echo "$1"
}
foo "hello world"

SC1066

変数の代入に$を使わない。

# BAD
$greeting="Hello World"

# GOOD
greeting="Hello World"

SC1068

=の前後にスペースを入れない。

# BAD
foo = 42

# GOOD
foo=42

SC1077

コマンド展開に´を使わない。

# BAD
echo "Your username is ´whoami´"

# GOOD
echo "Your username is $(whoami)"

SC1078

ダブルクオートの文字列を閉じ忘れしない。

# BAD
greeting="hello
target="world"

# GOOD
greeting="hello"
target="world"

SC1081

Ifではなくifを使う。

# BAD
If true
Then
  echo "hello"
Fi

# GOOD
if true
then
  echo "hello"
fi

SC1086

ループの反復変数に$を使わない。

# BAD
for $var in *
do
  echo "$var"
done

# GOOD
for var in *
do
  echo "$var"
done

SC1087

配列を展開する際は中括弧を使う。

# BAD
echo "$array[@]"

# GOOD
echo "${array[@]}"

SC1095

関数名と処理の間にスペースか改行を入れる。

# BAD
function foo{
  echo "hello world"
}

# GOOD
foo() {
  echo "hello world"
}

function foo {
  echo "hello world"
}

SC1097

==を使わず、代入の場合は=を、比較の場合は[ .. ]を使う。

# BAD
var==value

# GOOD
var=value
[ "$var" = value ]

SC1098

evalを使用する際は、特殊文字を引用/エスケープする。

# BAD
eval $var=(a b)

# GOOD
eval "$var=(a b)"

SC1099

#の前にスペースを入れる。

# BAD
while sleep 1
do# show time
  date
done

# GOOD
while sleep 1
do # show time
  date
done

SC2002

catを使わない。

# BAD
cat file | tr ' ' _ | grep a_
cat file | ( while read i; do echo "${i%?}"; done )

# GOOD
< file tr ' ' _ | grep a_  # **simple commands only, won't work with compounds
( while read i; do echo "${i%?}"; done ) < file # postfix works for everything

SC2015

A && B || Cのロジックは、AがtrueだとCが実行されるのでif-then-elseではない。

# BAD
[[ $dryrun ]] && echo "Would delete file" || rm file

# GOOD
if [[ $dryrun ]]
then
  echo "Would delete file"
else
  rm file
fi

SC2026

引用符の入れ子に注意する。

# BAD
alias server_uptime='ssh $host 'uptime -p''

# GOOD
alias server_uptime='ssh $host '"'uptime -p'"

SC2028

echoはエスケープを展開しないので、printfを使う。

# BAD
echo "Name:\t$value"

# GOOD
printf "Name:\t%s\n" "$value"

SC2035

./*glob*-- *glob*を使う。

# BAD
rm *

# GOOD
rm ./*

# GOOD
rm -- *

SC2046

単語を分割させないようにクオートを使う。

# BAD
ls -l $(getfilename)

# GOOD
ls -l "$(getfilename)"

getfilename | while IFS='' read -r line
do
  ls -l "$line"
done

SC2086

グロブと単語分割を防ぐためにダブルクオートを使う。

# BAD
echo $1
for i in $*; do :; done # this one and the next one also applies to expanding arrays.
for i in $@; do :; done

# GOOD
echo "$1"
for i in "$@"; do :; done # or, 'for i; do'

SC2140

引用符の入れ子に注意する。

# BAD
echo "<img src="foo.png" />" > file.html

# GOOD
echo "<img src=\"foo.png\" />" > file.html

SC2154

変数展開に注意する。

# BAD
var=name
n=42
echo "$var_$n.jpg"

# GOOD
var=name
n=42
echo "${var}_$n.jpg"

SC2164

cdで失敗したときのために終了する。

# BAD
cd generated_files
rm -r *.c

func(){
  cd foo
  do_something
}

# GOOD
cd generated_files || exit
rm -r *.c

func(){
  cd foo || return
  do_something
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away