2018-12-13

Django を ECS(Fargate) に手動デプロイしたログ

この記事は BeProud Advent Calendar 2018の 13日目の記事です BeProud Advent Calendar 2018 - Adventar普段忙しくてなかなかブログを書けない人のケツを叩くための BeProud アドベントカレンダーです 内容は技術的なことなら何でもOK BeProud に関係してる人なら誰でも、としたいんですが 枠が限られているので [BeProud](https://www.beproud.jp/) の社員か元社員の方に優先的に入ってもらいたい気持ちです カレンダー作成者でも枠の登録削除はできないようなので良識の範囲で登録してください 何かあれば [Twitter](https://twitter.com/crohaco) で連絡くださいhttps://adventar.org/calendars/3338

時代は既に EKS かもしれませんが、 以前案件で ECS に Django アプリをデプロイしたので プロジェクト構築手順を 残しておきます。

時間を無駄にしたくないし他の人にもしてほしくないので 俺の屍を超えていけ(定期)

info
  • 実は作るのは2回目なんで、すぐ終わるかなーと思ってたら 権限関係のトラブルが続出して精神が折れかけたので 今回は AdministratorAccess 権限で作ることにします。
  • DNS は Route53 を使おうかと思ったんですが移管とかめんどくさいし、 新ドメインを取るお金がもったいないので別サイトで管理している既存のドメインを使います。
  • 今回のシナリオは以下です
  • Djampleという私が作成したサンプル用アプリを ECS にデプロイ
    • PostgreSQL (RDS) に接続する
    • ドメインとして djample.crohaco.net を割り当てる
    • HTTPS 対応する

準備

認証情報

グループ と ユーザを作成。

グループには AdministratorAccess ポリシーを割り当てています。

(なぜ test-user にしなかったのか.)

Setup awscli

Docker イメージをPUSHするのに awscli を使うのでインストールします

$ pip install awscli $ aws --version aws-cli/1.15.60 Python/3.7.0 Darwin/15.6.0 botocore/1.10.59

アクセス情報を設定します。

他の案件と混ざると困るので \--profile を使って名前空間的なものを区切ります。

$ aws configure --profile djample AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXX AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Default region name [None]: us-west-2 Default output format [None]:

これによって --profile djample を指定することで 今回登録した認証情報を使うことができるようになりました

リポジトリをクローンする

続いて、デプロイ対象のイメージを作成するためのサンプルプロジェクトを用意します。 GitHub - righ/djample: django sample projectdjango sample project. Contribute to righ/djample development by creating an account on GitHub.https://github.com/righ/djample

$ git clone https://github.com/righ/djample

とりあえず準備はここまでです。

なんか作業が行ったり来たりするのでどこまでを準備としていいのか迷いますが、 長すぎると萎えるのでこのくらいで。

ECR

Dockerリポジトリを作ろう

Docker イメージをPUSHするためのリポジトリを作成します。

  • app
  • nginx

リポジトリが作成できたら PUSH するためのイメージを作成します

イメージをビルドする

さて、一旦コンソールに戻ります

イメージをビルドするときに毎回、アップデートとかが動くと嫌なので ベースイメージを作ることにします。

$ docker build -t djample-base . Sending build context to Docker daemon 49.51MB Step 1/4 : FROM ubuntu:18.04 AS djample-base ---> 74f8760a2a8b Step 2/4 : RUN useradd www --create-home --shell /bin/bash ---> Using cache ---> 536f8417ec7c Step 3/4 : WORKDIR /home/www ---> Using cache ---> fc05ab643d75 Step 4/4 : RUN set -x; apt-get update -y && apt-get install -y cron && apt-get install -y python3.6 python3-pip python3.6-venv && apt-get install -y postgresql-client && apt-get install -y libpcre3 libpcre3-dev && /usr/bin/python3.6 -m venv venv/ && chown www:www -R venv/ ---> Using cache ---> b352cf8215de Successfully built b352cf8215de Successfully tagged djample-base:latest

続いて、上記のイメージをベースとしてサービスの動作に必要なイメージをビルドします。

それぞれの コンテナを作成するための Dockerfile は deployment/ に出力したので -f でそのなかの Dockerfile パスを指定します

  • app
  • nginx
  • $ docker build -t djample-app . -f deployment/app/Dockerfile Sending build context to Docker daemon 49.51MB Step 1/13 : FROM djample_base:latest ---> b352cf8215de Step 2/13 : ARG requirements="requirements/requirements.txt" ---> Using cache ---> afffa1452c17 Step 3/13 : ARG preprocess="echo start processing" ---> Using cache ---> 384ba1153e6a Step 4/13 : ARG project="djample" ---> Using cache ---> 9d5339019178 Step 5/13 : USER www ---> Using cache ---> 56bcc23886d3 Step 6/13 : RUN mkdir ${project} ---> Using cache ---> 74b1c103567f Step 7/13 : WORKDIR /home/www/${project} ---> Using cache ---> 95086a8bc327 Step 8/13 : ADD apps/ apps/ ---> 9d0bd7ad2939 Step 9/13 : ADD templates/ templates/ ---> 9e837f364578 Step 10/13 : ADD static/ static/ ---> 2e1a601ebd96 Step 11/13 : ADD requirements/ requirements/ ---> c2cb99f51868 Step 12/13 : RUN set -x && ../venv/bin/pip install -r ${requirements} ---> Running in 2a61a9c3b944 + ../venv/bin/pip install -r requirements/requirements.txt Collecting Django==2.0.7 (from -r requirements/run.txt (line 2)) Collecting six==1.11.0 (from -r requirements/run.txt (line 3)) Collecting psycopg2==2.7.5 (from -r requirements/run.txt (line 4)) Collecting psycopg2-binary==2.7.5 (from -r requirements/run.txt (line 5)) Collecting pytz==2018.5 (from -r requirements/run.txt (line 6)) Collecting Jinja2==2.10 (from -r requirements/run.txt (line 7)) Collecting djangorestframework==3.8.2 (from -r requirements/run.txt (line 8)) Collecting uWSGI==2.0.17.1 (from -r requirements/run.txt (line 9)) Collecting MarkupSafe>=0.23 (from Jinja2==2.10->-r requirements/run.txt (line 7)) Downloading https://files.pythonhosted.org/packages/08/04/f2191b50fb7f0712f03f064b71d8b4605190f2178ba02e975a87f7b89a0d/MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl Installing collected packages: pytz, Django, six, psycopg2, psycopg2-binary, MarkupSafe, Jinja2, djangorestframework, uWSGI Successfully installed Django-2.0.7 Jinja2-2.10 MarkupSafe-1.1.0 djangorestframework-3.8.2 psycopg2-2.7.5 psycopg2-binary-2.7.5 pytz-2018.5 six-1.11.0 uWSGI-2.0.17.1 Removing intermediate container 2a61a9c3b944 ---> e7890ce4a544 Step 13/13 : CMD ${preprocess} && ../venv/bin/uwsgi --ini apps/uwsgi.ini ---> Running in eb439b9be16b Removing intermediate container eb439b9be16b ---> 468b3fc446c6 Successfully built 468b3fc446c6 Successfully tagged djample_app:latest
  • $ docker build -t djample-nginx . -f deployment/nginx/Dockerfile Sending build context to Docker daemon 49.52MB Step 1/19 : FROM node:latest AS webpack ---> 52fe93b8eea7 Step 2/19 : ARG webpack_config="webpack/webpack.prod.js" ---> Using cache ---> f10c7a39da94 Step 3/19 : ADD frontend/ frontend/ ---> Using cache ---> e0791031a12a Step 4/19 : WORKDIR frontend/ ---> Using cache ---> c1cd1acb2433 Step 5/19 : RUN set -x && npm install && $(npm bin)/webpack --config ${webpack_config} ---> Using cache ---> ecde11b80e71 Step 6/19 : FROM djample_base AS app ---> b352cf8215de Step 7/19 : ARG requirements="requirements/requirements.txt" ---> Using cache ---> afffa1452c17 Step 8/19 : WORKDIR /home/www ---> Using cache ---> 02db9470d977 Step 9/19 : ADD apps/ apps/ ---> Using cache ---> 127af7a8471b Step 10/19 : ADD requirements/ requirements/ ---> Using cache ---> f96e2ee6b9a3 Step 11/19 : ADD static/ static/ ---> 6c851b25121b Step 12/19 : RUN set -x && venv/bin/pip install -r ${requirements} && venv/bin/python apps/manage.py collectstatic --noinput --settings=settings.base ---> Running in 31d48872a4f6 + venv/bin/pip install -r requirements/requirements.txt Collecting Django==2.0.7 (from -r requirements/run.txt (line 2)) Collecting six==1.11.0 (from -r requirements/run.txt (line 3)) Collecting psycopg2==2.7.5 (from -r requirements/run.txt (line 4)) Collecting psycopg2-binary==2.7.5 (from -r requirements/run.txt (line 5)) Collecting pytz==2018.5 (from -r requirements/run.txt (line 6)) Collecting Jinja2==2.10 (from -r requirements/run.txt (line 7)) Collecting djangorestframework==3.8.2 (from -r requirements/run.txt (line 8)) Collecting uWSGI==2.0.17.1 (from -r requirements/run.txt (line 9)) Collecting MarkupSafe>=0.23 (from Jinja2==2.10->-r requirements/run.txt (line 7)) Downloading https://files.pythonhosted.org/packages/08/04/f2191b50fb7f0712f03f064b71d8b4605190f2178ba02e975a87f7b89a0d/MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl Installing collected packages: pytz, Django, six, psycopg2, psycopg2-binary, MarkupSafe, Jinja2, djangorestframework, uWSGI Successfully installed Django-2.0.7 Jinja2-2.10 MarkupSafe-1.1.0 djangorestframework-3.8.2 psycopg2-2.7.5 psycopg2-binary-2.7.5 pytz-2018.5 six-1.11.0 uWSGI-2.0.17.1 + venv/bin/python apps/manage.py collectstatic --noinput --settings=settings.base Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/selector-icons.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/calendar-icons.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-calendar.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-deletelink.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-addlink.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/README.txt' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/LICENSE' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-yes.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-alert.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/inline-delete.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-clock.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-changelink.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/tooltag-add.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-unknown.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-no.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/search.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/icon-unknown-alt.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/tooltag-arrowright.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/sorting-icons.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/gis/move_vertex_off.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/img/gis/move_vertex_on.svg' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/fonts/LICENSE.txt' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/fonts/README.txt' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Regular-webfont.woff' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Bold-webfont.woff' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/fonts/Roboto-Light-webfont.woff' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/base.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/responsive_rtl.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/rtl.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/forms.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/responsive.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/widgets.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/login.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/autocomplete.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/fonts.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/changelists.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/dashboard.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/vendor/select2/LICENSE-SELECT2.md' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/vendor/select2/select2.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/css/vendor/select2/select2.min.css' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/core.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/SelectBox.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/popup_response.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/collapse.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/timeparse.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/collapse.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/inlines.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/actions.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/change_form.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/SelectFilter2.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/cancel.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/actions.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/jquery.init.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/prepopulate_init.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/autocomplete.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/calendar.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/prepopulate.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/urlify.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/prepopulate.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/jquery/LICENSE-JQUERY.txt' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/LICENSE-SELECT2.md' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/select2.full.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/select2.full.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/he.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ru.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ro.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/lv.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sv.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/vi.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fi.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/eu.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/da.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/nb.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/de.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-CN.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/id.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ca.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/it.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/gl.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-TW.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pl.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sk.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/az.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fr.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/es.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ja.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hr.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/mk.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hu.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/tr.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hi.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/nl.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/en.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/bg.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/et.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ar.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sr.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ms.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/el.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/th.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/cs.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fa.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sr-Cyrl.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/lt.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/km.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/is.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pt-BR.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pt.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ko.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/uk.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/vendor/xregexp/LICENSE-XREGEXP.txt' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js' Copying '/home/www/venv/lib/python3.6/site-packages/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/img/glyphicons-halflings-white.png' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/img/grid.png' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/img/glyphicons-halflings.png' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.svg' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.ttf' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.eot' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.ttf' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff2' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.eot' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.woff' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.svg' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/bootstrap.min.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/bootstrap-theme.min.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/prettify.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/font-awesome-4.0.3.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/default.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/css/bootstrap-tweaks.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/default.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/bootstrap.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/jquery-3.3.1.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/coreapi-0.1.1.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/prettify-min.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/csrf.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/js/ajax-form.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/img/grid.png' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/img/favicon.ico' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/css/highlight.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/css/jquery.json-view.min.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/css/base.css' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/js/jquery.json-view.min.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/js/highlight.pack.js' Copying '/home/www/venv/lib/python3.6/site-packages/rest_framework/static/rest_framework/docs/js/api.js' 151 static files copied to '/home/www/static', 2 unmodified. Removing intermediate container 31d48872a4f6 ---> 3926aa0a8826 Step 13/19 : FROM nginx:perl ---> 8cf54770ff0a Step 14/19 : ADD deployment/nginx/uwsgi_params /etc/nginx/uwsgi_params ---> 27023a82e194 Step 15/19 : ADD deployment/nginx/nginx.conf /etc/nginx/nginx.conf ---> 802c94a3f80f Step 16/19 : ADD deployment/nginx/conf.d/ /etc/nginx/conf.d/ ---> 6b984577c912 Step 17/19 : COPY --from=app /home/www/static/ /usr/share/nginx/static/ ---> 9f3f12e4d8b4 Step 18/19 : COPY --from=webpack frontend/assets/ /usr/share/nginx/static/assets/ ---> 097978bd29a3 Step 19/19 : CMD ["nginx", "-g", "daemon off;"] ---> Running in 0c0dd0cf6337 Removing intermediate container 0c0dd0cf6337 ---> 87edefa4dbbc Successfully built 87edefa4dbbc Successfully tagged djample_nginx:latest

イメージをPUSHする

プライベートなコンテナリポジトリを使う場合、docker クライアントで認証が必要になります。

今回は AWS ということもあり ECR を使うことにするので、 awscli から認証していきます。

とはいっても簡単で、 aws ecr のコマンドで 認証コマンドが出力されるので $() で囲んでそのまま実行してあげるだけです。

# profile とか リージョンは各自変えること $(aws --profile djample ecr get-login --no-include-email --region us-west-2) WARNING! Using --password via the CLI is insecure. Use --password-stdin. Login Succeeded

上記のように Login Succeeded とでれば認証成功です。

おめでとうございます。いやまだ続くけど。

info

少し経つと有効になります。多分 AdministratorAccess だと発生しません

  • djample-app
  • djample-nginx
  • $ docker tag djample-app:latest XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-app:latest $ docker push XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-app:latest The push refers to repository [XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-app] 6836c8c88b45: Pushed 615d45681fa6: Pushed 15b6883e063f: Pushed c5eee45b9f53: Pushed 8e771df6e17b: Pushed dab2c9255521: Pushed 016210a3d295: Pushed ef7a479213de: Pushed 374f3534200b: Pushed 8fec0692e6a1: Pushed 219d5a9f3bbe: Pushed 67b9b2a215ea: Pushed 956940650d5d: Pushed latest: digest: sha256:6e78416aee66fd997e9d3eacb15ee602a14dba76a72fcb0dbc100dcd39f4c6f8 size: 3031
  • $ docker tag djample-nginx:latest XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-nginx:latest $ docker push XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-nginx:latest The push refers to repository [XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/djample-nginx] f514a6aae98f: Pushed 82544808b996: Pushed 942f421fc8f4: Pushed 67f95e015a50: Pushed 3803fdb990e6: Pushed 5871f1dd9014: Pushed 4cc529071e3b: Pushed cdb3f9544e4c: Pushed latest: digest: sha256:8b467500656e208d712a8ae7cb25f13896cf81e207d891469e9848b8da6f7d93 size: 1987
info

さて、コンソールでの操作は以上です。

証明書

HTTPS でアクセスするために、証明書を発行します。

何故かメール認証を選択しても全然メールが来なかったので DNS で認証することにします。

DNS に CNAME で 認証情報を登録します。 先頭の _ は入力しなくてOKです。

認証が終わったようです

VPCを作る

今回は Create Default VPC で Default VPC を作成します.

Default VPC を作ると 3つのサブネットも自動的に作成され 3つのアベイラビリティゾーンに割り振られるようです。

info
  • 後述するロードバランサが 2つ以上のサブネットを必要とするので、自分でVPCを作る場合はサブネット分割をする必要があります。
  • CIDR とかよくわからない場合は (他のサービスに影響がないなら) デフォルトVPC を使えばよいです

Security group

AWSではアクセス制御に セキュリティグループを用います。

今回も作っていきましょう。

EC2 dashboard から 2つの Security group を作成します。

Web 用

Inbound で 80, 443 だけ許可します

DB 用

Web のセキュリティグループからのみアクセスできるようにします。

Inbound の設定で TCP5432 の通信を djample-web のセキュリティグループからのみ許可します

RDS instance

DBもイメージにしてよかったんですが、普通はホストも分けたいと思うので今回は RDS の PostgreSQL (最小スペック)にします。

ユーザ
  • djampleuser
パスワード
  • djamplepass
DB
  • djampledb

で PostgreSQL を 建てます。

VPC と セキュリティグループは先ほど作成したものをアタッチしましょう.

今回、エンドポイントは djample.civihq7xgpb5.us-west-2.rds.amazonaws.com で作成されました

info

ロードバランサーを作成する

Fargate に振り分けるためにロードバランサが必要なので作成しましょう。

EC2 dashboard から操作します。

Target Groups

後述する Load Balancer に設定するために Target group を先に作成します。

  • Target type は IP を設定
  • VPC は 先程作成したものと同じものを設定

その他はデフォルトで Create します。

Load Balancer

ロードバランサーを作成します。 選択するのは Application Load Balancer (通称:ALB) です。

今回は HTTPS での通信に対応するために Listeners に HTTPS を追加します

HTTPS に対応する場合 次のページで セキュリティの設定があります。

セキュリティグループには先ほど作成したグループを指定します。

ルーティングの設定では 先ほど作成した target-grouop を指定します。

Register Targes はスルーして、入力に問題がなければ作成してしまいましょう。

作成された Load balancer の URL をDNSにも登録します (このUIはスタードメインのものです)

info
  • Route53 を使っている場合はそちらで登録してください。

ECS

さて、ようやく パーツが揃いました。

ここからは ECS の設定です。

Task Definition (for web service)

ECS における処理の最小単位は Task です。

Web サービス用のタスクを作成します。

  • Task Role を指定
  • Requires compatibilities には FARGATE を作成
  • Task size は最小を指定

Container

使用するコンテナを指定

  • Container name には識別するためのコンテナ名を指定
  • Image には ECR に登録した リポジトリの URL を指定
    • DockerHubなど別のリポジトリに登録されている場合はそれを指定しても良い
  • コンテナが開放しているポート番号をポートマッピングに指定
  • 設定値などの環境変数を指定
djample-app
  • uwsgi が 3031 ポートで待ち受けているので 3031 をポートマッピングに指定
  • DjangoのDB接続情報を環境変数で渡すようにしたので、先程のRDSの情報を割り当てます。
  • 環境変数名は settings の変数名を __ で区切ったものにしました。
  • 詳細は settings/env.pyを参照
djample-nginx
  • ポートマッピングに 80 (HTTP) を指定
info
  • Task はバージョンで管理されており、変更する場合は新たなリビジョンを追加することで対応します
    • 後述するサービスに指定するときもリビジョン番号まで含めて指定する
  • Task Role がない場合、 IAM Console から ecsTaskExecutionRole を作成
    • ロールのポリシーが足りないと CannotPullECRContainerErrorCannotStartContainerError が発生します
    • 今回は AdministratorAccess をアタッチしました

Cluster

今回は Fargate を選択します

クラスタ名を指定し、 VPC は先程のものを使うので作成しません。

Service

クラスタの中に サービスを作成します

  • Task Definition には先ほど作成した djample-web を指定します。
    • タスク定義は新たなリビジョンを作って変更するため、リビジョン番号まで含めて指定する
    • (いろいろ試行錯誤したため revision が進んでます)
  • サービス名は web にしました
  • デプロイタイプはローリングアップデートにします

ネットワーク設定には VPC と セキュリティグループには先ほど作成したグループを指定します。 先程作成したものを指定します。

Load balancing には application Load Balancer を選択し、 先ほど作成した djample-alb を指定します。

コンテナ名:ポートnginx:80:80 を指定し Add to load balancer ボタンをクリックすると 設定画面が開くので リスナーポートとターゲットグループ名を指定します

  • その他は デフォルトで次のページへ
  • オートスケーリングは今回指定せずに次へ
  • 確認して問題なければそのまま作成

クラスタに割り当てたURLにアクセスしてみると

見れました!

では Django admin にログインしようとすると

500 エラーが出ました。

これはテーブルがないからですね

info
  • ここで 503 が出る場合、ロードバランサーの設定がおかしいです。 多分target group とかかな?
  • 当該ドメインは削除済みなのでアクセスできません。

migration task

DBを初期化するためのマイグレーション用のタスクを作ります。

web サービス用のタスクと環境変数が共通しているので使いまわして作ることにします。

djample-web を選択して Create new revision で開いて、タスク名を変更します。 今回は djample-migration にします。ほかは変えない

Container 定義に移動して次のように操作します。ほかは変えない。

  • djample-nginx はこのタスクでは不要なので消します (消さなくても動くけど意味ない)
  • djample-app コンテナを開いてコンテナで実行するコマンドを指定します。
    • ENVIRONMENT(環境)セクションに移動して、マイグレーションコマンドを指定します
    • ../venv/bin/python3,apps/manage.py,migrate,--settings=settings.env
      • 区切り文字は スペースではなく , (カンマ) なので注意

Action から Run Task を選択

info
  • いろいろ設定してますが、セキュリティグループは djample-web だけで良かったと思います
    • デフォルトで新規作成になっているので、既存のセキュリティグループから選択しましょう。
  • subnet は多分一つで十分です

実行がおわりました

もう一度適当にログインしてみましょう。

エラーが変わりました。DBには接続できているみたいですがレコードがないエラーですね。

無事アクセスできているようなのでこれで終わってもいいんですが、せっかくなんでログインまでしてみたいと思います。

createuser task

当該アプリでは createuser ってコマンドを用意してあるので、これをラップするタスクを使ってユーザを作成してみましょう。

migration タスクをコピーして名前を変更

あとは実行コマンドを変更します.

  • admin/admin の superuser を作ります
    • パスワードの指定がない場合は Joe (ユーザ名==パスワード)になります
    • --superuser を指定すると スーパーユーザになる
      • このとき 自動的にスタッフになる
    • ' (シングルクォート) は引用符ではなくそのままユーザ名に採用されてしまうので注意

先ほどと同じように実行します。終わったようです。

ログインしてみます

できましたーーーーーーー

終わりっ

参考

How to Deploy Docker Containers | AWShttps://aws.amazon.com/getting-started/hands-on/deploy-docker-containers/ ECS+ECR環境でDockerコンテナをデプロイする - Qiita#前置きDockerで開発環境が動作するようになったはいいけれど、これだけではまだ道半ば。開発で使用したDockerイメージがそのまんま本番環境にデプロイされるところまでいってなんぼでしょう。…https://qiita.com/furu8ma/items/6dcf596ee67780e8807f

他にも参考にしたサイトがあったと思うんだけど、リンクを取っておくの忘れました;; ごめんなさい