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

これはCircleCI2.0がBetaの頃に書いた記事なので正式リリースされた時は変わっている可能性はあります

hatappi.hateblo.jp

昨日はTravis CIネタを書きましたが今回はCircleCI 2.0ネタ
CircleCI2.0から実行環境にDocker Imageが使えるようになり、1の頃に必要だったミドルウェアなどをインストールしてなどの時間を自分で作成したImageやDocker HubにあがっているDocker Imageを使って環境を素早く提供できるようになりました

1.0から2.0になって実行時間が半分になった記事なども見かけます
engineer.crowdworks.jp

また個人的に面白いなと思ったのがワークフローが組めるようになったことです 参考: Orchestrating Workflows CircleCI側としてはワークフローは下記のようなケースの場合に検討すると良いそうです

  • Run and troubleshoot jobs independently
  • Fan-out to run multiple jobs in parallel for testing various versions
  • Fan-in for deployment to separate platforms with automated triggers
  • Branch-level job execution with artifact sharing

今回はbuildするjobとPackerでデプロイするjobをわけて実行したいためワークフローを使うことにしました
その理由としては一番大きいのはDockerコンテナ上でPackerを動作させようとするとビルドできないことです…
せっかくCircleCI2.0で任意のコンテナが立てやすくなったのにPackerのせいで使えなくなるのは辛い….
これらはすでにPackerでは議論されていてPRもあがっているようですが、まだ時間はかかりそうです

設定

まずは今回検証用のPackerで使用するjsonを用意します
中身はシンプルでubuntuのDocker ImageをベースにSAMPLE!!!!という中身の/tmp/sampleを作成して最後にDocker HubにPushするだけです

次がCircleCI2.0のYAMLファイル
今まではプロジェクトのRootディレクトリ直下においていましたが2.0からは.circleci/config.ymlに置くようになりました

まずjobの説明をしていきます

build:
    docker:
      - image: ruby:2.4.1
    working_directory: ~/circleci-2.0
    steps:
      - checkout
      - run: ruby -v

build jobでは動作環境をruby 2.4.1にしてDocker Hubから取得するようにしています
steps内でこの動作環境での実際に何をするかを記載していくのですが
- checkoutで対象リポジトリをgit経由でおとしてきます
run: にコマンドを定義することが出来て今回は単にrubyのバージョンだけを表示するようにしています
他にどんなものが設定できるかなどは docを見ていただくのが良いかと思います

おそらく実際の運用ではRailsだったらrubocopとかrspecとか走らせるようなものを記載していくと思います

deploy:
    machine: true
    working_directory: ~/circleci-2.0
    steps:
      - checkout

      - run: docker --version
      - run: go version
      - run:
          name: Install Packer
          command: |
            set -xe
            sudo apt-get install -y unzip
            curl -L -o packer.zip https://releases.hashicorp.com/packer/1.0.0/packer_1.0.0_linux_amd64.zip
            unzip packer.zip
            rm packer.zip
            sudo mv packer /usr/local/bin
            packer version
      - run:
          name: Build images
          command: |
            set -xe
            packer build sample.json

次がdeploy jobです
先程は動作環境はDockerでしたが今回はmachine: true にしています
これを設定するとDockerではなくVM上でUbuntu 14.04で動作するようです

後はPackerのバイナリを公式からダウンロードしてきて、先程作成したPacker用のjsonファイルを指定して実行すればDocker Hubにイメージが出来上がります

これで一通りのjobが定義できました
最後がワークフローです

workflows:
  version: 2
  test_and_deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master

今回はシンプルでbuildは毎回行うようにしてあり、deployに関してはmasterの時のみかつbuildが成功したらにしています
その他の設定に関してはdocをご覧ください

実行

master以外の時は

f:id:hatappi1225:20170616152705p:plain

masterの時は

f:id:hatappi1225:20170616152723p:plain

のようになります