こんにちは、id:daido1976 です。入社してもうすぐ 3 年が経ちます。
Docker BuildKit の --secret フラグについて、公式ドキュメントでの説明や関連する日本語記事はすでにいくつかあるのですが、2020/12/08 にリリースされた Docker Engine 20.10.0 で「秘匿情報を環境変数経由で渡せるようになっていたこと」への言及が見当たらなかったので書かせていただきます。*1(個人的にはとても嬉しいアップデートでした…!)
リリースノートの該当箇所は以下です。
See. https://docs.docker.com/engine/release-notes/#20100
- buildkit: secrets: allow providing secrets with env moby/moby#41234 docker/cli#2656 moby/buildkit#1534
- Support
--secret id=foo,env=MY_ENV
as an alternative for storing a secret value to a file.--secret id=GIT_AUTH_TOKEN
will load env if it exists and the file does not.
要点
- Docker Engine 20.10.0 までは
--secret id=my_secret,src=my_secret.txt
のようにファイル経由でしか秘匿情報を渡せなかった - 20.10.0 からは
--secret id=my_env,env=MY_ENV
のように環境変数経由で秘匿情報を渡せるようになった - 上記の
--secret id=my_env,env=MY_ENV
にはショートハンドが用意されており--secret id=MY_ENV
とも書ける(この場合 Dockerfile 側でもid
はMY_ENV
になる)
使い方
基本的な使い方は 公式ドキュメント に書いてあるのでそちらに説明を譲ります。
以下は主に上記の 要点
と公式ドキュメントに記載のない仕様を説明するための最小のサンプルコードです。
こんな Dockerfile があったとして、
# syntax = docker/dockerfile:1.2 FROM alpine # 1. docker build 時に `id` を明示的に指定する場合(例: `--secret id=my_env1,env=MY_ENV1` ) RUN --mount=type=secret,id=my_env1 cat /run/secrets/my_env1 # 2. docker build 時に `id` を明示的に指定しない場合(例: `--secret id=MY_ENV2`) RUN --mount=type=secret,id=MY_ENV2 cat /run/secrets/MY_ENV2 # 3. `dst` を指定した場合(`dst` を指定しないとデフォルトで `/run/secrets{id}` に秘匿情報が入ります) RUN --mount=type=secret,id=MY_ENV3,dst=/foobar cat /foobar # 補足: key 名の指定は実はいろいろできるらしい # https://github.com/moby/buildkit/blob/v0.8.2/frontend/dockerfile/instructions/commands_runmount.go#L154-L216
以下のように docker build
すると、環境変数経由で秘匿情報を渡すことができます。
$ export MY_ENV1='my_env1!!!' && export MY_ENV2='my_env2!!!' && export MY_ENV3='my_env3!!!' # 複数の秘匿情報を渡すには --secret フラグを複数使えば良い $ DOCKER_BUILDKIT=1 docker build --secret id=my_env1,env=MY_ENV1 --secret id=MY_ENV2 --secret id=MY_ENV3 --no-cache --progress=plain . # ... #8 [2/4] RUN --mount=type=secret,id=my_env1 cat /run/secrets/my_env1 #8 sha256:d32e4958843414fb006b5dbe7c259112f1bd481d17d84098c3d84f499793cb3b #8 0.252 my_env1!!!#8 DONE 0.3s #9 [3/4] RUN --mount=type=secret,id=MY_ENV2 cat /run/secrets/MY_ENV2 #9 sha256:4cc22ee3d7f39180f4f4f8167deaa481e852b2fc577c89a234fe88b9852952ba #9 0.301 my_env2!!!#9 DONE 0.4s #10 [4/4] RUN --mount=type=secret,id=MY_ENV3,dst=/foobar cat /foobar #10 sha256:91f97f55e633c8ed675126abefa015110265a7fbd40e4aeaf88204dcb912cb26 #10 0.283 my_env3!!!#10 DONE 0.3s # ...
Docker Compose で --secret フラグが使えないことへの対策
余談ですが、Docker Compose には BuildKit が統合されているものの、2021年3月現在 --secret フラグは利用できません。(対応中らしき PR はある)
私のチームではワークアラウンドとして、開発環境でも docker-compose build
ではなく docker build
を使う方法を取りました。
Docker Compose では docker-compose.yml
で指定しているイメージと同名のイメージがローカルにあればそちらを使ってくれるので、以下のような docker-compose.yml
を書いて、
version: '3' services: app: build: . image: my-app # ...
$ DOCKER_BUILDKIT=1 docker build -t my-app --secret id=MY_ENV .
上記のように docker build
で同名のイメージを事前に作っておいて docker-compose
から使う、という流れになります。
参考記事
- Docker 18.09 新機能 (イメージビルド&セキュリティ) | by Akihiro Suda | nttlabs | Medium
- Docker Engine 18.09 から使える Build-time secrets を試してみた | はったりエンジニアの備忘録
*1:BuildKit や --secret フラグってそもそも何?という方は最下部の参考記事に詳しくまとまっておりますのでぜひご覧ください。