LoginSignup
2
0

More than 1 year has passed since last update.

DockerHubが無課金で自動ビルド出来なくなったのでCircleCIからDockerイメージビルドしてプッシュする

Last updated at Posted at 2021-10-10

DockerHubが無課金で自動ビルド出来なくなった

公式ブログの記事によるとDockerHubの自動ビルドが暗号通貨マイニングに悪用されているため、2021年6月18日から無料利用枠でのAutobuildを廃止したとのこと。

CircleCIでDockerイメージビルドしてDockerHubにプッシュする

DockerHubには課金せず、CircleCIでDockerイメージをビルドしてDockerHubにプッシュする方法を考える。
CircleCIで使用する自前executorが必要なので、本末転倒だがCirleCIでビルドしてDockerHubに置くことにする。
手順は以下の通り

  1. GitHubにレポジトリを作って.circleci/config.ymlDockerfileを置く
  2. DockerHubにレポジトリを用意
  3. CirleCIに環境変数と登録しビルド〜プッシュを実行

.circleci/config.ymlの構成

GitHubのレポジトリにアップしたconfig.ymlこちら
再利用性を高めるため以下の3つのブロックで構成している。

commands

commandsは5つ用意した。

  1. command-docker_checksumはコンテキストディレクトリからキャッシュ用のチェックサムを生成する
  2. command-docker_buildはビルドを実行する
  3. command-docker_loadはキャッシュをロードする
  4. command-docker_saveはキャッシュを保存する
  5. command-docker_pushはプッシュを実行する
commands
commands:
  command-docker_checksum:
    parameters:
      context:
        type: string
    steps:
      - run:
          name: generate checksum.txt
          command: |
            rm -f /tmp/checksum.txt
            cat $(find << parameters.context >> -type f | sort) >> /tmp/checksum.txt
  command-docker_build:
    parameters:
      context:
        type: string
      dockerfile:
        type: string
        default: Dockerfile
      target:
        type: string
        default: ""
      image:
        type: string
      tag:
        type: string
        default: build
    steps:
      - run:
          name: docker login
          command: |
            docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD
      - run:
          name: docker build
          command: |
            if [ -z "<< parameters.target >>" ]; then
              docker build --tag=<< parameters.image >>:<< parameters.tag >> --file=<< parameters.context >>/<< parameters.dockerfile >> << parameters.context >>
            else
              docker build --tag=<< parameters.image >>:<< parameters.tag >> --file=<< parameters.context >>/<< parameters.dockerfile >> --target << parameters.target >> << parameters.context >>
            fi
  command-docker_load:
    parameters:
      workdir:
        type: string
        default: /tmp/docker
      image:
        type: string
      tag:
        type: string
        default: build
    steps:
      - run:
          name: docker load
          command: |
            if [ -f "<< parameters.workdir >>/$(basename '<< parameters.image >>')_<< parameters.tag >>.tgz" ]; then
              gunzip -c << parameters.workdir >>/$(basename '<< parameters.image >>')_<< parameters.tag >>.tgz | docker load
              docker images << parameters.image >>:<< parameters.tag >>
            else
              echo "no cache"
            fi
  command-docker_save:
    parameters:
      workdir:
        type: string
        default: /tmp/docker
      image:
        type: string
      tag:
        type: string
        default: build
    steps:
      - run:
          name: docker save
          command: |
            if [ -n "$(docker images -q << parameters.image >>:<< parameters.tag >>)" ]; then
              mkdir -p << parameters.workdir >>
              docker save << parameters.image >>:<< parameters.tag >> $(docker history -q << parameters.image >>:<< parameters.tag >> | tail -n +2 | grep -v \<missing\> | tr '\n' ' ') | gzip > << parameters.workdir >>/$(basename '<< parameters.image >>')_<< parameters.tag >>.tgz
            else
              exit 1
            fi
  command-docker_push:
    parameters:
      image:
        type: string
      tag:
        type: string
        default: build
      repo:
        type: string
    steps:
      - run:
          name: docker login
          command: |
            docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD
      - run:
          name: docker push
          command: |
            if [ -n "$(docker images -q << parameters.image >>:<< parameters.tag >>)" ]; then
              if [ -n "${CIRCLE_TAG}" ]; then
                docker tag << parameters.image >>:<< parameters.tag >> ${DOCKER_LOGIN}/<< parameters.repo >>:${CIRCLE_TAG}
                docker images ${DOCKER_LOGIN}/<< parameters.repo >>:${CIRCLE_TAG}
                docker push ${DOCKER_LOGIN}/<< parameters.repo >>:${CIRCLE_TAG}
              else
                docker tag << parameters.image >>:<< parameters.tag >> ${DOCKER_LOGIN}/<< parameters.repo >>:latest
                docker images ${DOCKER_LOGIN}/<< parameters.repo >>:latest
                docker push ${DOCKER_LOGIN}/<< parameters.repo >>:latest
              fi
            else
              exit 1
            fi

