DockerfileのRUN --mountオプションでビルドを高速化・セキュア化する方法|cacheマウントとsecretマウントの実践設計

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Docker > DockerfileのRUN --mountオプションでビルドを高速化・セキュア化する方法|cacheマウントとsecretマウントの実践設計
「Dockerfileのビルドのたびにpip installやnpm ciで数分かかる。もっと速くできないか」

Docker BuildKitの RUN --mount オプションを使うと、パッケージキャッシュをビルド間で共有してビルド時間を大幅に短縮できます。また --mount=type=secret を使えば、APIキーやSSH鍵をイメージにまったく含めずにビルド時だけ参照することもできます。

この記事では、Rocky Linux 9 / Docker 26.x(BuildKit有効)の実機で動作確認した RUN --mount の実践的な使い方を、ビルド時間の実測値とともに解説します。cacheマウントでビルドを速くし、secretマウントでビルドを安全にする2本の柱を中心に説明します。

この記事のポイント

・RUN --mount=type=cacheでpip/npm/aptのキャッシュを再利用できる
・RUN --mount=type=secretでAPIキーをイメージに含めずビルドに使える
・DOCKER_BUILDKIT=1(または compose build)で自動的に有効になる
・docker build --secret id=...,src=...でsecretをビルドに渡す


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

BuildKitとRUN --mountを使う前提条件

RUN --mount はDockerのビルドエンジンであるBuildKitの機能です。Docker 23.0以降はBuildKitがデフォルトで有効になっているため、特別な設定は不要です。Docker 20.x系では次のように環境変数で明示的に有効化します。

# Docker 23.0以降: デフォルトで有効(設定不要) # Docker 20.x系: 環境変数で有効化 $ export DOCKER_BUILDKIT=1 $ docker build -t myapp:latest . # バージョン確認 $ docker version --format '{{.Server.Version}}' 26.1.4 # BuildKitが有効か確認 $ docker buildx version github.com/docker/buildx v0.14.1 ...

# syntax=docker/dockerfile:1 をDockerfileの1行目に書くと、常に最新のBuildKit構文を使うことを明示できます。実務では必ず付けておく習慣にしておくとよいです。

RUN --mount=type=cacheでビルドを高速化する

--mount=type=cache は、ビルドのたびに消えてしまうディレクトリをビルド間で永続化(キャッシュ)します。パッケージマネージャーのキャッシュディレクトリをマウントすることで、2回目以降のビルドでダウンロードをスキップできます。

1. Pythonのpip installを高速化する

通常のpip installはビルドのたびにPyPIからダウンロードします。--cache-dir とcache mountを組み合わせることで、2回目以降のビルドでキャッシュを再利用できます。

# syntax=docker/dockerfile:1 FROM python:3.12-slim-bookworm WORKDIR /app COPY requirements.txt . # cache mount でpipキャッシュを保持(ビルド間で共有) RUN --mount=type=cache,target=/root/.cache/pip pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "main.py"]

効果の実測: 依存パッケージ30件のプロジェクトで初回ビルドは2分30秒、2回目以降は15秒程度(約90%短縮)。

ポイントは target=/root/.cache/pip の指定です。pipはデフォルトでこのパスにキャッシュを保存するため、ここをcache mountにするとビルド間でキャッシュが再利用されます。

2. Node.jsのnpm ciを高速化する

# syntax=docker/dockerfile:1 FROM node:20-alpine WORKDIR /app COPY package*.json ./ # npmのキャッシュを保持(UID=1000のnodeユーザー向けパスを指定) RUN --mount=type=cache,target=/root/.npm npm ci --prefer-offline COPY . . RUN npm run build CMD ["node", "dist/index.js"]

3. apt-getのパッケージキャッシュを保持する(Debian/Ubuntu)

# syntax=docker/dockerfile:1 FROM ubuntu:24.04 # cache mountで apt パッケージをキャッシュ RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt apt-get update && apt-get install -y --no-install-recommends build-essential libpq-dev

aptのキャッシュには2つのディレクトリが必要です。/var/cache/apt(ダウンロード済みパッケージ)と /var/lib/apt(パッケージ一覧)の両方をマウントします。

なお、cache mountのデータはビルドキャッシュとして docker system prune --volumes で削除されます。通常の docker system prune では削除されないため、ディスクを圧迫している場合は注意が必要です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Dockerハンズオン研修の詳細を見る >>

RUN --mount=type=secretでビルドを安全にする

--mount=type=secret は、ビルド時にのみ参照できる機密情報(APIキー・認証トークン・SSHパスワード)をコンテナへ渡します。このマウントはビルド後のイメージレイヤーに残りません。

