【第4回】Dockerfile書き方完全ガイド|docker buildとイメージ作成【Rocky Linux 9】

この記事で分かること
  • Dockerfileが何者で、なぜ必要なのかが分かる
  • FROM / RUN / COPY / CMD など基本命令の意味と使い方が分かる
  • Rocky Linux 9ベースのNginxイメージを実際にビルドしてDocker Hubにpushできる

前回の第3回では、docker rundocker stop などの基本コマンドを学びました。

今回は「自分だけのDockerイメージを作る」ことに挑戦します。

そのための設計図が Dockerfile です。難しそうに聞こえますが、書き方はシンプルです。この記事を読み終えるころには、Rocky Linux 9ベースのNginxイメージを自分でビルドできるようになります。

このシリーズはRocky Linux 9 + SELinux Enforcing環境を前提としています。Dockerのインストール手順は第2回を、コンテナの基本概念は第1回をご参照ください。

目次

Dockerfileとは?まず「何のためにあるか」を理解しよう

Dockerfileとは、「このイメージをどう作るか」を記した設計書(テキストファイル)です。

料理に例えると分かりやすいです。

  • 🥘 料理のレシピDockerfile(作り方の手順書)
  • 🍳 できあがった料理Dockerイメージ(レシピを実行した結果)
  • 🍽️ 食べている状態Dockerコンテナ(イメージを起動した状態)

Dockerfileさえあれば、誰でも・どの環境でも・何度でも同じイメージを作れます。「自分のPCでは動いたのに本番では動かない」問題を根本から防げるのが最大のメリットです。

Dockerイメージの「レイヤー構造」を理解しよう

Dockerfileを書く前に、イメージの仕組みを少しだけ理解しておきましょう。ここを知っておくと、後で出てくる「キャッシュ」の話がぐっとわかりやすくなります。

イメージは「積み重ねた層(レイヤー)」でできている

Dockerイメージは、複数の読み取り専用のレイヤーが積み重なった構造をしています。Dockerfileに書いた命令(FROMRUNCOPY など)が、それぞれ1つのレイヤーになります。

イメージをミルフィーユケーキに例えると、こんなイメージです。

  • 1層目:Rocky Linux 9の土台(FROM)
  • 2層目:Nginxをインストール(RUN)
  • 3層目:設定ファイルをコピー(COPY)

レイヤー構造のメリット|
同じベースイメージを使う複数のイメージがあっても、共通部分(1層目)は1回だけダウンロードすれば済みます。ストレージと通信を節約できます。

キャッシュの仕組み — 変更があると「それ以降がリセット」される

Dockerはビルド時に各レイヤーをキャッシュします。前回と同じ命令・同じファイルなら、再実行せずキャッシュを再利用します。これがビルドを高速化する仕組みです。

ただし注意が必要です。あるレイヤーに変更があると、それ以降の全レイヤーのキャッシュが無効になります。

変更頻度が高いもの(ソースコードのCOPYなど)を上の方に書くと、毎回ほぼ全レイヤーが再実行されてビルドが遅くなります。「変わりにくいものを上、変わりやすいものを下」に書くのがコツです。

Dockerfileの基本命令を1つずつ覚えよう

Dockerfileで使う命令は多くありません。まずは以下の5つを覚えれば、ほとんどのケースに対応できます。

① FROM — ベースイメージを選ぶ(必須・最初に書く)

FROMはDockerfileの必ず最初に書く命令です。「どのOSイメージをベースにするか」を指定します。

FROM rockylinux:9

イメージの選び方: rockylinux:9 はフルパッケージ版。軽量版が必要なら rockylinux:9-minimal もあります(ただしパッケージマネージャが microdnf になります)。

② RUN — コマンドを実行して環境を作る

RUNはビルド中に実行するコマンドを指定します。パッケージのインストールや設定変更などに使います。

ここで初学者がよくやってしまうのが「RUNを分けすぎる」ミスです。

# ❌ NG:RUNが2行 = レイヤーが2つ増える(イメージが太る)
RUN dnf -y install nginx
RUN dnf clean all

# ✅ OK:&&で1行にまとめる = レイヤーが1つで済む
RUN dnf -y install nginx && \
    dnf clean all && \
    rm -rf /var/cache/dnf

