Dockerfileのベストプラクティス8選
はじめに
Dockerfileを書く上で、Docker社の推奨するベストプラクティスを8つにまとめました。
ベストプラクティスに従うことによって、簡単・安全・効率的な、Dockerfileの作成を目指します。
Dockerのガイドライン
コンテナは、必要最小限(エフェメラル)であるべき。
Dockerfile で定義されたイメージを使って作成されるコンテナは、可能ならばエフェメラル(短命;ephemeral)にすべきです。私たちの「エフェメラル」とは、停止・破棄可能であり、明らかに最小のセットアップで構築して使えることを意味します。
Dockerfileベストプラクティス
1. Baseイメージは、公式の信頼できるものを使おう
特定の言語などを扱う場合は、公式が言語が入ったイメージを配布してくれている場合が多いので、そちらを使おう。
FROM ubuntu
RUN apt-get update && apt-get install -y node
FROM node
2. Baseイメージのバージョンを指定しよう
Baseイメージのバージョンが未指定だと、最新のバージョンがインストールされる。環境毎の再現性が低くなってしまう。
FROM node
FROM node:17.3.0
3. Baseイメージは、可能な限りミニマムなイメージを選ぼう
ミニマムだと、ビルド早いし、セキュリティリスクも減る。
alpine linux
のイメージが公式から配布されている場合は、積極的に選んだほうが良さそう。
FROM node:17.3.0
FROM node:17.3.0-alpine
4. Dockerのキャッシュレイヤーを最適化しよう
FROM node:17.3.0-alpine
WORKDIR /app
COPY myapp /app
RUN npm install
CMD ["node", "src/index.js"]
FROM node:17.3.0-alpine
WORKDIR /app
COPY package*.json .
RUN npm install
COPY myapp /app
CMD ["node", "src/index.js"]
実際にbuildしてみる
CACHEの効きを確かめるために、一度build
した後に、app/index.js
を編集して、再度build
してみた。
Badパターンの場合、「3/4」以降はCACHEが効いておらず、buildが走っている。特に、[4/4]npm install
が4.8sもかかってる。
Goodパターンの場合、「4/4」までCACHEが効いており、buildが走っていない。[4/4]npm install
もbuildが走っておらず、爆速。
5. .dockerignoreを書こう
実行に必要の無いディレクトリ・ファイルは、buildから除外しましょう。
secrets
などの秘密データは、必要のない場合は除外しましょう。
# ignore .git and .cache folders
.git
.cache
# ignore all markdown files (md)
*.md
# ignore sensitive files
private.key
setting.json
6. Multi-Stage Buildsを使おう
一つのイメージの中に、必要なものをすべて詰め込む(builder pattern)は保守が辛いのでやめよう。
# syntax=docker/dockerfile:1
FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go ./
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# syntax=docker/dockerfile:1
FROM golang:1.16 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]
7. userの実行権限は最小限にしよう
USER
を指定しないとroot
で実行されるので、 USER
を指定しましょう。
# run with default root user
CMD node index.js
# create group and user
RUN groupadd -r tom && useradd -g tom tom
# set ownership and permission
RUN chown -R tom:tom /app
# switch to user
USER tom
# run with tom
CMD node index.js
8. Securityスキャンをしよう
dockerhubにログインする。
docker login
docker scan
コマンドは、内部的にsnyk
を利用して、Securityスキャンをしてくれるので、snyk
でもログインする必要がある。
docker scan --login
build image
をSecurityスキャンするk
docker scan myapp:1.0
おわりに
今回は、Dockerfile作成時のベストプラクティスについてまとめました。
皆さんのDockerライフの一助となれば幸いです。
twitterでGolang・Flutter・GCP開発など情報発信していますので、よかったらフォローしてくださいmm
参考
Discussion
Dockerfile 苦手なので参考になりました,ありがとうございます><
alpine
の typo があるみたいです.(alphine
になっているみたいです><)コメントありがとうございます!
タイポ修正しましたmm
こんにちは!とても素敵な記事で参考になりました!🐶
追加で
CACHE
のタイポも確認したのでコメント添えておきます🙈笑(「4. Dockerのキャッシュレイヤーを最適化しよう」あたりで
CASHE
になってますね)コメントありがとうございます!!
励みになります(^o^)
CASHE
修正しました笑良記事ありがとうございます!!