🐶

硬派なDockerfile

に公開
2

Docker代替についてが話題になりつつありますが、まだしばらくがDockerが使われ続けると信じてDockerfileの記事を書きます。

Dockerfileに書いちゃえば環境移行時の問題は起きないよね、とも言い切れないことも多く、環境移行に対してロバストな(硬派な・・?)Dockerfileについての小ネタをまとめてみました。


1. プロキシ問題

社内ネットワークなどでは プロキシ設定が必須の場合があります。
公式ドキュメントでも推奨されているのは、~/.docker/config.json に proxy 設定を書いて Docker デーモン/CLI に反映させる 方法であり、Dockerfile に直接書くのは避けるのがBetterです。

FROM node:14
# Dockerfile に直書きするとイメージが汚れる&公開時に漏洩リスクも
ENV http_proxy=http://proxy.example.com:8080
ENV https_proxy=http://proxy.example.com:8080
// ~/.docker/config.json
{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:8080",
      "httpsProxy": "http://proxy.example.com:8080",
      "noProxy": "localhost,127.0.0.1"
    }
  }
}

2. リポジトリの陳腐化

ベースイメージやパッケージソースは日々更新され、放っておくと可搬性が低下するリスクが高まります。
できる限りバージョンを明記し、必要に応じてソースからビルドすることで更に堅牢なDockerfileも構築可能です。

FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3 pip
  • latestタグやバージョン省略は、ある日突然中身が変わりビルドが壊れる可能性大。

Better: タグ+Digest指定

FROM ubuntu:20.04@sha256:3f5f9e1b1e...
RUN apt-get update \
 && apt-get install -y python3=3.8.10-0ubuntu1 pip=20.0.2-5ubuntu1 \
 && rm -rf /var/lib/apt/lists/*

More Robust: ソースからビルド

FROM ubuntu:20.04@sha256:3f5f9e1b1e...
RUN apt-get update \
 && apt-get install -y build-essential wget ca-certificates \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src
RUN wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz \
 && tar xzf Python-3.8.10.tgz \
 && cd Python-3.8.10 \
 && ./configure --enable-optimizations \
 && make -j$(nproc) \
 && make altinstall \
 && cd .. && rm -rf Python-3.8.10*
  • OSやリポジトリの更新に左右されず、一度ビルドしたアーティファクトが同一に保たれます。

3. COPYはキャッシュ化の敵

COPY . . でワークツリー丸ごとコピーすると、ちょっとの変更でキャッシュが無効化。ビルド時間が激増します。ここは無駄のない質実剛健な設定をしていきたいところです。

COPY . .
RUN bundle install
RUN npm install

Better: ファイルを段階的に分割COPY

# 依存定義だけ先にコピー
COPY Gemfile Gemfile.lock /app/
WORKDIR /app
RUN bundle install

# ソースを後からCOPY
COPY app/ /app/app/
COPY config/ /app/config/
  • ポイント: 依存定義が変わらなければbundle installステップは毎回キャッシュヒット。

4.対応アーキテクチャを明記

Dockerfile自体に対応する CPU アーキテクチャを明示しておくと、ミスビルドを未然に防げます。

# docker buildx
FROM --platform=$TARGETPLATFORM node:14

上記のBetterパターンを適用すれば、長期間・多拠点・多環境にわたって「壊れない」「再現できる」Dockerfileになります。ぜひ次のプロジェクトで。

ヘッドウォータース

Discussion

kodani takushikodani takushi

過去にFROM python:3.11-slimでpythonのイメージを使ってたら、パッチアップデートにやられた回がありました。こういうの痛い目見ないと気付けないがちですよね……。
https://zenn.dev/headwaters/articles/2ee12e5bb88fa0

阿久津阿久津

すみません、コメント気づけませんでした!
常に気にしていると大変ですが、ここぞというときには意識できるようにはしたいなと思っています!