docker compose buildの --ssh option(w/ BuildKit)を試す
docker compose v2.4.0 から対応している --ssh
option について、Python パッケージの install を例にまとめています。
環境
- Mac OS Monterey version 12.0.1
- Docker for Mac 4.7.1 (Engine: 20.10.14)
❯ docker version
Client:
Cloud integration: v1.0.23
Version: 20.10.14
API version: 1.41
Go version: go1.16.15
Git commit: a224086
Built: Thu Mar 24 01:49:20 2022
OS/Arch: darwin/arm64
Context: default
Experimental: true
Server: Docker Desktop 4.7.1 (77678)
Engine:
Version: 20.10.14
API version: 1.41 (minimum version 1.12)
Go version: go1.16.15
Git commit: 87a90dc
Built: Thu Mar 24 01:45:44 2022
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: 1.5.11
GitCommit: 3df54a852345ae127d1fa3092b95168e4a88e2f8
runc:
Version: 1.0.3
GitCommit: v1.0.3-0-gf46b6ba
docker-init:
Version: 0.19.0
GitCommit: de40ad0
やりたいこと
GitHub の private repository から独自パッケージを pip install して、docker image の build を行うようなケースを想定しています。
単純な docker build であれば、--ssh
option は対応している一方で、ローカル開発環境では docker-compose (docker compose
) を頻繁に利用します。
v2.4.0 以前の docker compose build コマンドは --ssh
option は対応していない状況でした。
BuildKitについて
BuildKit に関する詳細な説明は割愛しますが、本記事で記載する内容は BuildKit を利用した image build が前提となります。
Docker 18.09 から、DOCKER_BUILDKIT=1
で環境変数を指定することで、BuildKit が利用できるようになっています。
BuildKit に関しては、下記の資料・ドキュメントが参考になるかと思います。
- https://www.slideshare.net/AkihiroSuda/buildkit
- https://docs.docker.com/develop/develop-images/build_enhancements/
docker
ssh keyの利用 (w/ BuildKit)
上記でも記載した通り、Docker 18.09 から BuildKit が利用できるようになっています。
docker build であれば、--ssh
option は対応しており、下記のドキュメントを参考に Dockerfile を記述できます。
例えば、Flask App を起動する開発用の docker image を build したい場合を考えます。
requirements.txt
には、install したい python パッケージを管理している GitHub repository が指定されています。
...
sloppy @ git+ssh://git@github.com/taxintt/sloppy.git@0.1.0 ; python_version >= "3.9" and python_version < "4.0"
uvicorn==0.17.6; python_version >= "3.7"
上記を踏まえて、Dockerfile は下記のようになります。
--mount=type=ssh
で指定することで、RUN
で定義されたコマンドでクライアント側の ssh-agent を利用するようになります。
(注意点として、ssh-add
で ssh-agent に対して、事前に GitHub で利用している秘密鍵を登録する必要があります。)
# syntax=docker/dockerfile:1
ARG PYTHON_VER=3.9
FROM python:${PYTHON_VER}-buster as app-base
COPY requirements.txt .
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN pip install --no-cache-dir -r requirements.txt
RUN flask run --host=0.0.0.0 --port=5000 --debugger --reload
準備ができたら、Dockerfile があるディレクトリで下記のコマンドを実行して image build を行うことができます。
$ export DOCKER_BUILDKIT=1
$ docker image build -t pip-install-private-repo-sample .
docker compose
--ssh option以前のworkaround
記載している通り、v2.4.0 以前の docker compose
では --ssh
option は対応していませんでした。
回避策として、--target
option でパッケージインストールを行うステージを指定して、事前に docker build を行うことで回避できました。
# 1. pkg (パッケージインストールを行うステージ) をtargetとして指定してimage buildを行う
$ export DOCKER_BUILDKIT=1
$ docker image build --ssh default --target=pkg .
# 2. docker compose buildを通す
$ export COMPOSE_DOCKER_CLI_BUILD=1
$ export DOCKER_BUILDKIT=1
$ docker compose build
--ssh option (^v2.4.0)
上記のような回避方法もありましたが、docker compose v2.4.0 のリリースで、docker compose build で --ssh option が対応するようになりました。
Mac 用の Docker Desktop であれば、4.7.0 で docker compose のバージョンが v2.4.1 になっています。
Docker for Mac 4.3.2 (Engine: 20.10.11)の状態では、docker compose build
を実行すると下記のように pip install が失敗します。
=> [libs 3/4] RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts 6.6s
=> ERROR [libs 4/4] RUN --mount=type=ssh pip install --no-cache-dir -r requirements.txt 2.1s
------
> [libs 4/4] RUN --mount=type=ssh pip install --no-cache-dir -r requirements.txt:
#12 1.000 Ignoring colorama: markers 'python_version >= "3.7" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.7" and python_full_version >= "3.5.0"' don't match your environment
#12 1.002 Collecting sloppy@ git+ssh://git@github.com/taxintt/sloppy.git@0.1.0
#12 1.002 Cloning ssh://****@github.com/taxintt/sloppy.git (to revision 0.1.0) to /tmp/pip-install-gd771hcn/sloppy_7e4edbf65fe949d795d03e7ff53cb5a3
#12 1.014 Running command git clone --filter=blob:none --quiet 'ssh://****@github.com/taxintt/sloppy.git' /tmp/pip-install-gd771hcn/sloppy_7e4edbf65fe949d795d03e7ff53cb5a3
#12 1.581 Warning: Permanently added the ECDSA host key for IP address '13.114.40.48' to the list of known hosts.
#12 1.951 git@github.com: Permission denied (publickey).
#12 1.955 fatal: Could not read from remote repository.
#12 1.955
#12 1.955 Please make sure you have the correct access rights
#12 1.970 and the repository exists.
#12 1.975 error: subprocess-exited-with-error
#12 1.975
#12 1.975 × git clone --filter=blob:none --quiet 'ssh://****@github.com/taxintt/sloppy.git' /tmp/pip-install-gd771hcn/sloppy_7e4edbf65fe949d795d03e7ff53cb5a3 did not run successfully.
#12 1.975 │ exit code: 128
#12 1.975 ╰─> See above for output.
#12 1.975
#12 1.975 note: This error originates from a subprocess, and is likely not a problem with pip.
#12 1.978 error: subprocess-exited-with-error
#12 1.978
#12 1.978 × git clone --filter=blob:none --quiet 'ssh://****@github.com/taxintt/sloppy.git' /tmp/pip-install-gd771hcn/sloppy_7e4edbf65fe949d795d03e7ff53cb5a3 did not run successfully.
#12 1.978 │ exit code: 128
#12 1.978 ╰─> See above for output.
#12 1.978
#12 1.978 note: This error originates from a subprocess, and is likely not a problem with pip.
------
failed to solve: rpc error: code = Unknown desc = executor failed running [/bin/sh -c pip install --no-cache-dir -r requirements.txt]: exit code: 1
make: *** [build-local] Error 17
一方で、Docker for Mac 4.7.1 (Engine: 20.10.14)では、--ssh
の option を指定した docker compose build
を実行できます。
docker compose コマンドでの Buildkit の有効化は下記の blog を参考にできます。
docker compose 側の --ssh
の option は、基本的に --ssh default
のように指定するだけです。
❯ make build-local
env COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 env UID=501 docker compose --project-directory=. --env-file=docker/local/compose.env build --ssh default --pull
[+] Building 14.5s (13/13) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1 0.8s
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:91f386bc3ae6cd5585fbd02f811e295b4a7020c23c7691d686830bf6233e91ad 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load metadata for docker.io/library/python:3.9-buster 0.7s
=> [internal] load build context 0.0s
=> => transferring context: 38B 0.0s
=> [libs 1/4] FROM docker.io/library/python:3.9-buster@sha256:2ebfde37127af1b36196a6e4ca9b159e30b0fbea80b49cd1201ae48d907aeac4 0.0s
=> CACHED [libs 2/4] COPY requirements.txt . 0.0s
=> CACHED [libs 3/4] RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts 0.0s
=> [libs 4/4] RUN --mount=type=ssh pip install --no-cache-dir -r requirements.txt 12.6s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:feab17f4b00d2933673893742a0614cb431532148b89599722d5629577d45c04 0.0s
=> => naming to docker.io/library/use_sloppy_app 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
一連の実行コマンド的には、下記のように Buildkit の有効化と --ssh
オプションを指定するのみです。
(上記のログでは、検証環境に合わせた形で Makefile を利用しているので、下記のコマンドとは厳密には一致していません。)
$ export COMPOSE_DOCKER_CLI_BUILD=1
$ export DOCKER_BUILDKIT=1
$ docker compose build --ssh default
Discussion