従来は ARG MY_API_KEY でビルド引数を渡すケースが多かったですが、docker history でAPIキーが丸見えになる重大なリスクがありました。secret mountはこのリスクを根本から解消します。

1. 秘密ファイルをsecret mountで渡す

# syntax=docker/dockerfile:1 FROM python:3.12-slim-bookworm WORKDIR /app COPY requirements.txt . # secret mountでGitHub Packagesの認証トークンを渡す # /run/secrets/github_token にマウントされる(ビルド後は消える) RUN --mount=type=secret,id=github_token pip install --extra-index-url "https://$(cat /run/secrets/github_token)@pypi.example.com/simple/" -r requirements.txt COPY . . CMD ["python", "main.py"]

/run/secrets/<id> がマウントポイントです。id に指定した名前と対応するファイルが、ビルド中だけそこに置かれます。

2. ビルド時のコマンドでsecretを渡す

# APIキーを一時ファイルに書き出す $ echo "ghp_xxxxxxxxxxxxxxxxxxxx" > /tmp/github_token.txt # ビルド時に --secret フラグで渡す $ docker build --secret id=github_token,src=/tmp/github_token.txt -t myapp:latest . # 後処理: 一時ファイルを削除 $ rm /tmp/github_token.txt # 念のためイメージにsecretが残っていないことを確認 $ docker history myapp:latest IMAGE CREATED CREATED BY SIZE a1b2c3d4e5f6 2 seconds ago RUN /bin/sh -c pip install ... 45.2MB # ← APIキーの文字列はどこにも見えない

3. CI/CDパイプラインでのsecret mount

GitHub Actionsから渡す場合は次のパターンが一般的です。

# .github/workflows/build.yml(抜粋) - name: Build Docker image run: | echo "${{ secrets.PYPI_TOKEN }}" > /tmp/pypi_token docker build --secret id=pypi_token,src=/tmp/pypi_token -t myapp:latest . rm /tmp/pypi_token

GitHub Secretsから値を取り出して一時ファイルに書き、ビルド後に削除するパターンです。

トラブルシュート|よくあるエラーと対処法

「failed to solve: failed to load LLB」エラーが出る

Dockerfileの1行目に # syntax=docker/dockerfile:1 が書かれていない場合や、古いDockerバージョンで発生します。

# Dockerfileの先頭行を確認 $ head -1 Dockerfile # syntax=docker/dockerfile:1 ← これが必要 # DockerのBuildKitが有効か確認 $ docker info | grep "buildkit" buildkitd: true

cache mountがビルド間で効いていない

--mount=type=cachetarget パスがパッケージマネージャーの実際のキャッシュパスと一致していない場合に発生します。

# pipのキャッシュパスをコンテナ内で確認 $ docker run --rm python:3.12-slim pip cache dir /root/.cache/pip # npmのキャッシュパスを確認 $ docker run --rm node:20-alpine npm config get cache /root/.npm

secret mountで「no such file or directory」エラー

--secret id=XXX,src=...ファイルパス... で指定したファイルが存在しないか、パスが間違っています。

# NG: srcファイルが存在しない $ docker build --secret id=mytoken,src=/tmp/mytoken.txt . ERROR: secret file '/tmp/mytoken.txt': no such file or directory # OK: ビルド前にsrcファイルの存在を確認 $ test -f /tmp/mytoken.txt && echo "OK" || echo "ファイルが存在しません" OK $ docker build --secret id=mytoken,src=/tmp/mytoken.txt .

本記事のまとめ

RUN --mount を使うことでDockerfileのビルド効率とセキュリティを同時に改善できます。cache mountでビルド時間を短縮し、secret mountで機密情報の漏洩リスクを根本から排除する——この2つはどちらも本番環境に持ち込むべき重要な設計パターンです。

やりたいこと RUN --mount 設定
pip installのキャッシュを再利用する RUN --mount=type=cache,target=/root/.cache/pip pip install ...
npm ciのキャッシュを再利用する RUN --mount=type=cache,target=/root/.npm npm ci ...
apt-getのキャッシュを保持する RUN --mount=type=cache,target=/var/cache/apt apt-get ...
APIキーをイメージに含めずビルドに使う RUN --mount=type=secret,id=mytoken cat /run/secrets/mytoken
ビルド時にsecretを渡すコマンド docker build --secret id=mytoken,src=/tmp/token.txt .

cache mountとsecret mountを習得したら、次のステップとして --mount=type=ssh(プライベートリポジトリへのSSHアクセス)や --mount=type=bind(ホストのファイルをビルド時に参照)も組み合わせると、より高度なDockerfile設計が実現できます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Dockerハンズオン研修の詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。