CircleCI
CircleCI2.0

CircleCI2.0でDockerをビルドしてDocker HubにPushするまで

CircleCI2.0ハンズオン!シリーズです。

今回はCircleCI2.0でDockerをビルドしてDocker HubにPushするまでやってみます。

config.yml

Tag作成をトリガーにGitHubのTagと同じTagのイメージとlatestを作成します。

.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/golang:1.9.3
    working_directory: /go/src/github.com/project/repo
    steps:
      - setup_remote_docker:
          version: 17.11.0-ce
          docker_layer_caching: true
      - checkout
      - run:
          name: Build
          command: docker build -t ${OWNER}/${IMAGE_NAME}:latest .
      - run:
          name: Tag to latest
          command: docker tag ${OWNER}/${IMAGE_NAME}:latest ${OWNER}/${IMAGE_NAME}:$CIRCLE_TAG
      - run:
          name: Docker Login
          command: docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
      - run:
          name: Push image to registory
          command: docker push ${OWNER}/${IMAGE_NAME}
workflows:
  version: 2
  build:
    jobs:
      - build:
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /.*/

ビルドにcircleciのイメージを使う

そもそもsetup_remote_dockermachine:trueで動かないらしいので、dockerイメージを使ってビルドしています。

Note: setup_remote_docker is not curently compatible with the machine executor.

また、circleci/golang:1.9.3を使用していますが、素のgolang:1.9.3には当然、dockerなどビルドするときに欲しいコマンドがありません。

そこで、ビルドに必要なコマンドが揃っているcircleciのイメージを使っています。

Docker provides official images for popular languages and services that are aimed to work in common context, whether in development or in production. CircleCI highly recommends using them for creating custom images that are more appropriate for users.

However, we frequently found them lacking some tools making them appropriate for dev/CI use. CircleCI publishes this image to extend the images in the following ways:

  1. Common tools used in development and CI are installed e.g. git, ssh, tar, ca-certificates, curl, wget.
  2. Docker tools: latest docker, docker-compose, and dockerize are installed
  3. Variants for common use cases, e.g. images with common browsers installed and configured to run in a containized environment
  4. Use a non-root user (namely circleci) by default. Many applications refuse to run as run (e.g. chrome) or their behavior differs when run as root (e.g. tar file ownership behavior)

https://hub.docker.com/r/circleci/golang/

setup_remote_dockerversionを指定する

2018年1月28日現在、setup_remote_dockerは以下のdockerバージョンに対応しています。

defaultで17.03.0-ceに設定されてしまうので、新しいバージョンを指定しておきます。

特にmulti-stage buildsなんかをやる場合は17.05.0-ce以上のバージョンでないとコケます。

The currently supported versions are:

  • 17.03.0-ce (default)
  • 17.05.0-ce
  • 17.06.0-ce
  • 17.06.1-ce
  • 17.07.0-ce
  • 17.09.0-ce
  • 17.10.0-ce
  • 17.11.0-ce

https://circleci.com/docs/2.0/building-docker-images/#docker-version

workflowsを設定する

buildをただ実行するだけなら、workflowを設定する必要がありませんが、Tagがついてるときのみにしたかったので、「全ブランチ無視」「全タグトリガー」にしました。

通常のcommitはビルドだけ行い、TagがついたらPushする

builddocker image save.tarに書き出し、pushではdocker loadで展開するようにしました。

.circleci/config.yml
alias:
  default_env: &default_env
    docker:
      - image: circleci/golang:1.9.3
    working_directory: /go/src/github.com/project/repo
  setup_remote_docker: &setup_remote_docker
    version: 17.11.0-ce
    docker_layer_caching: true

version: 2
jobs:
  build:
    <<: *default_env
    steps:
      - setup_remote_docker: *setup_remote_docker
      - checkout
      - run:
          name: Build
          command: docker build -t ${OWNER}/${IMAGE_NAME}:latest .
      - run:
          name: Save image
          command: docker image save ${OWNER}/${IMAGE_NAME}:latest > ./docker-image.tar
      - persist_to_workspace:
          root: .
          paths:
            - ./docker-image.tar
  push:
    <<: *default_env
    steps:
      - setup_remote_docker: *setup_remote_docker
      - attach_workspace:
          at: .
      - run:
          name: Load image from tar
          command: docker load -i ./docker-image.tar
      - run:
          name: Tag to latest
          command: docker tag ${OWNER}/${IMAGE_NAME}:latest ${OWNER}/${IMAGE_NAME}:$CIRCLE_TAG
      - run:
          name: Docker Login
          command: docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
      - run:
          name: Push image to registory
          command: docker push ${OWNER}/${IMAGE_NAME}
workflows:
  version: 2
  build:
    jobs:
      - build:
          filters:
            tags:
              only: /.*/
      - push:
          requires:
            - build
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /.*/

まとめ

Docker HubでもAutomated buildsがありますが、遅すぎてイライラすることが多かったので、CircleCIでビルドすればそのストレスから解放されそうです。