AWS
RDS
CircleCI
docker
ECS

HEW2018 モダンなWebサービスの作成(インフラ編)

自己紹介

じゅんじゅんと言うニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。

HAL大阪3回生です。(2018/03/11現在)

イベントや、勉強会に参加してるので是非お会いした際はお声掛けください!

HEW2018 モダンなWebサービスの作成(インフラ編)とは

これは僕の学校のイベントの発表をQiitaの記事としてあげておくためのエントリーです。

気になる方はこちらをご覧ください。

インフラ以外には

があります。

環境

今回はAmazon Web ServiceのECS(Elastic Container Service)RDS(Relational Database Service)を使っていて、Docker ContainerをECSへCircleCIからオートデプロイしています。

以下、軽く用語の説明になります。

ECS

Amazon Elastic Container Service (ECS) は、非常にスケーラブルかつ高性能なコンテナ管理サービスで、Docker コンテナに対応しており、Amazon EC2 インスタンスのマネージドクラスターでアプリケーションを簡単に実行できます。

わかりやすい解説: Amazon EC2 Container Service(ECS)の概念整理

RDS

Amazon Relational Database Service (Amazon RDS) を使用すると、クラウド内でリレーショナルデータベースを簡単に設定、運用、およびスケールできます。ハードウェアのプロビジョニング、データベースのセットアップ、パッチ適用、バックアップなどの時間がかかる管理タスクを自動化しながら、コスト効率とサイズ変更可能なキャパシティーを提供します。

わかりやすい解説: weblio/Amazon RDS

Docker

「Docker(ドッカー)」とは、非常に軽量なコンテナ型のアプリケーション実行環境である。dotCloud社(現Docker社)が開発し、2013年にオープンソースのプロジェクトとして公開された。ソフトウェアの高速な配布・実行や容易なイメージのカスタマイズ、導入運用の手軽さ、豊富なプレビルドイメージの提供などの理由により、当初はソフトウェアの開発やテスト段階における利用が多かったが、現在ではパブリッククラウドからオンプレミスシステムまで、さまざまなシーンで急速に普及しつつある。

わかりやすい解説: Dockerについて基本から最近追加された機能までまとめ

CircleCI

Create custom environments, apply Workflows for control over your build pipeline, enjoy flexible resource allocation, and more.

わかりやすい解説: CircleCIで出来るコト

オートデプロイ

今回はCircleCIを使って、GitHubのmasterブランチにpushした時にコンテナをアップロードし、ECSに通知することを意味するとします!

動画にまとめました

手順を全てスクショとってやっているとかなり記事の画面を占領してしまうのでYouTubeにアップロードしましたので、そちらをご覧ください

ECS + RDSでのサービス作り

開発

今回はインフラなので、

  • circleci
  • Dockerfile
  • Makefile

の説明をしていきます。

Dockerfile

まずDockerfile

Dockerfile
FROM alpine:3.6
WORKDIR /root
ENV GO_ENV production

