8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

初心者がDockerfileを書くときに身につけたい5つの習慣

Posted at

概要

突然ですが、Dockerfile適当に書いていませんか?
ほんの少しの工夫で、軽量になったり可読性が上がったりするので、今回はそんなTipsを紹介します。

この記事は人力で書きました。

その1 : マルチステージビルドを使う

Dockerのマルチステージビルドとは、ビルドと実行用のイメージに分割することで最終的なイメージをコンパクトにできるものです。
実際にgoのコンテナを作成するときの例を挙げてどのようなメリットがあるか確認してみます。

初心者のDockerfile
FROM golang:1.25
WORKDIR /app
COPY . .
RUN go build -o myapp .
CMD ["./myapp"]
玄人のDockerfile
# Stage 1: Build
FROM golang:1.25 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

# Stage 2: Run
FROM alpine:3.22.1
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

では、実際に上記の2ファイルをbuildしてみて、どれくらいの容量差分が出てくるのか確認してみます。一旦の構成でmain.gogo.modでgoアプリを構成します。

main.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, Docker!")
}
go.mod
module myapp

go 1.21
# それぞれbuildビルド
docker build -f Dockerfile.junior -t myapp-junior .

docker build -f Dockerfile.senior -t myapp-senior .

実際にbuildして比べてみた結果、なんと80倍も変わりました。今回小さい構成で実施したのですが、これくらいの差が出ていますが、ガッツリ使用した場合はもっと大きくなりそうですね。。

isoda@shota-mac junior % docker images | grep myapp
myapp-junior                   latest    f1c396cf8580   41 seconds ago       888MB
myapp-senior                   latest    eab45bab740d   About a minute ago   10.8MB

その2 : ベースイメージは必ずバージョンを固定する

これを怠ると今日動いたbuildが明日動かなくなるかもしれません。

NG例

FROM golang:latest

今日、上記の記載方法でbuildが成功したとしても、明日latestが更新されたらどうなるでしょう?
急にbuildが失敗してしまうかもしれません。

OK例

FROM golang:1.25-alpine

ポイントとしては、以下になります。

  • LTSの特定バージョンを明示的に指定する
  • 可能なら軽量イメージ(alpineやbullseye-slimなど)を使用する

バージョン指定することで、思わぬトラブルを防ぐのとイメージの軽量化にも貢献してくれます。4倍くらいイメージ容量が変わってきますね。

isoda@shota-mac junior % docker image ls | grep golang
golang                         latest        d7e6adee7899   7 days ago       855MB
golang                         1.25-alpine   6ea50bc9f564   7 days ago       211MB

その3 : レイヤーはできるだけ減らす

続いてのポイントとしては、レイヤはできるだけ減らすということです。そうすることで以下のようなメリットがあります。

  • イメージサイズ削減(不要ファイルを残さない)
  • キャッシュ効率アップ(再ビルド時間の短縮)
  • 配布・展開の高速化(レイヤが少ないほどpush/pullが速い)

NG例

FROM debian:bullseye
RUN apt-get -y update
RUN apt-get install -y python

OK例

