エンジニアを目指す日常ブログ

日々勉強したことのメモ。独学ですので間違っていたらコメント等で教えてください。

ECS(Fargate)でコンテナを起動する方法メモ(基礎編:nginxアプリ)

はじめに

今回の記事の目的

ECS(Fargate)を使ってdockerコンテナを立ち上げ、Webアプリを起動する。 dockerイメージの管理にはECRを利用する。

dockerイメージ自体は、前回の記事(nginxのイメージを利用してローカル環境でコンテナを立ち上げた)で作成済であるのでこちらを利用する。 tomiko0404.hatenablog.com

前提

  • AWSマネジメントコンソールにアクセスできること。
  • IAMユーザに対し、必要なAWSサービスの利用を許可するIAMロールが紐づいていること。
  • ローカル環境にdockerがインストールされていること。

こちらの手順でdockerをインストールした。ローカル環境としてEC2を利用しているが、Vagrant等のローカル環境でも可。 tomiko0404.hatenablog.com

  • ローカル環境にdockerイメージが作成されていること。

こちらの手順でdockerイメージを作成した。Dockerfileの記述も以下。今回はローカル環境としてEC2を利用しているが、Vagrant等のローカル環境でも可。 tomiko0404.hatenablog.com

環境

  • ローカル環境(開発環境):EC2(Linux)にsshログイン
  • dockerイメージ:nginx

ECRへのdockerイメージ保存方法メモ

aws CLIをインストール

公式ガイド(Getting started with the AWS CLI - AWS Command Line Interface)に従いaws CLIをインストールする。

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version

awsCLIの基本設定(aws configure設定)

公式ガイド( 設定の基本 - AWS Command Line Interface )に従ってaws CLIの認証情報を設定する。

IAM認証情報の設定

アクセスキー ID とシークレットアクセスキーを取得する。

AWSマネジメントコンソールのIAMコンソール→ユーザ→自分のIAMユーザ→「認証情報」タブ→「アクセスキーの作成」

アクセスキー ID とシークレットアクセスキーはメモorCSVダウンロードしておく。

awsCLIの基本設定

以下コマンドを実行すると「アクセスキーID」「シークレットアクセスキー」「リージョン」「出力形式」を対話型で設定可能。

$ aws config

リージョンはとりあえず東京でap-northeast-1、出力形式はjsonにした。

ECRにリポジトリ設定

以下の動画をベースに実施。この通りにやって失敗したところもあるのでその時実施したことも記載している。
【AWS 入門】ECS(Fargate)とECRで楽々コンテナからHelloWorldしよう! - YouTube]

マネジメントコンソールから「ECR」を検索してリポジトリ」ページ→「リポジトリの作成」。 今回は名前をhello-world-ecs-test(dockerイメージ名と同じ)として作成。

dockerイメージをECRにプッシュ

ECRはGitのようにdockerイメージを管理できる機能と思えば良いらしい。

プッシュコマンドを表示を押すとプッシュするためのコマンドが表示される。

クライアント認証

認証トークンを取得し、レジストリに対して Docker クライアントを認証します。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
参考:ここで発生したエラー(IAM権限問題)

こちらのエラーに5時間ほど悩まされる。

An error occurred (AccessDenied) ・・・

結果的に、IAMロールの設定で解消できた。 フルアクセスの権限がついていたので問題ないと思ったのだが、「MFA認証をしない限り何もできないようにするロール」もついており、それが悪さをしていたようで、そのロールの紐づけを外したら解決した。詳細は確認中。

参考:ここで発生したエラー(ファイルアクセス権限)

IAMロール問題解決の後、こちらのエラーが発生。

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/auth": dial unix /var/run/docker.sock: connect: permission denied

/var/run/docker.sockファイルに実行権限が無いことが問題のようなので、実行権限をつける。 この操作により、これまでsudoをつけていたdockerコマンド操作がsudo無しで実行可能になる。

$ sudo chmod 666 /var/run/docker.sock
参考:同じことをEC2ではなくvagrant上で実施したときのエラー

エラー内容

Error saving credentials: error storing credentials - err: exit status 1, out: `Cannot autolaunch D-Bus without X11 $DISPLAY`

