🐋

Docker image を安定的に運用する

2024/03/11に公開

https://twitter.com/toms74209200/status/1765760663052493206


Docker image を Docker Hub などのレジストリに公開する場合の運用についてまとめます. この記事では上の zenn-cli の image を例として説明します.

Image の作成・公開

Dockerfile の書き方

基本的には公式で『Dockerfile を書くベストプラクティス』[1] が紹介されているのでこれを参考にすればよいです.

https://docs.docker.jp/develop/develop-images/dockerfile_best-practices.html

可能な限り Apple Silicon にも対応できるとよいです. base image が対応するか確認するとよいでしょう.

Node image の対応 platform
Node image の対応 platform node Tags | Docker Hub

Image の公開

Image の公開は今後定期的に実行されることになるため, CI/CD ツールを使って自動化します. ここでは GitHub Actions を利用します. GitHub Actions を使った image の公開についてはこれまた公式で『Docker イメージの発行』[2] が紹介されているのでこれを参考にすればよいです. 基本的には公開したいレジストリにログインして docker/build-push-action を利用するだけです.

https://docs.github.com/ja/actions/publishing-packages/publishing-docker-images

以下のように複数のレジストリをまとめて指定して公開することもできます.

      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:latest
            ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.DOCKER_IMAGE_NAME }}:${{ env.LATEST_TAG }}
            ghcr.io/${{ github.repository }}:latest
            ghcr.io/${{ github.repository }}:${{ env.LATEST_TAG }}

https://github.com/toms74209200/docker-zenn-cli/blob/a80585bcdeafa23a67e11eccd8dbc7ee75bd0772/.github/workflows/build_image.yml#L40-L47

Multi-platform image を公開する場合でも基本的には platform を複数指定するだけです. QEMU を使った build は時間がかかるものの, とても簡単に構築できるためよほどの理由がない限りはこれで十分と思われます. これも公式のドキュメント[3]を参考にしましょう.

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: user/app:latest

https://docs.docker.com/build/ci/github-actions/multi-platform/

Tag の管理

Docker image につける tag には image で利用するアプリケーションのバージョンや, base image のバージョンや variant (例えば debian や alpine など)がつけられることが多いようです.

Node image の tag
Node image の tag node - Official Image | Docker Hub

Image tag に variant を持たなければ, tag はバージョン情報だけになるため直線的な管理で済みます. この場合は Git の tag をそのまま使うことができます. 上記の zenn-cli の Docker image ではローカルリポジトリから手動で tag を切ってリモートリポジトリに push しています.

依存関係の管理

パッケージマネージャを使って依存関係の管理を行う場合, Dependabot や Renovate による自動更新が利用できます. 通常のアプリケーションと同様に管理するとよいでしょう. 依存関係更新に伴う Dockerfile の検証は難しいですが, image のビルドができるかや簡単なコマンドが実行できるかといったスモークテストがあるだけでも十分良いと思います. また Dependabot や Renovate では Dockerfile の base image の更新にも対応しています.

問題は APT や NPM のグローバルインストールなどの Dockerfile 上でのインストールされるアプリケーションです. 直接関係のないアプリケーションはバージョン指定せず, 定期的に image build を行って更新しましょう. 上記の zenn-cli の Docker image では NPM のグローバルインストールを利用しています. Dockerfile 上でインストールするアプリケーションのバージョンは Dependabot などを使って更新することができないため, 依存関係の管理のためには手動で更新するしかありません. 対策として zenn-cli の更新を検知するために package.json を作成し, Dependabot で更新を検知するようにしています. また Dockerfile 上でのインストールは minnor バージョンまでを指定し, patch バージョンは定期更新で対応するようにしています. もっとうまいやり方あったら教えてください.

RUN npm install -g zenn-cli@0.1

https://github.com/toms74209200/docker-zenn-cli/blob/master/Dockerfile#L5

運用の概要

Docker image の運用をまとめると以下のようになります.

  • Image の定期更新. GitHub Actions で image build を定期実行する.
  • Dependabot などを使った依存関係の管理.
  • 必要があれば Docker image tag の更新.

CI/CD ツールを使って自動化してしまえば, ほとんど手間をかけずメンテナンスできます.

脚注
  1. Dockerfile を書くベストプラクティス — Docker-docs-ja 24.0 ドキュメント ↩︎

  2. Docker イメージの発行 - GitHub Docs ↩︎

  3. Multi-platform image with GitHub Actions | Docker Docs ↩︎

Discussion