LoginSignup
26
31

More than 5 years have passed since last update.

Docker イメージを作って AWS EC2 Container Registory (ECR) にプッシュし、ElasticBeanstalk でデプロイする

Last updated at Posted at 2016-10-03

Amazon Web Service の EC2 Container Registory (ECR) は、フルマネージドな Docker コンテナリポジトリです。プライベートな Docker イメージをプッシュし、EC2にデプロイすることができます。

今回の構成

  • AWS EC2 Container Registory (ECR)
  • AWS ElasticBeanstalk
  • Docker
  • Python3
  • Django1.10
  • uwsgi
  • nginx
  • supervisor
  • Fabric

手元で、Python3 + Django の Docker イメージを作り、EC2 Container Registory (ECR) にプッシュし、ElasticBeanstalk (EB) でデプロイするまで書きます。

サンプルコード

こちらです。 https://github.com/ytyng/aws-eb-docker-django-skeleton

Fabric の準備

fabric は必須ではありませんが、私はコマンドをすぐ忘れてしまうため fabric のコマンド化してあります。

とはいえ、サーバに SSH でデプロイするわけではないので、fabric の本来の使い方ではないですね。(make や invoke なんかで良さそうです)

fabfile

fabric は、あらかじめローカル環境にインストールしておく必要があります。
おそらく、Python3 では動作しないため、ローカルの Python2 環境に
インストールする必要があります。

$ python
Python 2.7.10
...

$ sudo pip install fabric

Dockerイメージのビルド

$ fab build

(もしくは $ docker build -t aws-eb-docker-django-skeleton )

Dockerfile
FROM ubuntu:16.04

MAINTAINER ytyng

RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    python3-dev \
    python3-setuptools \
    nginx \
    supervisor \
  && rm -rf /var/lib/apt/lists/*

# for pil
# apt-get install libjpeg-dev
# RUN ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib/libjpeg.so

# for ipython
# apt-get install lib32ncurses5-dev

# set locale
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

# Python packages
COPY requirements/base.txt /tmp/requirements/base.txt
COPY requirements/production.txt /tmp/requirements/production.txt
RUN pip3 install -r /tmp/requirements/base.txt
RUN pip3 install -r /tmp/requirements/production.txt

# setup all the configfiles
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
COPY conf/nginx-app.conf /etc/nginx/sites-available/default
COPY conf/supervisor-app.conf /etc/supervisor/conf.d/

RUN mkdir /var/log/django

COPY . /var/django/aws-eb-docker-django-skeleton

EXPOSE 80
EXPOSE 443
CMD ["supervisord", "-n"]

Dockerfile

DBマイグレーション

$ fab manage:migrate

↑コマンドが何をしているかは fabfile を見てみてください

サーバ起動

$ fab up

(ポート 80, 443 をバインドします)

docker-compose.yml
version: '2'
services:
  aws-eb-docker-django-skeleton:
    build: .
    image: aws-eb-docker-django-skeleton
    container_name: aws-eb-docker-django-skeleton
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - .:/var/django/aws-eb-docker-django-skeleton
    environment:
      - UWSGI_PROCESSES=1
      - UWSGI_THREADS=1
      - APP_NAME=aws-eb-docker-django-skeleton
      - DJANGO_APP_NAME=aws_eb_docker_django_skeleton
      - DJANGO_SETTINGS_MODULE=aws_eb_docker_django_skeleton.settings.local

docker-compose.yml

$ docker-machine ls でIPアドレスを調べ(例: 192.168.99.100 )、
ブラウザで開くと起動ページが見れます

$ open "http://192.168.99.100/"

スクリーンショット 2016-10-03 18.06.14.png

Docker リポジトリを、AWS EC2コンテナサービス (ECS) に登録する

プライベートリポジトリとして登録できます。

1. ローカルPCの AWS CLI を設定 (既に行っていれば不要)

1-1. IAM より、ローカルコンピュータに保存するログインクレデンシャルを作っておきます。
既に作ってある場合は不要です。

IAMページ

ユーザー → 新規ユーザーの作成

ユーザー名 適当に (例: aws-cli )

スクリーンショット 2016-10-03 16.48.17.png

ユーザーのセキュリティ認証情報を表示 をクリックし、アクセスキー ID と シークレットアクセスキー を保存しておく。

もしくは「認証情報のダウンロード」を押して、CSVを保存しておく。

閉じる をクリック

スクリーンショット 2016-10-03 17.02.24.png

作成したユーザーを選択し、「ポリシーのアタッチ」

スクリーンショット 2016-10-03 17.02.42.png

AmazonEC2ContainerRegistryFullAccess をアタッチしておきましょう

スクリーンショット 2016-10-03 17.04.02.png

スクリーンショット 2016-10-03 17.04.19.png

1-2. aws cli のインストール

$ sudo pip install awscli --upgrade --ignore-installed six

1-3. aws を設定

$ aws configure

さきほどのクレデンシャル情報を入力しておく

AWS Access Key ID [None]: AK................
AWS Secret Access Key [None]: ********************************
Default region name [None]: ap-northeast-1
Default output format [None]:

2. AWS EC2 コンテナリポジトリの設定とイメージのプッシュ

2-1. AWS コンソールの ECSページを表示

ECSページ

初回起動時、チェックボックスが出ます。

Store container images securely with Amazon ECR にチェックON して Continue。

スクリーンショット 2016-10-03 16.39.16.png

Repository name にリポジトリ名を入力して、Next step。

すると、コンソールでの手順が表示されます。

スクリーンショット 2016-10-03 16.42.15.png

2-2. ローカルでコンテナ登録コマンド実行

表示されたコマンドにそって

$ aws ecr get-login --region ap-northeast-1

ターミナルから入力すべきコマンドが表示されます。つまり、やるべきことは

$ $(aws ecr get-login --region ap-northeast-1)

です。

$ $(aws ecr get-login --region ap-northeast-1)
Flag --email has been deprecated, will be removed in 1.13.
Login Succeeded

fab のコマンドも用意してあります。 $ fab login_ecr

引き続き、AWSのページの手順に沿って続けます。

$ docker tag aws-eb-docker-django-skeleton:latest 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/aws-eb-docker-django-skeleton:latest
$ docker push 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/aws-eb-docker-django-skeleton:latest

fab のコマンドも用意してあります $ fab push

3. プッシュしたイメージから ElasticBeanstalk でインスタンスを作成

3-1. EBを作成

EB のページを表示

プラットフォームの選択 は、Multi-container Docker にして、「今すぐ起動」

スクリーンショット 2016-10-03 17.19.59.png

(※起動する Docker コンテナは1つですが、単一Docker コンテナの設定ファイルと互換性が無いため、あとからコンテナを増やしたい場合等に困ります。マルチコンテナDockerで全く問題無いでしょう。(メモリ設定が必須で少し面倒なぐらい?))

そしたら、「初めての Elastic Beanstalk アプリケーション」という変なアプリケーションが
出来たので、これは無視して右上の「新しいアプリケーションの作成」をクリック

スクリーンショット 2016-10-03 17.23.29.png

アプリケーション名は適当に、例: aws-eb-docker-django-skeleton

→ 次へ → ウェブサーバーの作成 →

スクリーンショット 2016-10-03 17.24.35.png

プラットフォームの選択: Multi-container Docker

環境タイプ: 単一インスタンス

→ 次へ

送信元: 独自のアップロード

今回は、手作業で Json ファイルをアップロードします。

本来は、S3経由でコマンドでアップロードなどした方が良いと思うのですが、
ここの ベストプラクティスはまだ確立できていません。(ebコマンドでできるか等もまだ不明…)

EC2コンテナサービス (ECS) を使う場合、Dockerrun.aws.json だけアップロードすれば良いです。

Dockerrun.aws.json
{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "aws-eb-docker-django-skeleton",
      "image": "000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/aws-eb-docker-django-skeleton:latest",
      "essential": true,
      "environment": [
        {
          "name": "UWSGI_PROCESSES",
          "value": "2"
        },
        {
          "name": "UWSGI_THREADS",
          "value": "2"
        },
        {
          "name": "APP_NAME",
          "value": "aws-eb-docker-django-skeleton"
        },
        {
          "name": "DJANGO_APP_NAME",
          "value": "aws_eb_docker_django_skeleton"
        },
        {
          "name": "DJANGO_SETTINGS_MODULE",
          "value": "aws_eb_docker_django_skeleton.settings.production"
        }
      ],
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80
        },
        {
          "hostPort": 443,
          "containerPort": 443
        }
      ],
      "memory": 256,
      "memoryReservation": 128
    }
  ]
}

Dockerrun.aws.json

image の箇所を修正した json ファイルを、「独自のアップロード」のファイルに指定します。

環境名、環境URL は、例: aws-eb-docker-django-skeleton を入力

スクリーンショット 2016-10-03 17.30.59.png

その他のリソース は、今回は使わないのでチェック無しで「次へ」

スクリーンショット 2016-10-03 17.31.17.png

構成の詳細は適当に。今回はテストなので t1.micro で充分です

スクリーンショット 2016-10-03 17.32.26.png

環境タグ も不要なので入力せずに「次へ」

アクセス制限 も、そのままで『次へ」

スクリーンショット 2016-10-03 17.33.08.png

内容がプレビューされますので、「起動」

スクリーンショット 2016-10-03 17.33.38.png

しばらく待つとインスタンスが作られるのですが、そのままでは下記のようにエラーになります。

ECS task stopped due to: Essential container in task exited. (aws-eb-docker-django-skeleton: CannotPullContainerError: AccessDeniedException: User: arn:aws:sts::000000000000:assumed-role/aws-elasticbeanstalk-ec2-role/i-00000000 is not authorized to perform: ecr:GetAuthorizationToken on resource: * status code: 400, request id: 00000000-0000-0000)

スクリーンショット 2016-10-03 17.53.13.png

スクリーンショット 2016-10-03 17.53.01.png

3-2. ロールにポリシーを設定

エラーの原因は、EB のロールが ECS (コンテナレジストリ) の GetAuthorizationToken
権限が無いためです。付与しましょう。

IAM のロールページ

から、aws-elasticbeanstalk-ec2-role を選択し、「ポリシーのアタッチ」→ container で検索して、

AmazonEC2ContainerRegistryReadOnly をアタッチします。

スクリーンショット 2016-10-03 17.58.30.png

スクリーンショット 2016-10-03 17.59.16.png

3-3. 再デプロイ

EB のアプリケーションのページの、アップロードとデプロイ → アプリケーションバージョン ページ

スクリーンショット 2016-10-03 18.02.26.png

「最初のリリース」を選択して「デプロイ」

Environment update completed successfully. になりました。

スクリーンショット 2016-10-03 18.04.49.png

4. ページ確認

EB には1つの URL が割り当てられます。例: aws-eb-docker-django-skeleton.ap-northeast-1.elasticbeanstalk.com

ブラウザでEBのURLにアクセスするとページが表示されます。

スクリーンショット 2016-10-03 18.06.14.png

追記

EB でデプロイすると、遅いですしダウンタイムもあったので少し使いづらいですね。

複数台構成にしてローリングデプロイなんかで対応する必要がありそうですが、 uwsgi や gunicorn は無停止リロードができるのでせっかくなら活用したい所です。

26
31
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
31