Dockerfile の再現性をちょっと高める
ライフイズテック株式会社 サービス開発部の山口 (@no_clock) です。塾プロダクトグループでソフトウェアエンジニアをしています。
Dockerfile でいつでもどこでも同じ環境を再現できる… と思いたいのですが、いろんな原因で壊れる(再現できなくなる)ことがあります。
本記事では、すこしだけ再現性を高める方法を考えます。 100 点は目指しません。
3 行でまとめると
-
FROM
命令で記述するベースイメージのタグはパッチバージョンまで細かく指定 - 例えば Node.js なら
npm ci
, Ruby ならbundle install --deployment
を使う - あくまで「すこしだけ」、割り切りが必要
FROM
命令
FROM
命令で指定するベースイメージのタグを なるべく細かく指定する ことで、イメージが変わるリスクを減らします。
たとえば node では、 Node.js のパッチバージョンや Linux ディストリビューションのコードネーム (bookworm
) もしくはバージョン (alpine3.18
) まで明記されたタグを使います。
FROM node:20.10.0-bookworm-slim
また、昨今は CPU アーキテクチャの違いから問題が生じるケースもあります( Apple silicon や AWS Graviton は ARM ベース)。固定して問題なければ、引数 --platform
で固定できます。
FROM node:20.10.0-bookworm-slim
より厳密には、イメージの digest 値を指定することも出来ます。ただし、可読性は落ちる上、プラットフォームも固定されます。
# node:20.10.0-bookworm-slim (linux/amd64)
FROM node@sha256:18aacc7993a16f1d766c21e3bff922e830bcdc7b549bbb789ceb7374a6138480
アプリケーション
.dockerignore でビルド結果などを除外する
イメージビルド時にアプリケーションの過去のビルド結果などが混入しないよう、 .dockerignore で除外します。
node_modules
.next
out
(ビルドを CI でしか行わない場合は、 .gitignore でリポジトリから除外していれば事足ります)
インストールされるライブラリのバージョンを固定する
ライブラリのインストール時に、バージョンが固定されるようにします。
固定方法は、使用言語やパッケージマネージャーによります。例えば npm (Node.js) では npm ci
を、 Bundler (Ruby) では --deployment
オプション を使います。もちろん、ロックファイル (package-lock.json や Gemfile.lock) が正しく管理されている必要があります。
ちょっとだけ高まった
ベースイメージはほぼ固定され、ライブラリのバージョンも固定されました。ちょっとだけ再現性が高まったと言えます。ただし、再現性が下がるポイントはまだあります。
- ベースイメージのタグが更新されるかもしれないし、消えるかもしれない
- ライブラリの古いバージョンが提供されなくなるかもしれない
-
apt
やapk
で追加するパッケージのバージョンが変わるかもしれない - (そもそもインターネットからコンテンツを取得している時点で、限界がある…)
ある程度のところで割り切っておくのが無難そうです。
ちょっと宣伝
ライフイズテック サービス開発部では、気軽にご参加いただけるカジュアルなイベントを実施しています。開催予定のイベントは、 connpass のライフイズテックグループからご確認ください!
Discussion