なぜ1行にまとめるの?

RUNを分けるとレイヤーが増え、イメージサイズが大きくなります。さらに「nginxをインストールしたレイヤー」と「キャッシュを削除したレイヤー」が別になると、削除したはずのキャッシュがイメージに残ってしまいます。同じRUNでまとめることで確実に削除できます。

③ COPY — ファイルをイメージに取り込む

COPYはホストマシン上のファイルをイメージ内にコピーします。Webコンテンツや設定ファイルを含めるときに使います。

# 書き方:COPY ホスト側のパス イメージ内のパス
COPY html/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf

ADDという命令もありますが、特別な理由(tarの自動展開など)がない限り COPY を使うのがベストプラクティスです。動作が明確で予想外のことが起きません。

④ CMD — コンテナ起動時に実行するコマンドを指定する

CMDはコンテナが起動したときに自動実行されるコマンドを指定します。Webサーバーを起動したり、アプリを実行したりするときに使います。

# Nginxをフォアグラウンドで起動
# ※ "daemon off;" が重要!これがないとコンテナがすぐ終了する
CMD ["nginx", "-g", "daemon off;"]

「daemon off;」がないとコンテナがすぐ終了します。 Nginxはデフォルトでバックグラウンド(デーモン)起動しようとします。コンテナはメインプロセスが終了すると停止するので、フォアグラウンド実行(daemon off;)にする必要があります。

⑤ EXPOSE / ENV / WORKDIR — 補足情報を付加する命令

  • EXPOSE 80:「このコンテナはポート80を使いますよ」という宣言(実際の公開は docker run -p で行う)
  • ENV LANG=C.UTF-8:環境変数を設定する。アプリの設定値などに使う
  • WORKDIR /app:以降の命令の作業ディレクトリを指定する。cd と同じイメージ

実践|Rocky Linux 9ベースのNginxイメージを作ってみよう

ここからは実際に手を動かしてみましょう。以下の3ステップでDockerfileを作り、イメージをビルドします。

STEP
作業ディレクトリとHTMLファイルを準備する

まずDockerfileや関連ファイルを置くディレクトリを作ります。

# 作業ディレクトリを作成して移動
mkdir -p ~/docker-nginx && cd ~/docker-nginx

# Webコンテンツ用のhtmlフォルダも作成
mkdir html

続いて、Nginxが表示するテスト用のHTMLファイルを作成します。

cat << 'EOF' > html/index.html
<!DOCTYPE html>
<html>
<head><title>Docker Test</title></head>
<body><h1>Hello from Rocky Linux 9 + Nginx!</h1></body>
</html>
EOF
STEP
Dockerfileを作成する

~/docker-nginx/ ディレクトリの中に Dockerfile(拡張子なし)という名前でファイルを作成します。

# ~/docker-nginx/Dockerfile

# ① ベースイメージ:Rocky Linux 9を使う
FROM rockylinux:9

# ② Nginxをインストール(キャッシュ削除も同じレイヤーで行う)
RUN dnf -y install nginx && \
    dnf clean all && \
    rm -rf /var/cache/dnf

# ③ ホストのhtmlフォルダをNginxの公開ディレクトリにコピー
COPY html/ /usr/share/nginx/html/

# ④ ポート80を使うことを宣言
EXPOSE 80

# ⑤ コンテナ起動時にNginxをフォアグラウンドで実行
CMD ["nginx", "-g", "daemon off;"]

ファイル名は必ず Dockerfile(大文字D・拡張子なし)にしてください。別の名前にする場合は docker build -f ファイル名 で指定できます。

STEP
docker buildでイメージをビルドする

Dockerfileがあるディレクトリで以下のコマンドを実行します。

# -t でイメージ名:タグを指定。末尾の「.」はビルドコンテキスト(カレントディレクトリ)
docker build -t my-nginx:1.0 .

# ビルドが成功したかイメージ一覧で確認
docker images | grep my-nginx

ビルドが成功すると以下のような出力になります。

REPOSITORY   TAG   IMAGE ID       CREATED          SIZE
my-nginx     1.0   a1b2c3d4e5f6   10 seconds ago   235MB

