はじめに
Docker v18.09
以降ではBuildKit modeを使用することができます。
これはexport DOCKER_BUILDKIT=1
をホスト側で設定することで使用でき、docker bulidをセキュアに行う機能を提供しています。
本記事ではBuildKitが提供する機能の中でもssh接続に関するものについて簡単に紹介した上で、docker build中で複数の秘密鍵を利用する方法について説明します。
BuildKitを使ったssh認証
例えば、docker build中でGithubのprivateリポジトリをcloneする場合、ホスト側からdocker側にSSH秘密鍵を渡す必要があります。
DockerfileにCOPY命令を記述して秘密鍵を渡すことでdocker側でもSSH接続できるようにはなりますが、この方法では後で鍵ファイルを削除しても削除する前のレイヤが残ってしまい安全ではありません。また、このように作成したdocker imageをパブリックなレジストリに公開してしまうと、第三者が秘密鍵にアクセスできる状態になってしまいます。
このあたりの挙動についてはこちらの記事が分かりやすかったので参考にされてください。
一方でBuildKitを使用した場合、SSH接続を伴うRUNコマンドのプロセスが走る間だけ、鍵の情報を読み取り専用でマウントされ、作成されたimageに秘密鍵の情報が残ることはありません。
BuiildKitを使用してssh認証情報を渡す方法は以下のようにとてもシンプルに行うことができます。
- Dockerfile内でRUNする際に
--mount=type=ssh
を指定する - build時に
--ssh default
を指定する
FROM alpine
RUN --mount=type=ssh git clone git@github.com:private-repo.git
DOCKER_BUILDKIT=1 docker build --ssh default -t test-image .
また、build時にdefaultを指定した場合は鍵情報として暗黙的に$SSH_AUTH_SOCK
が使用されます。注意点としてdefaultを使用する際は事前にローカルPCでSSH agentに秘密鍵を追加しておく必要があります。
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
複数の秘密鍵を使用する
前提
複数の秘密鍵を使用する例としてdocker build中で複数のGithub privateリポジトリをcloneする場合を考えます。
前提として、この例ではdocker buildを行う環境として以下の2つが考えられるかと思います。
1つ目は自分のローカルのPCでbuildを行う場合, 2つ目はGithub ActionsやCloud BuildといったCI/CDでbuildを行う場合です。2つの違いとしては使用する認証情報にあります。
**【ローカルPCでのbuild】**自分のローカルPCでbuildを行う場合、--ssh default
とすると自分のGithubアカウントに紐づく認証情報がbuild時に使用されます。
アカウントに紐づく認証情報の場合、権限のあるprivateリポジトリであれば全て参照できるので、1つの認証情報をbuild時に渡すだけで、複数privateリポジトリをcloneすることができます。
FROM alpine
RUN --mount=type=ssh git clone git@github.com:private-repo-a.git && \
git clone git@github.com:private-repo-b.git
DOCKER_BUIDKIT=1 docker build --ssh default -t test .
**【CI/CDでのbuild】**CI/CDでbuildを行う場合はcloneしたいprivateリポジトリにdeploy keyとして公開鍵を設定し、CI/CD側にはそれぞれの秘密鍵を置くことになります。
この時、Githubリポジトリのdeploy keyには共通の公開鍵を設定することはできない仕様のため、それぞれのリポジトリごとに秘密鍵と公開鍵のペアが必要になります。
このため、BuildKitでdocker build時に使用する秘密鍵も複数必要になります。
解決法
BuildKitを使ったtype=ssh
のマウントにはいくつかのオプションが提供されており、今回のケースではその中でもid
オプションをRUNに設定して対応することができます。
id
オプションをRUN時に設定すると、先ほど--ssh default
とした部分で指定した秘密鍵を区別して使用することができます。
FROM alpine
RUN --mount=type=ssh,id=private-repo-a git clone git@github.com:private-repo-a.git
DOCKER_BUIDKIT=1 docker build --ssh private-repo-a=~/.ssh/id_rsa_private_repo_a -t test .
複数の秘密鍵を使用する場合はid
オプションを使うことで次のようにbuildを行うことができます。
FROM alpine
RUN --mount=type=ssh,id=private-repo-a git clone git@github.com:private-repo-a.git
RUN --mount=type=ssh,id=private-repo-b git clone git@github.com:private-repo-b.git
build時につける--ssh
フラグを増やすことでdocker build中のRUNではそれぞれで使用したい認証情報を使うことができます。
DOCKER_BUIDKIT=1 docker build --ssh private-repo-a=~/.ssh/id_rsa_private_repo_a --ssh private-repo-b=~/.ssh/id_rsa_private_repo_b -t test .
まとめ
- BuildKitを使用するとdocker build時にセキュアに秘密鍵を使用することができる。
- BuildKitを使う場合、idを指定することで複数の秘密鍵を区別して使用することができる。
今回はtype=ssh
のマウント方法に着目しましたが、BuildKitには他にもいくつかのマウント方法が用意されています。詳しくは参考資料の方をご参照ください!