Amazon EC2 Container Service (ECS) と CircleCI を活用した Docker ベースなコーポレートサイト

コーポレートサイトを一部リニューアル

今月のはじめに、弊社のコーポレートサイトを一部リニューアルしている。
内容だけではなく、バックエンドのシステム側も AWS OpsWorks を使って構築した環境へデプロイしていたものから、 Amazon EC2 Container Service (ECS) を使った Docker ベースのものへと変更している。
弊社では、これまで開発環境では Docker を使っていたが、本番環境での Docker 運用はしていなかった。  
そろそろ本番環境でも Docker を使った環境に移行したいと思い、 ECS 環境への移行を行った。
今回は、その移行の際のポイントをまとめてみたいと思う。

Docker Hub

  • 前述のとおり、開発では Docker を使っており、Docker Hub を使っていたので、そのまま ECS でも Docker Hub を使っている(今回は Amazon EC2 Container Registry (ECR) は使わない)
  • Docker Hub にはあらかじめ Ruby on Rails で稼働している弊社コーポレートサイトが一通り動作する、ビルド済みのベースとなるイメージを置く
  • 開発時や、 CircleCI でテストを実行する際は、そのベースイメージを Pull してアプリケーションのソースを追加、テストが通ったら、アセットファイル群をプリコンパイルして、デプロイ。そうすることで、0からビルドするよりは時間の短縮が出来る
  • AWS ECR ではなくて、Docker Hub を使う場合、 ECS 対応 AMI の場合は下記のように /etc/ecs/ecs.config に追加する必要がある
1
2
ECS_ENGINE_AUTH_TYPE=docker
ECS_ENGINE_AUTH_DATA={"https://index.docker.io/v1/":{"username":"ユーザー名","password":"パスワード","email":"メールアドレス"}}
1
2
3
#!/bin/bash
echo "ECS_ENGINE_AUTH_TYPE=docker" >> /etc/ecs/ecs.config
echo 'ECS_ENGINE_AUTH_DATA={"https://index.docker.io/v1/":{"username":"ユーザー名","password":"パスワード","email":"メールアドレス"}}' >> /etc/ecs/ecs.config

CircleCI

  • CircleCI のバージョンは、ベータ中の 2.0 の検証がまだ出来ていないので、 1.0 を使用
  • 2.0 では docker-compose が使えたり、かなり便利になっているようなので、検証が出来次第そちらに移行したいと考えている
  • 【参考URL】Using docker-compose - CircleCI

Docker コンテナのビルド、キャッシュ

  • ビルドしたコンテナは、 tar ファイルとして保持しておく
  • ビルド実行時に、 tar ファイルを読み込んで、ビルドを高速化
  • tar ファイルが配置されている ~/docker ディレクトリはキャッシュする設定を追加
1
dependencies:
  cache_directories:
    - "~/docker"

  override:
    - if [[ -e ~/docker/image.tar ]]; then docker load -i ~/docker/image.tar; fi
    - docker build --rm=false -t app .
    - mkdir -p ~/docker; docker save app > ~/docker/image.tar

テストで使う MySQLDocker コンテナを使わない

  • CircleCI 環境でデフォルトで起動する MySQL を使って、テストを行う( DB のコンテナは作成しない)
  • アプリケーションのコンテナから、ホスト側で稼働している MySQL に接続するため、接続用のユーザー作成を行う
1
database:
  override:
    - mysql -uroot mysql < scripts/create_rails_user.sql

scripts/create_rails_user.sql は下記のような内容。

1
2
GRANT ALL PRIVILEGES ON *.* TO 'rails'@'%' identified by "rails";
FLUSH PRIVILEGES;
  • アプリケーションのコンテナから、ホスト側で稼働している MySQL に接続するため、外部接続設定(bind-address の行をコメントアウト)を変更
1
machine:
  pre:
    - sudo sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/mysql.conf.d/mysqld.cnf
  • テストは、 docker run で、下記のように実行
1
test:
  override:
    - docker run --add-host db:$(ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1) -e RAILS_DATABASE_HOST=db app bundle exec rspec spec

ECS

ログは標準出力するように

  • ログの出力を標準出力に変更して、 CloudWatch で確認できるように

例えば unicorn の設定ファイル config/unicorn.rb のログファイルの設定箇所をコメントアウトして、標準出力にすることで、 ECS で設定している CloudWatch のロググループにログストリームを送信できるようになる。

1
2
3
# log
# stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
# stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])

を使ってデプロイ

  • silinternational/ecs-deploy を使うと、簡単に Blue Green Deployment が出来てしまうのでこれを利用
  • CircleCI からは、下記のように実行している
1
- $(aws ecr get-login --region ap-northeast-1)
- docker tag app mmmcorp/corporate_web:$CIRCLE_SHA1
- docker push mmmcorp/corporate_web:$CIRCLE_SHA1
- ./scripts/ecs-deploy --timeout $ECS_TIMEOUT -c $PRD_ECS_CLUSTER -n $PRD_ECS_SERVICE -i mmmcorp/corporate_web:$CIRCLE_SHA1

Datadog

まとめ

CircleCIDocker コンテナをビルド、テスト実行して、 ECS へデプロイする際のポイントをざっくりとまとめてみた。
同じような環境を構築しようとしている方に、何か少しでも役に立てれば幸いである。
CircleCI 2.0 を使うことになった際には、また設定等の変更が必要になるので、そのときにはまた改めてブログにまとめられるといいかな、と思っている。

このエントリーをはてなブックマークに追加