2回目以降のビルドではログに CACHED が表示されます。これは「前回と変わっていないのでキャッシュを使いました」という意味です。COPYするファイルを変更した行以降は再実行されます。

ビルドしたイメージを動かして確認する

ビルドしたイメージを実際に起動して、Nginxが動いているか確認してみましょう。

# SELinux環境では :z オプションが必要
docker run -d -p 8080:80 --name test-nginx my-nginx:1.0

# ブラウザで http://サーバーIP:8080 にアクセス
# または curl で確認
curl http://localhost:8080

Rocky Linux 9(SELinux Enforcing)でボリュームマウントする場合: -v ./html:/usr/share/nginx/html だけでは Permission denied になります。:z(複数コンテナで共有)または :Z(このコンテナ専用)を末尾に付けてください。

.dockerignoreでビルドを軽くする

Gitの .gitignore と同じ発想で、ビルドに不要なファイルを除外できます。.dockerignore をDockerfileと同じ場所に置きましょう。

# ~/docker-nginx/.dockerignore
.git
*.md
.env
docker-compose*.yml

docker pushでイメージをDocker Hubに公開する

作成したイメージをDocker Hubに公開すると、チームメンバーや別サーバーから docker pull で取得できるようになります。まずDocker Hubで無料アカウントを作成してください。

STEP
Docker Hubにログインする
docker login
# ユーザー名とパスワードを入力
STEP
Docker Hub用のタグを付ける

Docker Hubにpushするには「ユーザー名/リポジトリ名:タグ」の形式でタグを付ける必要があります。

# yourname をDocker Hubのユーザー名に置き換える
docker tag my-nginx:1.0 yourname/my-nginx:1.0
STEP
pushしてDocker Hubにアップロードする
docker push yourname/my-nginx:1.0

# 完了後はログアウト
docker logout

pushが完了すると、Docker Hub上のリポジトリページにイメージが表示されます。他のメンバーは docker pull yourname/my-nginx:1.0 で取得できます。

よくある疑問

docker build が途中でエラーになった場合は?

エラーメッセージの直前の出力を確認しましょう。多くは「パッケージが見つからない」「パスが間違っている」などです。docker build はどのSTEPで失敗したかを表示してくれるので、その番号に対応するDockerfileの命令を見直してください。

ビルドのたびにdnf installが走って遅い。キャッシュを効かせたい

COPYするファイルを変更するたびにキャッシュが無効になっている可能性があります。Dockerfileの順番を見直してください。「変わりにくいもの(RUN dnf install)を上に、変わりやすいもの(COPY html/)を下に」配置するとキャッシュが効くようになります。

CMDとENTRYPOINTの違いは?どちらを使えばいい?

迷ったら CMD を使えばOKです。CMDdocker run イメージ名 コマンド のように起動時に上書きできます。ENTRYPOINT は上書きされず必ず実行されるので、「絶対に実行したいコマンド(例:特定のシェルスクリプト)」がある場合に使います。

イメージサイズを小さくするコツは?

①RUNを1行にまとめてキャッシュを同じレイヤーで削除する ②.dockerignore で不要ファイルを除外する ③ベースイメージを rockylinux:9-minimal にする — この3つが基本です。さらに本格的に小さくしたい場合は「マルチステージビルド」という手法があります。

まとめ

今回はDockerfileを使ったイメージ作成の基本を学びました。

  • Dockerfileは「イメージの作り方レシピ」。あれば誰でも同じ環境を再現できる
  • 命令は FROM → RUN → COPY → CMD の順番が基本
  • RUNはなるべく1行にまとめてレイヤーを減らしイメージを軽量化する
  • Rocky Linux 9環境でSELinuxが有効な場合、ボリュームマウント時は :z / :Z を忘れずに
  • ビルドしたイメージは docker push でDocker Hubに公開してチームで共有できる

Dockerfileを書けるようになると、「環境をコードで管理する」という考え方が身につきます。インフラエンジニアとして非常に強力なスキルです。次回はDocker Composeを使った複数コンテナの管理方法を学びましょう。

シリーズナビゲーション

前回:第3回 Dockerの基本コマンドを覚える|コンテナ操作の実践ガイド
次回:第5回 Docker Composeで複数コンテナを管理する(近日公開予定!)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次