executors

docker builddocker pushを使いたいのでDocker公式イメージをexecutorsとして利用する。

executors
executors:
  docker:
    docker:
      - image: library/docker:latest
        auth:
          username: $DOCKER_LOGIN
          password: $DOCKER_PASSWORD

jobsとworkflows

commandsに渡すcontextimageはGitHubレポジトリと同じ。キャッシュ名も同様。

jobs
jobs:
  docker_build:
    executor:
      name: docker
    steps:
      - setup_remote_docker
      - checkout
      - command-docker_checksum:
          context: awscli-executor
      - restore_cache:
          keys:
            - awscli-executor-v1-{{ checksum "/tmp/checksum.txt" }}
            - awscli-executor-v1
      - command-docker_load:
          image: awscli-executor
      - command-docker_build:
          context: awscli-executor
          image: awscli-executor
      - command-docker_save:
          image: awscli-executor
      - save_cache:
          key: awscli-executor-v1-{{ checksum "/tmp/checksum.txt" }}
          paths:
            - /tmp/docker
      - persist_to_workspace:
          root: /tmp
          paths:
            - docker
  docker_push:
    executor:
      name: docker
    steps:
      - setup_remote_docker
      - checkout
      - command-docker_checksum:
          context: awscli-executor
      - restore_cache:
          keys:
            - awscli-executor-v1-{{ checksum "/tmp/checksum.txt" }}
            - awscli-executor-v1
      - command-docker_load:
          image: awscli-executor
      - command-docker_push:
          image: awscli-executor
          repo: awscli-executor

workflowsmainブランチはlatestとしてタグはタグ名でDockerHubにDockerイメージがプッシュされる。

workflows
workflows:
  version: 2
  default:
    jobs:
      - docker_build:
          filters:
            tags:
              only: /.*/
      - docker_push:
          requires:
            - docker_build
          filters:
            tags:
              only: /.*/
            branches:
              only: main

Dockerfile

AWS CLIのexecutorのDockerfileconfig.ymlに書いたcontextと同じ名前のディレクトリに配置する。

Dockerfile
FROM library/docker:19.03.15
ENV AWS_CLI_VERSION 2.0.63
ENV GLIBC_VER 2.31-r0
RUN apk update \
 && apk add --no-cache \
    bash \
    curl \
 && curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub \
 && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk \
 && curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk \
 && apk add --no-cache \
    glibc-${GLIBC_VER}.apk \
    glibc-bin-${GLIBC_VER}.apk \
 && apk add --virtual .build-deps \
    binutils \
    unzip \
    zip \
 && curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI_VERSION}.zip -o awscliv2.zip \
 && unzip -q awscliv2.zip \
 && ./aws/install \
 && rm -f awscliv2.zip \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/*

DockerHubにレポジトリを用意

config.ymlに書いたimage名と同じ名前の空のレポジトリを作成するだけ。

CirleCIの設定

作成したGitHubレポジトリを取り込んでDockerHubログインの情報を環境変数(DOCKER_LOGINDOCKER_PASSWORD)として登録する。

20211010153010.png

DockerHubにプッシュしたイメージの確認

これでGitHubへのプッシュすれば今までと同じようにDockerHubにビルドイメージが自動でアップされる。

20211010161427.png

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0