今回は、AWSのECSをとりあえず使ってみたい!動かしてみたい!! という人に向けて「Hello World」する手順をまとめます。
なお、ECSには以下の2つのコンテナ起動パターンがあります。
- EC2上でコンテナを立ち上げるパターン
- FARGATEという仕組みを使ってフルマネージドで起動するパターン
今回紹介するのは、2つ目のFARGATEを使うパターン
です。
おそらく昨今の多くの現場ではECSを使用する時にはこちらを使うかと思います。
(確証はありません)
また、ECSを使用する際に自分で作成したDockerイメージを ECRというAWSが提供するイメージレジストリ(Docker hubみたいなもん)に置いておくと相性が良いので併せて紹介します。
ゴール
上記を踏まえて、本記事のゴールを改めて明確にしておくと以下の通りになります。
ECRにアップしたnginxのイメージをECSで起動して、ブラウザからアクセスし「Hello World」を表示する。
便宜上「Hello World」と記載しましたが、せっかくなので以下にしたいと思います。
「Hello world from ECS nginx!!!」
やる気出そうなので。
1. PCのローカルでDockerイメージを作成
まずは何はともあれ、Dockerイメージを作成するところから始めます。
適当な作業用フォルダを作成し、Dockerfileを作成しましょう。
mkdir ecs_test
cd ecs_test
code Dockerfile(VSCodeを使用している場合)
ecs_testという名前で作業用フォルダを用意していますが、ここはもちろん適当な名前でOKです。
また、「code Dockerfile」でファイルを作成しつつ、VSCodeを開くことができますが 他のエディタをお使いの場合は適宜変更ください。あくまで「Dockerfile」が作成できればOKです。
Dockerfile&index.html編集
まずはDockerfileを以下の内容で編集し、保存します。
FROM nginx:latest
COPY ./src /usr/share/nginx/html
ここでCOPYをしているのは、Hello Worldを表記したhtmlファイル郡です。 こちらも以下の通り作成します。
mkdir src
code src/index.html
index.htmlの内容は以下の通り、Hello Worldの文言を記載しただけの物です。
Hello world from ECS nginx!!!
イメージを作成し起動テスト
ここまでできたらDockerのイメージを作成し、ついでにローカルで起動のテストをします。
docker build . -t hello-world-from-ecs
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world-from-ecs latest fd0b37c50451 6 seconds ago 132MB
「docker build」コマンドに-tオプションでイメージの名前(hello-world-from-ecs)を指定しています。 「docker images」コマンドでイメージの作成が確認できればOK!!
起動テストとして、コンテナを立ち上げてみます。
コンテナが立ち上がったらブラウザからhttp://localhost:8080/にアクセスしてみましょう。
こんな感じでindex.htmlの内容が出れば完璧です! 要はこれと同じことをECSで行えば良いわけです。
2. ECRのリポジトリを作成し1で作ったイメージをアップ
次に先ほど作成したDockerイメージをECRのレジストリにアップします。
2-1. リポジトリ作成
AWSのマネジメントコンソールからECRの画面を開きます。
右上にある「使用方法」をクリックするとリポジトリ作成画面が表示されます。
ここのリポジトリ名は何でも良いのですがイメージ名と一致させておくと色々と都合が良いので、 hello-world-from-ecsを記入し、「リポジトリの作成」をクリックします。
2.2 イメージのアップ(Push)
リポジトリを作成したはいいものの、 このままでは空っぽなので先ほどローカルで作ったイメージをアップロードします。
作成したリポジトリを選択して、「プッシュコマンドの表示」をクリックします。
こんな感じでめちゃ丁寧な案内が出るので、これに従ってコマンドを叩くだけです。 ここではmacの手順を記載します。
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin AWSのアカウントID番号.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag hello-world-from-ecs:latest AWSのアカウントID番号.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest
docker push AWSのアカウントID番号.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest
1点注意点として、手順2の「docker build -t hello-world-from-ecs .」は記載していません。
理由としては、先ほどすでにローカルで作ったからです。
これでアップは完了したのですが、後ほどアップしたイメージのURIを使用します。 なので、予めここでどこかメモにコピーしとくとあとで楽です!!
ちなみに形式としては、
AWSアカウントのID.dkr.ecr.リージョン.amazonaws.com/イメージ名:タグ名
になってるかと思います。
3. ネットワーク周りの設定
次にECSを起動するためのネットワーク周りの設定をします。 AWSでは基本的にVPCとサブネットを作成し、その内側に各種サービスを起動する流れとなっております。
3-1. VPCの作成
サービスから「VPC」を検索し開きます。
VPCの画面が起動したら、左カラムの「VPC」をクリックします。
僕の図ではいくつかすでにVPCが作成されていますが、
まだ未作成の場合はここは何もないか、デフォルトの物しか表示されないかと思います。
(気にしなくて大丈夫です)
ここで「VPCの作成」をクリックして今回用に新しくVPCを用意しましょう!
以下のように設定しています。
対象 | 内容 |
---|---|
名前タグ | ecs-hello-world-test(テキトー) |
IPv4 CIDRブロック | 192.168.11.0/24(テキトー) |
IPv6 CIDRブロック | IPv6 CIDR ブロックなし |
テナンシー | デフォルト |
基本的に、名前とCIDRは適当(任意の物でOK)その他はデフォルトのままです。
こちらで「作成」をクリックします。
ちなみに、CIDRがいまいち分からん!!という方は動画で解説してますので良かったらみてくださいw
うまく作成ができていれば、以下のようにVPCのリストに追加されているはずです。
3-2. サブネットの作成
VPCができたら次にサブネットを追加します。
左カラムから「サブネット」をクリックし、「サブネットの作成」をクリックしてください。
VPCの時と同様に設定値を聞かれるので、以下の通りに設定します。
対象 | 内容 |
---|---|
名前タグ | public-ecs-hello-world-test-1a(テキトー) |
VPC | vpc-003c98145a2c9ee36(さっき作ったヤツ) |
アベイラビリティーゾーン | ap-northeast-1a(1aじゃなくても良い) |
VPC CIDR | 192.168.11.0/24(VPCの設定に紐づくのでこのまま) |
IPv4 CIDRブロック | 192.168.11.0/25(VPC内の半分を使用) |
名前タグは適当ですが、VPCの名前に「public」と「1a」を付け足してます。
これは今回はインターネット越しに通信するという意味の「public」
と
アベイラビリティーゾーンを「ap-northeast-1a」を使うという意味の「1a」
を付与した形になります。
多くの場合このように、通信要件とアベイラビリティゾーンを名前に含めておくと、 そのようなサブネットかということが名前から推測できるのでおすすめですが、あくまで名前なので究極何でも良いです。
これでサブネットもできました。
3-3. インターネットゲートウェイの作成とアタッチ
次にインターネット越しに通信できるように、「インターネットゲートウェイ」を作成しVPCにアタッチします。
左カラムから「インターネットゲートウェイ」をクリックし、「インターネットゲートウェイの作成」をクリックします。
これまでと同様に名前タグを設定し、作成をします。
対象 | 内容 |
---|---|
名前タグ | ecs-hello-world-test-igw(テキトー) |
タグ キー(Name) | ecs-hello-world-test-igw(勝手に入力される) |
例によって名前タグは適当ですが、インターネットゲートウェイを表すために末尾に「igw」を付与してます。
(Internet GateWayの略でigwね笑)
タグのキー(Name)はデフォルトで勝手に名前タグの値が入ると思うので、このままでOKです。
(変えても良いけどあんまメリットないです)
作成が完了したら、このインターネットゲートウェイをさっき作ったVPCにアタッチします。
こうすることで本来AWSの外に出ていけないVPC内のネットワークから外に出ることが可能
になります。
作成後の画面から、「アクション」をクリックし「VPCにアタッチ」をクリックしましょう。
使用可能なVPCから、先ほど作成したVPCを選択し「インターネットゲートウェイのアタッチ」をクリックしたら完璧です!
3-4. ルートテーブルの作成とアタッチ
最後にルートテーブルを作成し、3-2で作ったサブネットにアタッチします。
ルートテーブルを設定することで3-3で作ったインターネットゲートウェイに通信を向かうようにできます。
逆にインターネットゲートウェイをアタッチしただけでは、まだインターネットとの通信はできません。
左カラムから「ルートテーブル」を選択し、「ルートテーブルの作成」をクリックします。
以下の通り必要な値を入力し、「作成」をクリックします。
対象 | 内容 |
---|---|
名前タグ | ecs-hello-world-test-rt(テキトー) |
VPC | vpc-003c98145a2c9ee36(さっき作ったヤツ) |
タグ キー(Name) | ecs-hello-world-test-rt(テキトー) |
Route Tableの略でここでは末尾に「rt」を付与しています。
VPCは当然の如く先ほど作った物を指定し、 タグのNameにも名前タグと同様のものをつけておきましょう!
作成が完了したら、実際のルートの設定を行います。
作成されたルートテーブルを選択肢、画面下部の「ルート」タブをクリックします。 その後「ルートの編集」を押下します。
「ルートの追加」をクリックし、 以下の通り先ほど作成したインターネットゲートウェイに対するルーティングを設定してあげます。
対象 | 内容 |
---|---|
送信先 | 0.0.0.0/0(全てのIPアドレス) |
ターゲット | igw-0c0bb40339483c756(さっき作ったIGW) |
インターネットに向かう通信なので、送信先には「0.0.0.0/0」つまり全てのIPアドレスを指定します。
(インターネット上にあるアドレスは不特定多数で且つ不明なので全てのIPを対象にします)
ターゲットはさっき作ったインターネットゲートウェイでOK。「ルートの保存」をクリックします。
最後に、このルートテーブルを先ほど作ったサブネットに関連付けます。
(こうすることで、そのサブネットの中でルートテーブルが有効になります。)
ルートテーブルが選択されていることを確認し、「サブネットの関連付け」タブをクリック(「ルート」タブの隣)
「サブネットの関連付けの編集」を押下してください。
先ほど作成したサブネットを選択肢、「保存」をクリックします。 これでルーティングの完成です。
4. ECSからECRのイメージを元にコンテナサービスを起動
待ちに待ったECSによるコンテナの起動です! ここまできたらあと少し!Hello Worldはすぐそこです!!
まずは例によってサービスの検索から「ecs」と検索し「Elastic Container Service」を開きます。
初めてECSを使用する場合は以下のような画面が表示されると思いますので、 まずは試しに「今すぐ始める」をクリックしてみてください。
以下の通り、
初回のECS使用時にはAWS側がチュートリアル的な感じの手順を用意してくれています。
しかし、今回はこのチュートリアルは使用せず全て自分で作っていきます。 理由としては以下の2点です。
- 実際にECSを使用していく状況では、チュートリアルの手順ではなく自分で作っていくことになるから
- VPCとサブネットがチュートリアル用に自動で作られてしまい、前の手順で使用したものを設定できないから
4.1 クラスターの作成
まずはじめにクラスターを作成します。
クラスターとは、各コンテナサービスをまとめて管理できる箱のようなものです。 今回は1つのサービス(Hello-Worldするnginx)だけを作りますが、本来であればクラスターの中に複数のサービスを作成していきます。
左カラムから「クラスター」を選択し、「クラスターの作成」をクリックしてください。
クラスターテンプレートの選択画面が表示されます。
今回はFARGATEを使用するので、「ネットワーキングのみ(FARGATEを使用)」が選択されているのを確認し 「次のステップへ」をクリックしてください。
クラスターの設定を以下の通り行い、「作成」をクリックします。
対象 | 内容 |
---|---|
クラスター名 | ecs-hello-world-test-cluster(テキトー) |
ネットワーキング(VPCの作成) | チェック無し |
Tags キー(Name) | ecs-hello-world-test-cluster(テキトー) |
CloudWatch Container Insights | チェック無し |
起動ステータスが完了になれば作成OKです! そのまま「クラスターの表示」をクリックします。
4.2 タスク定義の作成
次にタスク定義の登録をします。 タスク定義について簡単に説明すると、コンテナをどのような設定で起動するか指定したものといったイメージです。
Docker-Composeを使用したことがある方はあのイメージを持ってもらえれば、大体同じです。 それにプラスでAWSで使うための設定が少し追加されてるって感じです。
左カラムから「タスク定義」をクリックしてください。
「新しいタスク定義の作成」をクリックして、今回用の物を追加します。
- ステップ1. 起動タイプの互換性の選択
起動タイプは前述の通りFARGATE
を選択し、「次のステップ」をクリックしてください。
- ステップ2. タスクとコンテナの定義の設定
対象 | 内容 |
---|---|
タスク定義名 | hello-world-from-ecs-task-definition(テキトー) |
タスクロール | なし |
ネットワークモード | awsvpc(これしか選べない) |
タスク実行IAMロール | 新しいロールの作成 |
タスクメモリ | 0.5GB(一番小さいの) |
タスクCPU | 0.25vCPU(一番小さいの) |
コンテナの定義 | 後述します |
サービス統合, プロキシ設定, ログルータの統合 | チェック無し |
ボリューム | 無し(そのまま) |
Tags キー(Name) | hello-world-from-ecs-task-definition(テキトー) |
上記の通り設定します。
コンテナの定義
については、「コンテナの追加」をクリックし以下の通り設定してください。
対象 | 内容 |
---|---|
コンテナ名 | hello-world-from-ecs-nginx(テキトー) |
イメージ | 670756759498.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest(ECRにアップしたやつ) |
プライベートレジストリの認証 | チェック無し |
メモリ制限 (MiB) | ソフト制限(128) |
ポートマッピング | コンテナポート:80 , プロトコル:tcp |
詳細コンテナ設定 | そのまま |
コンテナ名は例によって任意です。
イメージは、手順2で控えておいたECRのイメージのURIを指定します!(重要!)
プライベートレジストリの認証とメモリ制限は今回はデフォルト値のままにしています。
また、ポートマッピングは「80」にしておきましょう。
設定したら、「追加」をクリックすればOKです。 ポップアップが閉じるので、このまま「作成」をクリックし完了です。
ローカルでコンテナを立ち上げた時は、ポートのマッピングを「ホスト:8080, コンテナ:80」と設定しましたが、 FARGATEを使う時は同じポート番号しか基本的にマッピングできないので、ここでは80になります。
「タスク定義の表示」をクリックして確認してみましょう。
4-3. サービスの作成(タスクとクラスターの紐付け)
最後にサービスの作成を行います。 サービスとは常時このコンテナ(タスク)を起動しておくための設定です。(ECSの真骨頂です)
左カラムから再度「クラスター」を選択し、先ほど作成したクラスター名をクリックしてください。
「サービス」タブが開いていることを確認し、「作成」をクリックします。
- ステップ1. サービスの設定
対象 | 内容 |
---|---|
起動タイプ | FARGATE |
タスク定義(ファミリー) | hello-world-from-ecs-task-definition(さっき作ったやつ) |
タスク定義(リビジョン) | latestのもの(みなさんの環境では1のはず) |
プラットフォームのバージョン | LATEST |
クラスター | ecs-hello-world-test-cluster(さっき作ったやつ) |
サービス名 | ecs-hello-world-test(テキトー) |
サービスタイプ | REPLICA(FARGATEはこっちのみ) |
タスクの数 | 1(今回は1、実際には冗長化のため2以上の場合もあり) |
最小ヘルス率 | 100(デフォルト) |
最大率 | 200(デフォルト) |
デプロイメント, タスクの配置 | そのまま |
上記で設定ができたら「次のステップへ」をクリックします。
- ステップ2. ネットワーク構成
対象 | 内容 |
---|---|
クラスターVPC | vpc-003c98145a2c9ee36(さっき作ったヤツ) |
サブネット | subnet-0673c58ddb337327a(さっき作ったヤツ) |
セキュリティグループ | 今回はデフォルトのままでOK(理由は後述) |
パブリックIPの割当て | ENABLED |
ヘルスチェックの猶予期間, ロードバランシング, サービスの検出 | デフォルトのまま |
上記で設定し、「次のステップ」をクリックします。
セキュリティグループについて 今回デフォルトでOKな理由としては このまま新しくデフォルトで作成されるセキュリティグループを使用すれば、ポート80のみアクセス可能になるからです。 本来はもっと細かく制御したセキュリティグループをつけることがほとんどだと思います。
- ステップ3. Auto Scaling(オプション)
対象 | 内容 |
---|---|
Service Auto Scaling | サービスの必要数を直接調整しない |
これだけ、「次のステップ」をクリック。
- ステップ4. 確認
入力した値に問題がなければそのまま「サービスの作成」をクリックすれば完了です!
こちらもステータスが完了になることを確認したら、右下の「サービスの表示」をクリックし確認しましょう!
5. ブラウザからアクセスし確認!
長かったですが、あとはブラウザから確認するのみです!!
「サービスの表示」をすると以下のように「タスク」タブに1つタスクが追加されているはずです。
なのでこのタスクをクリックしてください。 以下のようにタスクの詳細な情報が確認できるはずです。
ここに書いてある「パブリックIP」
の値をコピーしてブラウザでアクセスしてみてください。
今回の僕の環境だと「54.199.96.208」
となっていますね。
このように、Dockerイメージを作った時のhtmlの内容が表示されれば成功!! お疲れ様でした!