何かの認証情報が保存できていない状況とのこと。

passgnupg2をインストールして解決。正直詳細が全然わかっていない。

$ sudo apt-get install pass gnupg2
$ gpg2 - gen-key
$ pass init $gpg_id

参考にしたサイト
How to fix the "Cannot autolaunch D-Bus without X11 $DISPLAY" error - Anto ./ Online

gnupg2は、公開鍵と秘密鍵を生成してくれるツールらしい。

gnupg2とpassについては以下サイト等が参考になりそうだが…
GnuPG2のインストールと各種コマンド
エンジニア向けパスワード管理ツールPassを紹介します - termina.io

dockerイメージの構築

dockerイメージの構築コマンドはスキップ。(既にイメージ作成しているため)

イメージにタグをつける

構築が完了したら、このリポジトリにイメージをプッシュできるように、イメージにタグを付けます。

$ docker tag hello-world-ecs-test:latest xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-ecs-test:latest

ここで

$ docker images

でイメージを見ると、同じイメージIDで、「REPOSITORY」の名前が異なるものが1行増えていることがわかる。

ECRにdockerイメージをプッシュ

以下のコマンドを実行して、新しく作成した AWS リポジトリにこのイメージをプッシュします。

docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-ecs-test:latest

ECRにイメージをプッシュできた。

ECRコンソール画面
ECRコンソール画面

ECSを利用したコンテナ立ち上げ

クラスター作成

ECSのマネジメントコンソールから クラスターの作成→ネットワーキングのみ

今回クラスタ名とNameタグは入れておく。詳細の設定は都度調べる必要がありそう。

タスク定義の作成

タスク定義とは、コンテナを立ち上げるときに実行する処理を書いておけるdocker-compose.ymlのイメージ。まずは「新しいタスク定義の作成」からタスク定義を作成する。

参考:【AWS】ECSのタスク定義とは何か?コンテナ要件を定めたタスク定義の作成方法。 - Qiita

  • FARGATEを選択
  • タスクロール:立ち上がるコンテナからほかのAWSサービスにアクセスする際は、タスクロールを設定して権限を付与する。
  • タスクの実行IAMロール:ECRにイメージをおいているので、アクセスする必要がある。 プラス、コンテナのログをCloud Watchに吐き出す権限をつける必要がある。「新しいロールの作成」にしておけばよい。
  • コンテナの定義追加:コンテナ名は適当に
  • コンテナの定義追加:イメージ:ここに、直接Dockerfileの中身を書いても良い。ECRを使う場合はイメージの URIを記載する。
  • コンテナ定義の追加:ポートマッピングは、80tcpを選択。ローカルでコンテナを立ち上げたときdocker runコマンドに-p 80:80をつけたが、この代わりとなるイメージ。

サービスの作成

実際にコンテナを立ち上げる。 「クラスター」からクラスターを選択し、「サービス」タブから「作成」をクリックする。

  • 起動タイプはFARGATE
  • タスク定義は先ほど作ったタスク定義
  • サービス名は適当に
  • タスクの数:実際に立ち上がるコンテナの数を設定できる。
  • セキュリティグループは、自動で作ってくれているので名前を変えておく。コンテナへのアクセス設定。
  • パブリックIPの自動割り当てはENABLEDにしておく。

タスクが立ち上がった

タスクが立ち上がった
タスクが立ち上がった

Webサイトにアクセスする

立ち上がったタスクのパブリックIPアドレスを確認して、

パブリックIPアドレス確認
パブリックIPアドレス確認

ブラウザでアクセスする。

Webサイトにアクセス
Webサイトにアクセス

コンテナの中には入れないらしい

FARGATEを使った場合、コンテナの中に入ることはできないらしい。

おわりに

ECSを使ってコンテナを立ち上げ、コンテナ上にWebサイトを構築することができた。 今回はnginxを利用した簡単なアプリをコンテナ上で起動したので、次回はコンテナにReactアプリを載せる。

tomiko0404.hatenablog.com

疑問点

  • 結局タスクのパブリックIPアドレスにアクセスしているが、ポートマッピングの先はどこに?
  • タスクが立ち上がるとIPアドレスが変わってしまう?対策は?ロードバランサ?