FROM debian:bullseye
RUN apt-get -y update && apt-get install -y python && rm -rf /var/lib/apt/lists/*

今回の例では、イメージサイズの削減は見られませんが、大きなDockerfileになれば差も大きくなってくると思います。

isoda@shota-mac junior % docker images | grep myapp               
myapp-junior                   latest        c30825b58d07   19 seconds ago   216MB
myapp-senior                   latest        818501d91809   34 seconds ago   198MB

その4 : .dockerignoreを活用する

これは、.gitignoreと同じような感覚でイメージに含まないファイルを指定することができます。

例えばですが、以下のようなDockerfileがあり

COPY . /app

もしも、ディレクトリに以下のような不要なファイルが含まれていたとしたらどうでしょうか?
その不要ファイルを.dockerignoreに記載すればその分の容量を節約できます。

venv/
.git/
logs
node_modules
...etc

.dockerignoreの記載方法は簡単で、プロジェクトルートに.dockerignoreというファイルを作成して、不要なファイルを記載するだけです。

node_modules 
.git 
*.log
Dockerfile
...etc

※以下のようにbuild時にオプションを指定すると実際どのようなファイルが送られているか確認できるので、試してみてください。

docker build . --no-cache --progress=plain

その5 : セキュリティを意識したDockerfileを構築する

Dockerのセキュリティのベストプラクティスとして、以下の4点を意識しましょう。

  • 信頼できる正しいベースイメージを使用し軽量化させる
  • マルチステージビルドを使う
  • イメージは定期的に再構築をする
  • イメージの脆弱性を確認する

それぞれ詳しく解説していきます。

信頼できる正しいベースイメージを使用し軽量化させる

まずは、信頼できるベースイメージを使用することが大切です。
Docker Hubにはかなりの量のイメージが公開されていますが、その中でもOfficial ImageVerified Publisherを使用すると良いです。
Docker Official Imagesは、以下のようなマークがついています。

スクリーンショット 2025-08-23 12.12.36.png

また、攻撃対象や脆弱性を減らすためにも、できるだけ小さなイメージ(alpineslim)を使用するようにしましょう。

マルチステージビルドを使う

前述もしましたが、マルチステージビルドを活用することによって「最終イメージには 不要なツールやファイルを含めない」ということができます。
それによって、不要なツールの脆弱性を回避できたり、攻撃対象を減らすということに繋がります。

イメージは定期的に再構築をする

例えば、何年も前に構築されたイメージを使用し続ける場合もしそのイメージ内で使用しているソフトウェアの脆弱性が発見および対応された場合でも再構築しない場合、脆弱性が対応されていないイメージを使い続けることになってしまいます。
そこで、定期期的に以下のようにイメージの再構築をしましょう。

docker build --no-cache -t myImage:myTag myPath/

--no-cacheを使用することで、キャッシュが使用されなくなります。(確実に新しいものをインストールするためにこのオプションを利用しましょう)

イメージの脆弱性を確認する

脆弱性を定期的にスキャンして、もし脆弱性が見つかった時はイメージの更新/再構築をするというのも大切です。

一番手軽に診断できるツールとしては、docker scoutがあります。これは、公式から提供されているツールで、現時点では、ローカルイメージは無料でスキャンできるようです。

docker scout cves <image-name>

実際に作成したイメージに対して、動作させて出力を確認してみました。(一部割愛)

    ✓ Image stored for indexing
    ✓ Indexed 356 packages
    ✓ Provenance obtained from attestation
    ✗ Detected 29 vulnerable packages with a total of 106 vulnerabilities


## Overview

                    │               Analyzed Image                
────────────────────┼─────────────────────────────────────────────
  Target            │  <image-name>:latest                       
    digest          │  XXXXXXXXXXXXX                               
    platform        │ linux/arm64                                 
    provenance      │ git@github.com:XXXXXXXXXXXXX/XXXXXXXXXXXXX.git      
                    │  XXXXXXXXXXXXXXXXXXXXXXXXXXX   
    vulnerabilities │    0C     1H     3M   102L                  
    size            │ 249 MB                                      
    packages        │ 356                                         


## Packages and Vulnerabilities

   0C     1H     0M    11L  XXXXXXXXXXXXX XXXXXXXXXXXXX
pkg:deb/debian/XXXXXXXXXXXXX
os_distro=XXXXXXXXXXXXX

    ✗ HIGH CVE-2025-55154
      https://scout.docker.com/v/CVE-2025-55154
      Affected range : >=8:7.1.1.43+dfsg1-1  
      Fixed version  : not fixed             

--- 略 ---

106 vulnerabilities found in 29 packages
  CRITICAL  0    
  HIGH      1    
  MEDIUM    3    
  LOW       102  


What's next:
    View base image update recommendations → docker scout recommendations XXXXXXXXXXXXX:latest

こういったスキャンを定期的に実行して、検出された脆弱性に対処していきましょう。

まとめ

今回紹介したTipsは、難しいものではなく日々の開発で少し意識するだけで取り入れることができると思います。振り返ると以下の5つです。

  • マルチステージビルドを活用する → イメージを軽量化し、不要な依存を排除できる
  • ベースイメージは必ずバージョン固定 → 再現性を高め、予期せぬビルドエラーを防ぐ
  • レイヤーを減らす → キャッシュ効率やビルド速度、イメージサイズを改善
  • .dockerignoreを活用する → 不要ファイルを含めず、効率的なビルドを実現
  • セキュリティを意識する → 信頼できるイメージを選び、定期的に再構築&脆弱性チェック

これらを少しずつ取り入れていくだけで、イメージは軽く・速く・安全になります。
次にDockerfileを書くときは、ぜひ一つでも試してみてください。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?