スケーラブルなインフラを構築できる AWS を使って Web アプリケーションを公開したい人向けに、 Elastic Beanstalk を使った Web アプリのデプロイ方法を解説します。
今回は、Django のアプリケーションを対象にデプロイしていきます。
Elastic Beanstalk とは
端的に言うと、AWS がオススメするサーバインフラを簡単に構築できるのサービスです。
コマンドラインやマネジメントコンソールから、 サーバの設定を行うことができ、サーバ自体に ssh でログインしてミドルウェアの設定をすることも不要となります。(ssh でログインすることもできます)
ユーザは、Elastic Beanstalk の作法に従ってソースコードをアップロードするだけで、デプロイが可能です。似たようなサービスとしては、Heroku があります。
以下のような開発言語(プラットフォーム)に対応しています。
- Node.js
- PHP
- Python
- Ruby
- Tomcat (Java)
- IIS (.NET)
- Docker
参考
- https://aws.amazon.com/jp/elasticbeanstalk/
- https://dev.classmethod.jp/cloud/aws/cm-advent-calendar-2015-aws-re-entering-elasticbeanstalk/
ハンズオン環境環境の構築
ハンズオンでは Python 製の cli ツールを使うので、Python をインストールしておきます。
pip も使えるようにしましょう。
$ python -V
Python 3.6.1
$ pip -V
pip 9.0.1
AWS CLI のインストール
AWS の操作をコマンドラインから行えるように AWS CLI をインストールします。
$ pip install awscli --upgrade --user
インストールできているか確認します。
$ aws --version
aws-cli/1.16.60 Python/3.6.1 Darwin/18.2.0 botocore/1.12.50
AWS CLI のセットアップ
AWS の IAM の Users 画面を開き、Create New Users からユーザを作っていきます。
取得した Credential を AWS CLI に設定します。
$ aws configure
AWS Access Key ID [None]: "自分のAccess Key ID"
AWS Secret Access Key [None]: "自分のSecret Access Key"
Default region name [None]: ap-northeast-1
Default output format [None]: json
参考
- https://dev.classmethod.jp/cloud/aws-cli-credential-config/
- https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html
セットアップが完了すると ~/.aws/config
と ~/.aws/credentials
が作成されます。
Elastic Beanstalk コマンドラインインターフェイス(EB CLI)のインストール
Elastic Beanstalk 用の CLI があるので、インストールします。
$ pip install awsebcli --upgrade --user
インストールできているか確認します。
$ eb --version
EB CLI 3.14.6 (Python 3.6.1)
デプロイしてみよう
デプロイする Web アプリの確認
今回は、Python で実装された Web アプリケーションフレームワーク「Django」のサンプルアプリを AWS 上にデプロイしています。
まずは、サンプルアプリをローカル環境で動かしています。
$ git clone https://github.com/redimpulz/django-docker-example.git
$ cd django-docker-example
$ tree .
.
├── Dockerfile
├── README.md
├── composeexample
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── docker-compose.yaml
├── manage.py
└── requirements.txt
1 directory, 9 files
django アプリの起動
Docker で実行できるようにしているので、実行しています。
$ docker-compose up
http://localhost:8000/ にアクセスして確認します。

