Background

我們嘗試把之前 docker-compose 的專案跟 CI service 整合在一起,本篇文章中我們使用CircleCI當作範例。並記錄一下整合的過程,預計的Flow為:

Push code to Github
        |
        V
CI automatically pulls repo
        |
        V
CI test code
        |
        V
CI build images for deploying
        |
        V
CI pushes built images to image repo(AWS ecr)

Testing

那這邊需要寫一些 unit test 讓 CI 有東西可以驗證程式是否通過,所以我加了一些 test code 在 server 專案中。詳細內容可以到我的Github 去看。(在CI Branch中)

CircleCI config

接下來到重頭戲啦,這邊分享一下我的 circleci config,大家可以先稍微看一下

.circleci/config.yml

version: 2
jobs:
  build-server:
    working_directory: ~/app
    docker:
      - image: circleci/python:3.6.4
        environment:
          PIPENV_VENV_IN_PROJECT: true
    steps:
      - checkout
      - run: sudo apt-get install python3-pip
      - run: sudo pip3 install --upgrade pip
      - run:
          command: |
            cd ~/app/server
            python3 -m venv venv
            . venv/bin/activate
            sudo pip3 install -r requirements.txt
      - save_cache:
          key: deps1-{{ .Branch }}-{{ checksum "server/requirements.txt" }}
          paths:
              -  ~/app/server/venv
      - run:
          command: |
            set -e
            export FLASK_APP=/home/circleci/app/server/run.py
            cd ~/app/server
            pytest -x

  build-client:
    working_directory: ~/app
    docker:
      - image: circleci/node:latest
    steps:
      - checkout
      - run:
          command: |
            cd ~/app/client 
            npm install
      - save_cache:
          key: deps1-{{ .Branch }}-{{ checksum "client/package.json" }}
          paths:
              -  ~/app/client/node_modules
      - run: echo "run test command"

  build-puhs-images:
    machine: true
    steps:
      - checkout
      - restore_cache:
          key: deps1-{{ .Branch }}-{{ checksum "server/requirements.txt" }}
      - restore_cache:
          key: deps1-{{ .Branch }}-{{ checksum "client/package.json" }}
      - run: sudo apt-get update
      - run: sudo apt-get install python3 python3-dev python3-pip
      - run: pip -V
      - run:
          name: Show current branch
          command: echo ${CIRCLE_BRANCH}
      - run:
          name: Show git commit id
          command: echo ${CIRCLE_SHA1}
      - run:
          name: Install aws cli
          command: sudo pip install awscli --upgrade --user
      - run:
          name: "Log in to AWS ECR"
          command: eval $(aws ecr get-login --no-include-email)
      - run: docker build -t taikerliang/flask-vue-crud-server ./server
      - run: docker build -t taikerliang/flask-vue-crud-client ./client
      - run: docker build -t taikerliang/flask-vue-crud-nginx ./nginx
      - run: docker tag taikerliang/flask-vue-crud-server ${ECR_URL}/flask-vue-crud:flask-vue-crud-server-${CIRCLE_BRANCH}
      - run: docker tag taikerliang/flask-vue-crud-client ${ECR_URL}/flask-vue-crud:flask-vue-crud-client-${CIRCLE_BRANCH}
      - run: docker tag taikerliang/flask-vue-crud-nginx ${ECR_URL}/flask-vue-crud:flask-vue-crud-nginx-${CIRCLE_BRANCH}
      - run: docker push ${ECR_URL}/flask-vue-crud:flask-vue-crud-server-${CIRCLE_BRANCH}
      - run: docker push ${ECR_URL}/flask-vue-crud:flask-vue-crud-client-${CIRCLE_BRANCH}
      - run: docker push ${ECR_URL}/flask-vue-crud:flask-vue-crud-nginx-${CIRCLE_BRANCH}
workflows:
  version: 2
  build_and_test:
    jobs:
      - build-server
      - build-client  
      - build-puhs-images:
          requires:
            - build-server
            - build-client  

稍微講解一下config檔的內容,整個config檔分為三塊:

  • build-server: 針對 server 端的程式碼建置環境&進行測試
  • build-client: 針對 client 端的程式碼建置環境&進行測試
  • build-puhs-images: 在上面前後端的程式碼都通過測試後我們會進行建立image的動作,並把建立好的image push到 AWS ECR上。

那另外其實測試可以分建好image在測試或是不需要建立image測試。那我選擇時後者,主要是我看到別人的解釋的原因再加上我覺得這樣也比較單純。 下面附上別人解釋的原因(原文連結)

Although we’re going to build a Docker image, you don’t have to work with the Docker image right away for this step. In general, you don’t have to use Docker for EVERYTHING. It’s completely alright to have a non-Dockerized dev workflow, as long as you keep the tradeoffs in mind.

In this case, we won’t have to build an image before running tests, we can save on work by using CircleCI deafault configs which are well tested and make use of caching. If there are no special OS dependencies which are needed to run tests for your code that’s fine.

最後都Run完沒問題後我們打開 AWS ECR 的 Console查看,會看到以下結果:

Screen-Shot-2019-07-08-at-6.34.04-PM

Reference