GitHub Action で,docker/setup-buildx-actionを用いて複数のイメージを扱ってみます.
前提条件
簡単な例として,pip
コマンドで依存関係を解決して,結果を表示する Docker イメージをビルドします.
Dockerfile
FROM python:3.11-slim-bullseye WORKDIR /app COPY requirements.txt . RUN pip install --upgrade pip RUN pip install wheel RUN pip install -r requirements.txt COPY . . CMD ["pip", "freeze"]
イメージを1個ビルドする
app/requirements.txt
flask
.github/workflows/ci.yaml
name: ci on: push jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build app uses: docker/build-push-action@v4 with: context: app push: false load: true tags: app:latest cache-from: type=gha cache-to: type=gha,mode=max - name: Run app image run: docker run app:latest
これを実行すると,初回は以下のようにflaskがインストールされます.
... #10 3.963 Collecting flask #10 3.992 Downloading Flask-2.2.2-py3-none-any.whl (101 kB) #10 3.999 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 101.5/101.5 kB 19.6 MB/s eta 0:00:00 ...
もう一度実行すると,キャッシュにより高速になります.
#10 [4/5] RUN pip install --upgrade pip && pip install wheel && pip install -r requirements.txt #10 CACHED
以下の画面でキャッシュを削除してからもう一度実行すると,flask がインストールされます.
... #10 3.838 Collecting flask #10 3.856 Downloading Flask-2.2.2-py3-none-any.whl (101 kB) #10 3.865 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 101.5/101.5 kB 15.7 MB/s eta 0:00:00 ...
最終的には以下のように出力されました.
click==8.1.3 Flask==2.2.2 itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.2 Werkzeug==2.2.2
コマンドが正常に実行されていることがわかりました.
イメージを2個ビルドする
app の他に,別のイメージである app2 をビルドしてみます.
app2/requirements.txt
django
.github/workflows/ci.yaml
name: ci on: push jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build app uses: docker/build-push-action@v4 with: context: app push: false load: true tags: app:latest cache-from: type=gha cache-to: type=gha,mode=max - name: Run app image run: docker run app:latest - name: Build app2 uses: docker/build-push-action@v4 with: context: app2 push: false load: true tags: app2:latest cache-from: type=gha cache-to: type=gha,mode=max - name: Run app2 image run: docker run app2:latest
一見うまくいきそうですが,キャッシュが使用されなくなります.異なるイメージを交互にビルドしてしまい,互いにキャッシュを破棄してしまうからです.
scope を指定する
scope=<scope>: which scope cache object belongs to (default buildkit)
GitHub - moby/buildkit: concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit
name: ci on: push jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build app uses: docker/build-push-action@v4 with: context: app push: false load: true tags: app:latest cache-from: type=gha,scope=app # Add scope cache-to: type=gha,mode=max,scope=app # Add scope - name: Run app image run: docker run app:latest - name: Build app2 uses: docker/build-push-action@v4 with: context: app2 push: false load: true tags: app2:latest cache-from: type=gha,scope=app2 # Add scope cache-to: type=gha,mode=max,scope=app2 # Add scope - name: Run app2 image run: docker run app2:latest
これでキャッシュが使われるようになりました.最終的には以下のような出力になり,正常にビルドできたことがわかりました.
app
click==8.1.3 Flask==2.2.2 itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.2 Werkzeug==2.2.2
app2
asgiref==3.6.0 Django==4.1.6 sqlparse==0.4.3