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

この記事は BeProud Advent Calendar 2018 の 13日目の記事です

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

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

備考

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

Preparation (準備)

Creates credential (認証情報)

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

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

iam.png

(なぜ 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 を指定することで 今回登録した認証情報を使うことができるようになりました

Clone an application repository

続いて、デプロイ対象のイメージを作成するためのサンプルプロジェクトを用意します。

当該記事では私が作成した Django のサンプルプロジェクトを使います

https://github.com/righ/djample

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

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

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

ECR

Creates Docker Repository

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

app nginx
create-registry-app.png create-registry-nginx.png

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

Builds images

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

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

$ 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

Pushes Docker images

$(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

備考

An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: arn:aws:iam::XXXXXXXXXXXX:user/test-djample is not authorized to perform: ecr:GetAuthorizationToken on resource: * と出る場合、 AmazonEC2ContainerServiceforEC2Role が足りていないので追加する

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

djample-app djamplenginx
$ 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

備考

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

Security certificate

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

add-domain-names.png

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

domain-validation-method.png

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

dns-validation-confirm.png

認証が終わったようです

domain-issued.png

Creates a VPC

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

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

vpc-availability-zones.png

備考

後述するロードバランサが 2つ以上のサブネットを必要とするので、自分でVPCを作る場合はサブネット分割をする必要があります。

CIDR とかよくわからない場合は (他のサービスに影響がないなら) デフォルトVPC を使えばよいです

Create a security group

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

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

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

Web 用

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

security-group-web.png

DB 用

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

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

security-group-db.png

Creates RDS instance

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

ユーザ:

djampleuser

パスワード:

djamplepass

DB:

djampledb

で PostgreSQL を 建てます。

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

rds-network-security.png

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

備考

  • パブリックアクセシビリティを有効にしないとアドレスが発行されません

  • The VPC vpc-XXXXXXX associated with the default subnet group does not exist. Please delete the default subnet group or specify another subnet group. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidVPCNetworkStateFault; Request ID: 3a0fea9b-9262-49fa-b194-464b4475079b) のように言われる場合、 RDS のメニューから Subnet groups を開き、該当するサブネットグループを削除するとうまくいくようです。罠だろこれ。

    あなたが神か

    I know it's closed, but to help someone searching on google, I've deleted a vpc and created a new default vpc and I got this problem, to solve this, I go to Amazon RDS > Subnet groups > and I deleted the subnet group, and worked

    https://github.com/terraform-providers/terraform-provider-aws/issues/4318#issuecomment-406126072

Creates a load balancer

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

EC2 dashboard から操作します。

Target Groups

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

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

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

create-target-group.png

Load Balancer

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

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

alb1.png

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

alb2.png

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

alb3.png

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

alb4.png

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

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

ecs-service7.png

備考

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

ECS

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

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

Task Definition (for web service)

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

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

  • Task Role を指定
  • Requires compatibilities には FARGATE を作成
  • Task size は最小を指定
ecs-task1.png

Container

使用するコンテナを指定

  • Container name には識別するためのコンテナ名を指定
  • Image には ECR に登録した リポジトリの URL を指定
    • DockerHubなど別のリポジトリに登録されている場合はそれを指定しても良い
  • コンテナが開放しているポート番号をポートマッピングに指定
  • 設定値などの環境変数を指定
djample-app

uwsgi が 3031 ポートで待ち受けているので 3031 をポートマッピングに指定

ecs-task-app1.png

DjangoのDB接続情報を環境変数で渡すようにしたので、先程のRDSの情報を割り当てます。

環境変数名は settings の変数名を __ で区切ったものにしました。

詳細は settings/env.py を参照

ecs-task-app3.png
djample-nginx

ポートマッピングに 80 (HTTP) を指定

ecs-task-nginx.png

備考

  • Task は バージョンで管理されており、変更する場合は新たなリビジョンを追加することで対応します
    • 後述するサービスに指定するときもリビジョン番号まで含めて指定する
  • Task Role がない場合、 IAM Console から ecsTaskExecutionRole を作成
    • ロールのポリシーが足りないと CannotPullECRContainerErrorCannotStartContainerError が発生します
    • 今回は AdministratorAccess をアタッチしました

Cluster

今回は Fargate を選択します

ecs-cluster1.png

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

ecs-cluster2.png

Service

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

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

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

ecs-service2.png

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

ecs-service3.png

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

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

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

djample-view.png

見れました!

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

error500.png

500 エラーが出ました。

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

備考

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

migration task

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

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

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

migration1.png

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

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

Action から Run Task を選択

migration-run-config.png

備考

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

実行がおわりました

migration-done.png

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

login-error.png

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

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

createuser task

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

$ ./manage.py createuser --help --settings=settings.base
usage: manage.py createuser [-h] --username USERNAME [--password PASSWORD]
                            [--email EMAIL] [--first-name FIRST_NAME]
                            [--last-name LAST_NAME] [--is-superuser]
                            [--is-staff] [--is-not-active] [--version]
                            [-v {0,1,2,3}] [--settings SETTINGS]
                            [--pythonpath PYTHONPATH] [--traceback]
                            [--no-color]

optional arguments:
  -h, --help            show this help message and exit
  --username USERNAME
  --password PASSWORD
  --email EMAIL
  --first-name FIRST_NAME
  --last-name LAST_NAME
  --is-superuser
  --is-staff
  --is-not-active

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

createuser-taskdefinition1.png

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

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

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

createuser-finished.png

ログインしてみます

admin-index.png

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

終わりっ

参考

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