はじめに
ECS(Fargate)を使ってdockerコンテナを立ち上げ、コンテナ上でWebアプリを起動します。
dockerイメージの管理にはAmazon ECRを利用します。
前提
- AWSマネジメントコンソールにアクセスできること。
- IAMユーザに対し、必要なAWSサービスの利用を許可するIAMロールが紐づいていること。
- 開発環境にdockerがインストールされていること。
- 開発環境にdockerイメージが作成されていること。イメージ名は、
hello-world-docker-test
とする。
dockerインストール方法とイメージの作成方法については、以下の記事を参照してください。
EC2(Linux)上でdockerコンテナを起動してみる | エンジニアを目指す日常ブログaws CLIを使えるようにする
aws CLIをインストール
公式ガイドに従いaws CLIをインストールします。
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version
すでにインストールされている場合、
$ sudo ./aws/install
でエラーが出ることがあります。その場合は
$ sudo ./aws/install --update
を実行します。
awsCLIの基本設定(aws configure設定)
公式ガイドに従ってaws CLIの認証情報を設定します。
IAM認証情報の設定
アクセスキー ID とシークレットアクセスキーを取得します。
AWSマネジメントコンソールのIAMコンソール→ユーザ→自分のIAMユーザ→「認証情報」タブ→「アクセスキーの作成」
アクセスキー ID とシークレットアクセスキーは、メモまたはCSVダウンロードしておきます。
awsコマンドを実行しているサーバが、自分のサーバであることを証明するためのキーとなります。
IAM認証情報をサーバ側で設定
以下コマンドを実行し、取得した「アクセスキーID」「シークレットアクセスキー」「リージョン」「出力形式」を対話型で設定します。
$ aws configure
設定項目
- AWS Access Key ID
- AWS Secret Access Key
- Default region name
- Default output format
リージョンはap-northeast-1
、出力形式はjson
とします。
$ aws configure
AWS Access Key ID [None]: ★
AWS Secret Access Key [None]: ★
Default region name [None]: ap-northeast-1
Default output format [None]: json
ECRにdockerイメージをプッシュする
AWSのdockerイメージ管理サービスであるAmazon ECR(Amazon Elastic Container Registry)を利用します。
Gitのようにdockerイメージを管理できる機能と思えば良いらしいです。
リポジトリを作成
マネジメントコンソールから「ECS」を検索して「Elastic Container Service」を選択する。
左側のメニューから「リポジトリ」を選択します。
「リポジトリを作成」を選択します。
今回は名前をhello-world-ecs-test-2
で作成しました。
CLIでクライアント認証
クライアント認証
コンソール画面で、リポジトリを選択し、プッシュコマンドを表示を押すとプッシュするためのコマンドが表示されるため、指示に従います。
まずCLIからECRにログインします。
認証トークンを取得し、レジストリに対して Docker クライアントを認証します。
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [アカウント].dkr.ecr.ap-northeast-1.amazonaws.com
以下、発生したラーの記録が続きます。エラーが起きなかった場合は dockerイメージの構築へ。
参考:ECR認証で発生したエラー(IAM権限問題)
こちらのエラーに5時間ほど悩まされましたが、IAMロールの設定を変更することで解消しました。
An error occurred (AccessDenied) ・・・(省略)
参考:ECR認証で発生したエラー(ファイルアクセス権限)
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
参考:ECR認証で発生したエラー(config参照不備)
以下のエラーが発生しました。
Unable to locate credentials. You can configure credentials by running "aws configure".
Error: Cannot perform an interactive login from a non TTY device
これは本来、前の手順のアクセスキー設定ができていないときに発生するエラーです。
設定しているのになぜ出てしまったかというと、aws ecr get-login-password
コマンドにsudo
をつけてしまっていたことが原因でした。
ECRのコンソールで指定されている通りに、sudo
無しのコマンドを実行し解決しました。
参考:同じことをEC2ではなくVirtualBox上で実施したときのエラー
エラー内容
Error saving credentials: error storing credentials - err: exit status 1, out: `Cannot autolaunch D-Bus without X11 $DISPLAY`
何かの認証情報が保存できていない状況とのことでした。
pass
とgnupg2
をインストールして解決。詳細は不明です。
$ sudo apt-get install pass gnupg2
$ gpg2 - gen-key
$ pass init $gpg_id
gnupg2
は、公開鍵と秘密鍵を生成してくれるツールらしいです。
参考にしたサイト:
- How to fix the "Cannot autolaunch D-Bus without X11 $DISPLAY" error - Anto ./ Online gnupg2とpassについて
- GnuPG2のインストールと各種コマンド
dockerイメージの構築
dockerイメージを作成します。
$ docker build -t hello-world-ecs-test-2 .
Sending build context to Docker daemon 212.3MB
Step 1/2 : FROM nginx:latest
---> 51086ed63d8c
Step 2/2 : COPY ./src /usr/share/nginx/html
---> Using cache
---> e79af938e3b8
Successfully built e79af938e3b8
Successfully tagged hello-world-ecs-test-2:latest
dockerイメージの一覧を確認すると、以下のようになっていました。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world-docker-test latest e79af938e3b8 2 hours ago 142MB
hello-world-ecs-test-2 latest e79af938e3b8 2 hours ago 142MB
nginx latest 51086ed63d8c 3 days ago 142MB
上2つはIMAGE ID
が同じになっています。中身は同じイメージですが、別のリポジトリとしてイメージを作成できました。
hello-world-ecs-test-2
というリポジトリでdockerイメージを作成できている場合は、本手順は実行しなくてもOKです。
イメージにタグをつける
dockerイメージに「タグ」をつけます。
構築が完了したら、このリポジトリにイメージをプッシュできるように、イメージにタグを付けます。
docker tag
コマンドを利用します。ECRが提示してくれたコマンドをコピペでOKです。
$ docker tag hello-world-ecs-test-2:latest [アカウント名].dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-ecs-test-2:latest
ここでCLI上で、
$ docker images
でイメージを見ると、同じイメージIDで、「REPOSITORY」の名前が異なるものが1行増えていました。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world-docker-test latest e79af938e3b8 2 hours ago 142MB
hello-world-ecs-test-2 latest e79af938e3b8 2 hours ago 142MB
[アカウント名].dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-ecs-test-2 latest e79af938e3b8 2 hours ago 142MBnginx
ECRにdockerイメージをプッシュ
リポジトリにイメージをプッシュします。
$ docker push [アカウント名].dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-ecs-test-2:latest
ECSを利用したコンテナ立ち上げ
いよいよAmazon ECS(Amazon Elastic Container Service)でコンテナを立ち上げます。
クラスター作成
ECSのマネジメントコンソールからクラスターの作成→ネットワーキングのみを選択します。
クラスタ名とNameタグは入れておきます。
タスク定義の作成
タスク定義とは、コンテナを立ち上げるときに実行する処理を書いておくことができるものです。
docker-compose.yml
のイメージ。
まずは「新しいタスク定義の作成」からタスク定義を作成します。
- FARGATEを選択
- タスクロール:立ち上がるコンテナからほかのAWSサービスにAPIアクセスする際などは、タスクロールを設定して権限を付与する必要があります。今回は「なし」とします。
- ネットワークモードは
awsvpc
、オペレーティングシステムファミリーはLinux
としました。 - タスクの実行IAMロール:ECRにイメージをおいているので、ECRに対するアクセス権限が必要です。 また、コンテナのログをCloud Watchに吐き出す権限をつける必要があります。「新しいロールの作成」にしておきます。
- メモリ、CPUは最小(0.5GB・0.25vCPU)としました。
- コンテナの定義追加
- コンテナ名をつけます。
- イメージ:ここに、直接Dockerfileの中身を書いても良いです。ECRを使う場合はイメージの URIを記載します。今回はURIを記載します。
- ポートマッピングは、
80
:tcp
を選択します。「ホストコンテナインスタンス」のポート80に、フォワーディングする設定とのことです。
ECRのURIは、マネジメントコンソールから確認可能です。
サービスの作成
実際にコンテナを立ち上げます。
「クラスター」からクラスターを選択し、「サービス」タブから「作成」をクリックします。
- 起動タイプはFARGATE
- タスク定義は先ほど作ったタスク定義
- サービス名は適当に
- タスクの数:実際に立ち上がるコンテナの数を設定できます。今回は3とします。
- デプロイメント:主流はBlue/Greenですが、今回は簡単のためローリングアップデートとします。
- VPCとサブネットは、過去作ったものを利用します。サブネットは、パブリックサブネットのAZ-aとAZ-cでそれぞれ設定しておきます。
- セキュリティグループは、自動で作ってくれます。
- パブリックIPの自動割り当てはENABLEDにします。
- ロードバランサは、簡単のため無しにします。
タスクが立ち上がった
タスクが3つ立ち上がったのが確認できます。
Webサイトにアクセスする
立ち上がったタスクのパブリックIPアドレスを確認して、ブラウザでアクセスします。
IPアドレスだけ入れればポート80にアクセスすることができます。
コンテナの中には入れないらしい
FARGATEを使った場合、コンテナの中に入ることはできないらしいです。
おわりに
ECSを使ってコンテナを立ち上げ、コンテナ上にWebサイトを構築することができました。