参考
とりあえずデプロイしてみる
さっそくですが、このサンプルアプリをデプロイしてみましょう。
eb init コマンドで EB CLI リポジトリを初期化します。
$ eb init -p python-3.6 django-tutorial
$ cat .elasticbeanstalk/config.yml
branch-defaults:
master:
environment: null
global:
application_name: django-tutorial
branch: null
default_ec2_keyname: null
default_platform: python-3.6
default_region: null
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: null
repository: null
sc: git
workspace_type: Application
キーペアの設定
環境を構築する前にサーバに ssh できるようにキーペアを事前に登録します。
自分の SSH 公開鍵をインポートするか、新たにキーペアを作成します。
参考
config.yml の設定を修正
default_region に「ap-northeast-1」を、default_ec2_keyname に作成したキーペア名を設定します。
$ cat .elasticbeanstalk/config.ymlせ
branch-defaults:
master:
environment: null
global:
application_name: django-tutorial
branch: null
default_ec2_keyname: "キーペア名"
default_platform: python-3.6
default_region: "ap-northeast-1"
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: null
repository: null
sc: git
workspace_type: Application
環境の構築
5 分くらい時間がかかります。
$ eb create django-env
Creating application version archive "app-9399-181122_173644".
Uploading django-tutorial/app-9399-181122_173644.zip to S3. This may take a while.
Upload Complete.
Environment details for: django-env
Application name: django-tutorial
Region: ap-northeast-1
Deployed Version: app-9399-181122_173644
Environment ID: e-qjhvepmjx5
Platform: arn:aws:elasticbeanstalk:ap-northeast-1::platform/Python 3.6 running on 64bit Amazon Linux/2.7.6
Tier: WebServer-Standard-1.0
CNAME: UNKNOWN
Updated: 2018-11-22 08:36:48.144000+00:00
Printing Status:
2018-11-22 08:36:47 INFO createEnvironment is starting.
...
2018-11-22 08:39:20 INFO Successfully launched environment: django-env
構築した環境のステータスを確認します。
$ eb status
Environment details for: django-env
Application name: django-tutorial
Region: ap-northeast-1
Deployed Version: app-9399-181122_173644
Environment ID: e-qjhvepmjx5
Platform: arn:aws:elasticbeanstalk:ap-northeast-1::platform/Python 3.6 running on 64bit Amazon Linux/2.7.6
Tier: WebServer-Standard-1.0
CNAME: django-env.pztawke5hi.ap-northeast-1.elasticbeanstalk.com
Updated: 2018-11-22 08:39:20.372000+00:00
Status: Ready
Health: Green
CNAME: django-env.pztawke5hi.ap-northeast-1.elasticbeanstalk.com
を composeexample/settings.py に追加します。
...
ALLOWED_HOSTS = ['django-env.pztawke5hi.ap-northeast-1.elasticbeanstalk.com']
変更を加えたファイルをgit add
します。
デフォルトで git との連携が有効なので、commit されたファイルのみがデプロイ対象になります。
オプションで git のステージン上グのファイルのデプロイも可能なので、今回はステージングに追加してデプロイを行っていきます 。
ちなみに、git との連携で開発・ステージング・本番環境を eb コマンドで切り分けて構築することも可能です。
参考
$ git add composeexample/settings.py
$ eb deploy --stage
Creating application version archive "app-9399-181122_180153-stage-181122_180153".
Uploading django-tutorial/app-9399-181122_180153-stage-181122_180153.zip to S3. This may take a while.
Upload Complete.
2018-11-22 09:01:55 INFO Environment update is starting.
2018-11-22 09:02:00 INFO Deploying new version to instance(s).
2018-11-22 09:02:25 INFO New application version was deployed to running EC2 instances.
2018-11-22 09:02:25 INFO Environment update completed successfully.
デプロイされたアプリが開きます。
$ eb open
管理(admin)サイトをデプロイする
Django の管理(admin)サイトをデプロイしてみます。
コンテナを立ち上げ、docker の中に入ります。
$ docker-compose up -d
Starting django-docker-example_db_1_64f5b30b685e ... done
Starting django-docker-example_web_1_77f7f1eda3dc ... done
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------
django-docker-example_db_1_64f5b30b685e docker-entrypoint.sh postgres Up 5432/tcp
django-docker-example_web_1_77f7f1eda3dc python3 manage.py runserve ... Up 0.0.0.0:8000->8000/tcp
$ docker exec -it django-docker-example_web_1_77f7f1eda3dc /bin/sh
マイグレーションを実行します。
# python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
スーパーユーザーを作成します。
# python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: me@mydomain.com
Password:
Password (again):
Superuser created successfully.
静的コンテンツを書き出して、デプロイに含めるようにします。
# python manage.py collectstatic
119 static files copied to '/code/static'.
上記の操作で変更を加えたファイルや新たに追加したファイルをgit add
します。
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: composeexample/settings.py
Untracked files:
(use "git add ..." to include in what will be committed)
db.sqlite3
static/
$ git add .
ステージングをデプロイします。
$ eb deploy --stage
Creating application version archive "app-9399-181122_180811-stage-181122_180811".
Uploading django-tutorial/app-9399-181122_180811-stage-181122_180811.zip to S3. This may take a while.
Upload Complete.
2018-11-22 09:08:13 INFO Environment update is starting.
2018-11-22 09:08:20 INFO Deploying new version to instance(s).
2018-11-22 09:08:44 INFO New application version was deployed to running EC2 instances.
2018-11-22 09:08:44 INFO Environment update completed successfully.
ssh でログインしてみる
構築した環境は Linux サーパなので、ssh で入ることもできます。
eb ssh
で入れます。 キーペアは~/.ssh/
以下に置く必要があるので注意してください。
$ eb ssh
INFO: Attempting to open port 22.
...
Warning: Permanently added '18.182.66.162' (ECDSA) to the list of known hosts.
_____ _ _ _ ____ _ _ _
| ____| | __ _ ___| |_(_) ___| __ ) ___ __ _ _ __ ___| |_ __ _| | | __
| _| | |/ _` / __| __| |/ __| _ \ / _ \/ _` | '_ \/ __| __/ _` | | |/ /
| |___| | (_| \__ \ |_| | (__| |_) | __/ (_| | | | \__ \ || (_| | | <
|_____|_|\__,_|___/\__|_|\___|____/ \___|\__,_|_| |_|___/\__\__,_|_|_|\_\
Amazon Linux AMI
This EC2 instance is managed by AWS Elastic Beanstalk. Changes made via SSH
WILL BE LOST if the instance is replaced by auto-scaling. For more information
on customizing your Elastic Beanstalk environment, see our documentation here:
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html
[ec2-user@ip-172-31-19-211 ~]$ exit
ssh でログインできました。
RDS の設定
ここまでは、データベースは Django 標準の SQlite3 を使ってきました。
本番運用では、MySQL や PostgreSQL などの RDBMS を使う方が良いので、データベースを切り替えてみます。
またデータベースは、アプリケーションサーバ上にインストールするのではなく、AWS のマネージドリレーショナルデータベースサービスである RDS(今回は、PostgreSQL) を使用してみます。
データベースを作成します。

composeexample/settings.py
を環境変数を読むように修正します。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['RDS_DB_NAME'],
'USER': os.environ['RDS_USERNAME'],
'PASSWORD': os.environ['RDS_PASSWORD'],
'HOST': os.environ['RDS_HOSTNAME'],
'PORT': os.environ['RDS_PORT'],
}
}
環境変数を設定します。

ステージングをデプロイします。
$ git add .
$ eb deploy --stage
SSH でログインします。
$ eb ssh
仮想環境を有効化し、マイグレーションを実行します。
[ec2-user@ip-172-31-19-211 ~]$ cd /opt/python/current/app
[ec2-user@ip-172-31-19-211 app]$ source /opt/python/run/venv/bin/activate
(venv) [ec2-user@ip-172-31-19-211 app]$ source /opt/python/current/env
(venv) [ec2-user@ip-172-31-19-211 app]$ python manage.py migrate
/opt/python/run/venv/local/lib64/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
""")
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
(venv) [ec2-user@ip-172-31-19-211 app]$ python manage.py createsuperuser
/opt/python/run/venv/local/lib64/python3.6/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
""")
Username (leave blank to use 'ec2-user'):
Email address: me@mydomain.com
Password:
Password (again):
Superuser created successfully.
デプロイされたアプリを開きます。
$ eb open

環境の削除
最後に、作成した環境を削除します。
$ eb terminate django-env
The environment "django-env" and all associated instances will be terminated.
To confirm, type the environment name: django-env
2018-11-22 08:46:36 INFO terminateEnvironment is starting.
...
2018-11-22 08:50:51 INFO terminateEnvironment completed successfully.
お疲れ様でした!