RUN set -x \
  && apk upgrade --no-cache \
  && apk --update add tzdata \
  && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
  && apk del tzdata \
  && rm -rf /var/cache/apk/*

RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*

ADD ./cmd/main .
ADD ./public ./public
ADD ./view ./view
ADD ./config.yml ./config.yml
ADD ./cmd/migrate .
ADD ./cmd/seed .

EXPOSE 8000

# Run it
ENTRYPOINT ["./main"]

1つずつ説明していきます。

FROM alpine:3.6

OSは軽量なalpineを使います

ENV GO_ENV production

これでDockerの環境変数を設定します。

今回は、productionモードで動いてほしいのでproductionを指定します。

ADD ./cmd/main .
ADD ./public ./public
ADD ./view ./view
ADD ./config.yml ./config.yml
ADD ./cmd/migrate .
ADD ./cmd/seed .

ここで、必要なファイルをDockerに移します。

EXPOSE 8000

# Run it
ENTRYPOINT ["./main"]

ここで、8000番ポートを開けておく設定をします。

AWSのECSのときのコンテナのポートと揃えてください。

goはビルドしているのでmainをたたけばサーバーが立ち上がるので、ENTRYPOINT./mainを指定します。

これで、docker runされたときに、./mainを叩いてくれてサーバーが立ち上がります。

Makefile

create:
    cp config.yml.template config.yml

migrate:
    go run migration/main.go

seed: migrate
    go run seed/main.go

go/build:
    make -f .circleci/ci.mk go/build

docker/build: go/build
    make -f .circleci/ci.mk docker/build

docker/push: go/build
    env NODE_ENV=production npm run build
    make -f .circleci/ci.mk docker/build
    make -f .circleci/ci.mk login
    make -f .circleci/ci.mk docker/push

makefileは基本的にコマンドなどを書いておきます。

今回ここのmakefileはローカルで触る場合を基本意識していてCIから触る方は.circleci/ci.mkに書いています。

なので、それを呼ぶ形にしています。

CircleCI

# ECS
ECS_ID := 871669327434
AWS_REGION := ap-northeast-1
APP := hew2018
export AWS_REGION
export AWS_DEFAULT_REGION=$(AWS_REGION)
DOCKER_IMAGE    := $(ECS_ID).dkr.ecr.$(AWS_REGION).amazonaws.com/$(APP):latest

login:
    aws configure set region $(AWS_REGION)
    aws configure set aws_access_key_id $$AWS_ACCESS_KEY_ID
    aws configure set aws_secret_access_key $$AWS_SECRET_ACCESS_KEY
    $$(aws ecr get-login --no-include-email --registry-ids $(ECS_ID) --region $(AWS_REGION))

go/build:
    make create
    env GOOS=linux env GOARCH=amd64 env CGO_ENABLED=0 go build -o ./cmd/main main.go
    env GOOS=linux env GOARCH=amd64 env CGO_ENABLED=0 go build -o ./cmd/migrate migration/main.go
    env GOOS=linux env GOARCH=amd64 env CGO_ENABLED=0 go build -o ./cmd/seed seed/main.go

docker/build:
    docker build -t $(DOCKER_IMAGE) --build-arg GO_ENV=production .

docker/push:
    docker push $(DOCKER_IMAGE)

docker/deploy:
    .circleci/ecs-deploy --enable-rollback --timeout 300 --cluster $(APP) --service-name $(APP) --image $(DOCKER_IMAGE)

基本のデプロイの流れとして、

  1. goをビルドする
  2. dockerをビルドする
  3. docker imageをpushする
  4. ecs-deployでdeploy作業をする

になっています。

基本変える場所としては

ECS_ID := 871669327434
AWS_REGION := ap-northeast-1
APP := hew2018

この3つだと思います。

ECS_IDはECSでリポジトリを作った際にかえってきたidです。
AWS_REGIONはAWSのリージョンを入力してください。
APPは、アプリケーション名を入力します。

この情報は全てリポジトリを作ったときに表示される

871669327434.dkr.ecr.ap-northeast-1.amazonaws.com/hew2018:latest

みたいなところから取得できます。

.circleci/config.yml

ここでcircleciの設定をかきます。

まずCircleCIで、GitHubのリポジトリを紐付けておくのを忘れないでください

あと、AWSのIAMをつくってそのユーザーのアクセスキーをCircleCIの設定のほうにかいておいてください。

version: 2
jobs:

  test:
    working_directory: /go/src/github.com/konojunya/HEW2018
    docker:
      - image: makki0205/deploy
    steps:
      - checkout
      - run:
         name: npm install
         command: npm install
      - run:
          name: component build
          command: env NODE_ENV=production npm run build
      - run:
          name: go build
          command: make -f .circleci/ci.mk go/build
      - save_cache:
          key: build-{{ epoch }}
          paths:
            - .

  deploy:
    working_directory: /go/src/github.com/konojunya/HEW2018
    docker:
      - image: makki0205/deploy
    steps:
      - setup_remote_docker:
          reusable: true
      - restore_cache:
          keys:
            - build
      - run:
          name: docker build
          command: make -f .circleci/ci.mk docker/build
      - run:
          name: aws login
          command: make -f .circleci/ci.mk login
      - run:
          name: docker push
          command: make -f .circleci/ci.mk docker/push
      - run:
          name: deploy
          command: make -f .circleci/ci.mk docker/deploy

workflows:
  version: 2
  build_and_deploy:
    jobs:
      - test
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: master

CircleCIはバージョン2を使うので2の設定になっています。

流れはworkflowのままです。

これでオートデプロイの環境を構築できました!

オートデプロイができるようになっているとプロダクトのコードに集中できるので少し設定が多くて難しいですがやっておいたほうがよいでしょう!

注意点として、

CircleCIの中でDockerを使う時は

- setup_remote_docker:
          reusable: true

これを入れておかないと、使えないです。

あとがき

Twitterしています!ぜひフォローください。 @konojunya

ソースコードは konojunya/HEW2018 にあります!