ゴールはec2のパブリックipにアクセス(ポート指定なしで)すると、Expressのサンプルアプリ(Welcome to Express)が表示されることがゴールです。
Dockerでコンテナを作成して、実現していきます。
<作成手順>
1、EC2インスタンスの作成
2、EC2にDockerをインストール
3、ローカルでexpressアプリを作成
4、docker-compose.ymlを記述する
5、リバースプロキシを設定する
1、EC2インスタンスの作成
事前に公開鍵と秘密鍵は作成しておいてください。→参照
OSはAmazon Linux AMIを選択して、インスタンスタイプは無料枠のt2.microを選択します。
セキュリティグループの作成で、ポート番号にHTTP用の80とアプリケーション用の3000をルール追加しておきます。
インスタンスが作成できたら、公開鍵を使って
#~/.ssh/key-name.pemの部分は自分が作った公開鍵の場所を指定
$ ssh -i ~/.ssh/key-name.pem ec2-user@パブリックipアドレス
でインスタンスにログインします。
2、EC2にDockerをインストール
[ec2-user@ip-0-0-0-0 ~]$ sudo yum -y update
[ec2-user@ip-0-0-0-0 ~]$ sudo yum install -y docker
[ec2-user@ip-0-0-0-0 ~]$ sudo gpasswd -a $USER docker
[ec2-user@ip-0-0-0-0 ~]$ sudo service docker start
今回はdocker-composeコマンドでコンテナを作成するので、docker-composeコマンドもインストールします。
[ec2-user@ip-0-0-0-0 ~]$ sudo -i
[ec2-user@ip-0-0-0-0 ~]$ curl -L "https://github.com/docker/compose/releases/download/1.11.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[ec2-user@ip-0-0-0-0 ~]$ chmod +x /usr/local/bin/docker-compose
[ec2-user@ip-0-0-0-0 ~]$ exit
3、ローカルでexpressアプリを作成
以下の手順でローカル環境でexpressアプリを作成します。
#expressを使う準備
$ npm install -g express
$ npm install -g express-generator
#expressコマンドでアプリディレクトリを作成。テンプレートエンジンはお好みで
$ mkdir express && cd express
$ express --view=pug myapp
$ cd myapp && npm install
#nginx用の設定ディレクトリ、設定ファイルとdocker-compose.ymlを作成
$ mkdir conf.d && touch conf.d/default.conf && touch docker-compose.yml
ここまでで実行するとディレクトリ構造は以下のような感じに
4、docker-compose.ymlを記述する
ウェブコンテナ(nginx)とアプリケーションコンテナ(node_express)を以下のように記述します。
ちなみに、volumesはコンテナ内のどの場所にディレクトリを配置するかを示しています。
version: '2'
services:
web:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
volumes:
- "./conf.d:/etc/nginx/conf.d"
links:
- app
app:
image: node:8.9.3-alpine
container_name: node_express
volumes:
- ".:/src"
working_dir: /src
command: [sh, -c, npm install && npm start]
#コンテナのポート3000をホストのポート3000で公開する
ports:
- "3000:3000"
5、リバースプロキシを設定する
この状態では、パブリックipにポート3000を指定すれば、expressのウェルカムページが表示されます。
ポート3000を指定してなくてもパブリックipだけ打てば、expressのウェルカムページが表示されるように、nginxの設定ファイルmyapp/conf.d/default.confを以下のようにします。
server {
listen 80;
charset utf-8;
access_log /var/log/nginx/default.access.log main;
error_log /var/log/nginx/default.error.log;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
#コンテナをプロキシにする際はコンテナ名:ポート番号を設定することで解決
proxy_pass http://app:3000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
アプリを動かすときがきた
ここまで作成できたら、実際にローカルで作成したディレクトリをEC2のtmp配下に転送してEC2でコンテナを起動します!
*転送の部分は、Gitで管理してCodeBuildを使って自動化するとより今どきなのかもしれません。
#ローカルから作成したexpressディレクトリをEC2へ転送
$ rsync -e "ssh -i ~/.ssh/key-name.pem" -r express --exclude=/node_modules ec2-user@パブリックipアドレス:/tmp
#EC2内のdocker-compose.ymlがあるところまで移動して、実行
$ ssh -i ~/.ssh/key-name.pem ec2-user@パブリックipアドレス
[ec2-user@ip-0-0-0-0 ~] $ cd /tmp/express/myapp
[ec2-user@ip-0-0-0-0 ~] $ docker-compose up -d
nginxとnode_expressの2つのコンテナが実行され、ブラウザでパブリックipアドレスを打ち込めばサンプルアプリが表示されます。
Amazon ECSを使えばもっといい環境になるのかも...
コンテナのデプロイについてAWSではAmazon ECSを利用することを推奨しています。Amazon ECS環境ではEC2起動だけでなく、コンテナのアプリケーション構築に特化したAWS Fargateというエンジンで起動できるようです。Amazon ECSはコンテナのクラスター管理がしやすくなるので、コンテナの数が増えてきた場合には要検討かもしれません。もう少し勉強が必要そうです。
https://github.com/awslabs/ecs-refarch-continuous-deployment