やること
Cloud9でDockerイメージをビルドして
ECRにDockerイメージをpushして
ECSでDockerコンテナを起動する
参考リンク
- AWS Cloud9環境でdocker-composeをできるようにする
- 今から追いつくDocker講座!AWS ECSとFargateで目指せコンテナマスター!
- Capacity Providerとは?ECSの次世代スケーリング戦略を解説する
構成
今回つくる環境
- ECSは、クラスターをEC2(linux)で構成
- クラスターを構成するEC2はCloud9と同じVPCに配置
- クラスターを構成するEC2とCloud9は通信可
各IAMロールの概要
No | Name | 概要 |
---|---|---|
IAM-1 | ecsrole | Cloud9からECS,ECRにアクセス |
IAM-2 | ー | ← これ無いわ、間違えた |
IAM-3 | ー | クラスターとしてEC2が機能するためのアクセス権 今回はクラスター作成時に自動生成する |
IAM-4 | ecsTaskExecutionRole | Dockerコンテナのアクセス権 RDS接続許可、みたいな権限 |
- 用語説明
- ECR(Amazon Elastic Container Registry)
- Dockerコンテナレジストリ
- Dockerイメージの保存と取得
- マネージドサービス
- ECS(Amazon Elastic Container Service)
- コンテナオーケストレーションサービス
- マネージドサービス
- クラスターをFargateで構成するとクラスター部分の管理もAWSお任せにできる
やっていきます
1.Dockerイメージを作成する
ECSで起動するDockerコンテナのため、Dockerイメージを作成
1-1.準備(環境構築)
cloud9の作成の詳細は省略(デフォルトVPCに作成するだけ)。
cloud9には、Dockerがインストールされている。
ec2-user をdockerグループに配属させる。
$ sudo usermod -a -G docker ec2-user
Docker Composeをインストールする。
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
IAMロール作成し、Cloud9 のEC2インスタンスにアタッチする。
IAMロール名 ecsrole
(図のIAM-1
)に適用したポリシー
AmazonEC2ContainerRegistryFullAccess
AmazonECS_FullAccess
1-2.Dockerイメージをビルドする
cloud9上でDockerイメージをビルドする。ビルドイメージ名 volumedemo
$ mkdir docker
$ mkdir docker/volumes
$ touch docker/volumes/Dockerfile
$ nano docker/volumes/Dockerfile
# -> 編集内容は後に記載してある
$ touch docker/volumes/index.html
$ nano docker/volumes/index.html
# -> 編集内容は後に記載してある
FROM centos:latest
RUN yum install -y httpd
COPY ./index.html /var/www/html/index.html
VOLUME /var/www/html
EXPOSE 80 443
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
<html><head><title>test</title></head><body><h1>TEST</h1></body></html>
ビルドする
$ cd docker/volumes
$ docker build -t volumedemo ./
# -> Successfully tagged volumedemo:latest となれば成功
ビルドが成功し、Dockerイメージがつくれたか確認
docker images
# -> REPOSITORY名 `centos`, `volumedemo` の2つが追加されてれば成功
Dockerコンテナを起動
$ docker run --name volumedemo -d -p 8080:80 volumedemo:latest
$ docker container ls
# -> NAMES `volumedemo` の STATUS が `UP xxx` となれば成功
Webが開くか動作確認
$ curl http://localhost:8080/index.html
# -> `<html><head><title>test</title></head><body><h1>TEST</h1></body></html>`と出力されたら成功
1-3.ホスト側からDockerコンテナ内のファイル(html)を更新する
Dockerコンテナのマウントボリュームを確認
$ docker inspect {CONTAINER ID}
# -> 出力結果から Mounts の情報を確認
Mounts
の Source
がホストのパス
"Mounts": [
{
"Type": "volume",
"Name": "951214538382d48c336a02bcd34d5d61e2cb88654587ec45f14996a2cda43024",
"Source": "/var/lib/docker/volumes/a02b1214538382d48c336c45fcd34d5d61e2cb88654587e9514996a2cda43024/_data",
"Destination": "/var/www/html",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
ホスト側からindex.htmlを編集し、Webサイトが更新されたことを確認
sudo nano /var/lib/docker/volumes/a02b1214538382d48c336c45fcd34d5d61e2cb88654587e9514996a2cda43024/_data/index.html
[更新前] <html><head><title>test</title></head><body><h1>TEST</h1></body></html>
[更新後] <html><head><title>test</title></head><body><h1>TEST123456789</h1></body></html>
↑の手法はパス探し面倒(Cloud9はアクセス権も絡み更に面倒)
なのでホスト側の格納パスを指定してバインドマウントする
$ mkdir /home/ec2-user/environment/docker/bindmount
$ touch /home/ec2-user/environment/docker/bindmount/index.html
$ nano /home/ec2-user/environment/docker/bindmount/index.html
# 中身 <html><head><title>test</title></head><body><h1>TEST-ABCDEFG</h1></body></html>
$ docker container run --name bindmount1 -d -p 80:80 -v /home/ec2-user/environment/docker/bindmount:/var/www/html volumedemo:latest
動作確認
Webサイトにアクセスして <html><head><title>test</title></head><body><h1>TEST-ABCDEFG</h1></body></html>
となれば成功
次にホスト側で /home/ec2-user/environment/docker/bindmount/index.html を編集し、Webサイトにアクセスして更新されてたら成功
2.DockerイメージをECRにpushする
作成したDockerイメージにECRの規則に沿ったタグを付与しECRにpushする
ECRでリポジトリを作成する ( リポジトリ名前 blackriverrepo
) 他の設定はデフォルト値を使用
Cloud9からECSにアクセス
$ aws ecr get-login --no-include-email --region ap-northeast-1
# -> Dockerログインコマンドでてくる(長くてビビる)
取得したDockerログインコマンドをCloud9上のターミナルで実行し、login Succeeded
と表示でれば成功。
ECRで作成したリポジトリ blackriverrepo
を選択し、プッシュコマンドの通知
ボタンをクリックすると、基本コマンドでてくる ※ 手順1,2は実施済み
ECS上のリポジトリにイメージをプッシュするために、Dockerイメージにタグを付ける
$ docker tag volumedemo:latest xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo:latest
# タグが付いたか確認
$ docker image ls
ECRで作成したリポジトリ blackriverrepo
にDockerイメージをpushする
$ docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo:latest
ECR のリポジトリを確認し、イメージURI xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo:latest
があれば成功
# ECR のリポジトリはコマンドでも確認できる
$ aws ecr describe-repositories --region ap-northeast-1
# コマンドでリポジトリの内容確認もできる
$ aws ecr describe-repositories --region ap-northeast-1 --repository-name blackriverrepo
AWSコンソールで確認するとこんな感じ
(おまけ)ECRからCloud9にDockerイメージをpullできるか確認
# Cloud9からのDockerイメージを消す
$ docker rmi xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo
# Cloud9でpullしてECRからDcokerイメージ取得
$ docker pull xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo
# -> キャッシュに残ってる場合はすぐ取得できる
# -> docker images で xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo があれば成功
# pullしたイメージでDockerコンテナ起動してみる
# コンテナ起動
$ docker run --name blackriver -d -p 8080:80 xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/blackriverrepo:latest
# コンテナ確認
$ docker ps -ls
# Webサイト確認
$ curl http://localhost:8080/index.html
3.クラスターを作成する
ECSにクラスターを作成。今回はFargate使わずEC2(linux)にする
ECSでクラスターを作成する(今回は EC2(linux) で作る) ※cloud9と同じVPCにする
- クラスターの構成
- クラスター名:cluster01
- プロビジョニングモデル:オンデマンドインスタンス
- EC2インスタンスタイプ:t2.small
- インスタンス数:2
- EC2 Ami Id:Amazon Linux 2 AMI
- EBSストレージ:22
- キーペア:{既存のキーペア指定} <- コンテナに入るなら設定しておく
- VPCはcloud9と同じデフォルトVPC
- セキュリティグループ:
新しいセキュリティグループ
- コンテナインスタンスIAMロール:
新しいロールの作成
- Tags:
Name
,ECSInstance01
設定時の画面 *クリックで拡大
作成がはじまる
ECSインスタンスが2つACTIVE
になると成功
4.(オプション)キャパシティープロバイダーを設定する
キャパシティープロバイダーは設定しなくてもDockerコンテナを起動できる
なので、この章(4章) はやらなくてもよい。(←これに気が付かず苦労した)
キャパシティープロバイダーとは、ECSに作ったクラスターに対する設定
前提として、ECSに紐づくAutoScalling側でスケールイン保護が必要
4-1.AutoScalling スケールインから保護
ECSに紐づくAutoScallingを編集
インスタンス保護を設定
キャパシティの最小値は 0
になっているが 1 以上にすることをオススメ
0
だと、EC2インスタンスが0になる可能性がある
EC2インスタンスが0の状態で、ECSでタスク実行すると『キャパシティーが無い』旨のメッセージがでる ※本記事のトラブルシュート参照
4-2.AutoScalling スケールイン保護の設定
所属するEC2インスタンスを選択し、スケールイン保護の設定
を設定する
4-3.ECS のクラスター clustre01
にキャパシティー作成
5.タスク定義を作成->実行する
タスク定義を作り実行すれば、Dockerコンテナが起動する。
- タスク定義とは?を粗く理解
- json形式
- コンテナ起動の設計書
5-1.タスク定義を作成
起動タイプ EC2 を選択
コンテナ追加
コンテナ名
, リポジトリのURI
, ポートマッピング
を設定
こんな感じで登録される
作成する
5-2.タスク定義を実行
4.(オプション)キャパシティープロバイダーを設定する
を実施していない場合は、このような画面になる。赤枠のメッセージは、4
を実施していないため、その下の起動タイプへ切り替える
をクリックし、(今回であれば)EC2を選択すればよい。
※おまけ※ 4.(オプション)キャパシティープロバイダーを設定する
を実施した場合は、このように赤枠のメッセージが出ない。
5-3.動作確認
Webサイトが開けば成功。
※ Cloud9(Webサイトにアクセスする環境)とクラスターに所属するEC2インスタンスが通信できるようSG(セキュリティグループ)を設定する。
Dockerコンテナが起動しているEC2インスタンスのローカルIPを確認するとアクセスするURLがわかる。
$ curl http://{Dockerコンテナが起動しているEC2インスタンスのローカルIP}/index.html
# -> 以下のような結果になれば成功
# <html><head><title>test</title></head><body><h1>TEST</h1></body></html>
今回はこれでおわり
トラブルシュート
タスク実行したときにキャパシティープロバイダー戦略のエラー発生
↓赤枠のメッセージ↓
キャパシティープロバイダー戦略
クラスターのデフォルト戦略
指定されたクラスターのデフォルトのキャパシティープロバイダー戦略にキャパシティープロバイダーが含まれていません。デフォルトのキャパシティープロバイダー戦略を更新して、1 つ以上のキャパシティープロバイダーを関連付けてから、もう一度お試しください。
- <考えられる原因>
- (1) ECSに作成したクラスターにキャパシティープロバイダーの設定がない
- (2) キャパシティープロバイダーに設定したAuto Scalling に
スケールイン保護の設定
されたEC2インスタンスがない
- <考えられる対策>
- (1)の対策案-1:本記事【4.(オプション)キャパシティープロバイダーを設定する】を実施しキャパシティープロバイダーを設定する
- (1)の対策案-2:
キャパシティープロバイダー
を使わない。起動タイプへ切り替える
をクリックする。本記事【5-2.タスク定義を実行】参照 - (2)の対策案:本記事【4-1.AutoScalling スケールインから保護】を参照し、Auto Scalling に最低1つ
スケールイン保護の設定
されたEC2インスタンスが含まれるようにする。