docker-compose.ymlを全自動でAWS ECSにデプロイ
概要
2020年7月にDocker社とAWSが協業を発表した。
DockerとAWSが協業 Docker DesktopとAmazon ECSが連係可能に - ITmedia NEWS
それから約半年後、ついにdockerコマンドでAWSに一発デプロイできるようになった
Docker ComposeとAmazon ECSの統合が一般提供に:CodeZine(コードジン)
ここでは、dockerコマンドを使ってfargateにデプロイする方法をメモする。dockerを使ってAWSにデプロイする、ということは数年前からできてたことで、それ自体は何も新鮮ではないのだが、ざっくりいうとAWSの設定を全く、ないしは極力せずにデプロイできるところが今回のアップデートの強みと言える。
- 今までのAmazon ECS CLIである「ecs-cli」コマンドは使わない
- AWS CloudFormationの設定不要
- Docker ECS Pluginもインストール不要
環境
今回はMacからデプロイしてみる。
$ docker -v
Docker version 20.10.0, build 7287ab3
用意するもの
- AWSのアカウント
Step1 Public Dockerイメージでデプロイ
まずは構成のシンプルな、Docker Hubのコンテナイメージを使ってデプロイしてみる。
単体で動作して、「動いている感」があるWordPressをデプロイしてみる。
docker-compose.ymlの準備
まずはローカルに以下のdocker-compose.ymlを作成
version: '3'
services:
db:
image: mysql:8.0
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=somewordpress
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
wordpress:
image: wordpress:latest
ports:
- 80:80
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress
volumes:
db_data:
この時点でローカルで docker-compose up
して http://localhost/ にアクセスするとWordPressをセットアップできるようになるはず。
Amazon ECS用のcontext作成
新しくdockerコマンドでcontextというものを設定できるようになった。これを使ってAWSにデプロイできるようにAWS用のコンテキストを作成する。
$ docker context create ecs myecs
AWSの認証にあたって、すでにaws-cli等でAWSのProfileを使うこともできる。
確認
$ docker context ls
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
myecs ecs credentials read from environment
作成したContextを使用する。今までの戻す場合は docker context use default
$ docker context use myecs
いざデプロイ docker-composeコマンドではないことに注意
# ハイフン不要
$ docker compose up
初期設定ではFargateの設定やLBの設定でなんかかんやで数分かかるので気長に待つ。
起動確認
$ docker compose ps
ID NAME REPLICAS PORTS
wordpress-docker-DbService-QlT5cdzCpSAw db 1/1
wordpress-docker-WordpressService-Z6O7p5za0nTI wordpress 1/1 xxxx.ap-northeast-1.elb.amazonaws.com:80->80/http
するとLBのエンドポイントが表示されるので、ブラウザで http://xxxx.ap-northeast-1.elb.amazonaws.com にアクセスすると晴れてWordPressが起動している。
ログ表示
$ docker compose logs
削除 Fargate、LBすべての設定も削除される。最強
$ docker compose down
Step2 自分のDockerイメージでデプロイ
ここまで既存のdocker-compose.ymlとdockerコマンドだけで完結できてしまっているのが凄い。
が、実際にはWordPressが一発で起動できても何も嬉しくない。結局は自分のコンテナをデプロイしたいのである。
Step2ではAWSにイメージをpushしてデプロイをしてみる。
事前準備
自分のDockerイメージをAWSのDocker RegistryであるECRにpushする必要がある。
以下のサイトを参考にECRにpushできるようにしておくこと。
AWS ECRにDockerイメージをPrivateにPushする - 動かざることバグの如し
push
自分のレポジトリを作成し、以下のようなdocker-compose-build.ymlを作成
version: '3'
services:
web:
image: xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hatena-blog-shibafu:latest
build:
context: .
dockerfile: docker/Dockerfile.production
docker context use default
でコンテキストを切り替えて、ビルド
docker-compose -f docker-compose-build.yml build
push
docker-compose -f docker-compose-build.yml push
ECSデプロイするためにコンテキスト切り替え docker context use myecs
以下のような docker-compose-production.yml 作成
version: '3'
services:
web:
image: xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hatena-blog-shibafu:latest
ports:
- 80:80
command: "bundle exec puma -p 80"
デプロイ
docker compose up -f docker-compose-production.yml
今回は自分のイメージとして、はてなブログの記事を投稿具合をGithub芝生で草生やすサイト(https://hatena.turai.work/)を使った。(zenn.dev版作るか
内部のコード説明は割愛するが、要はrubyで動いてポート80でアクセスできるWEBアプリである。Githubに構成ファイル含めてコードを公開している。
その他
以下色々あったのでメモ
公式ドキュメントはどこ
過渡期なのかググってもなかなか出てこない。。
https://docs.docker.com/engine/context/ecs-integration/
published port can't be set to a distinct value than container portエラー
fargateの仕様上なのか、コンテナとホスト側のポートは一致してなければならない。
例えば、
ports:
- 80:9292
とかにするエラーになる。
ローカルでテストさせろ
専用のContextが用意されている。以下のコマンドで作成
docker context create ecs --local-simulation ecslocal
ただ本番と必ずしもasisで動くわけでないので注意は必要。
詳細は公式ドキュメントの「local-simulation」の項目
なんかエラーになる
エラーメッセージは忘れたが、デプロイしたい対象のディレクトリにアンダーバー(_)が含まれているとデプロイできない
デプロイ先のリージョンを変更できない
先述したdockerコマンドとAWSの紐付け時に特定の条件になるとリージョンを変更できず必ずus-east-1になってしまうバグがあるらしい。
詳細は https://github.com/docker/compose-cli/issues/1056
自分の場合は
export AWS_ACCESS_KEY_ID=XXXX
export AWS_SECRET_ACCESS_KEY=XXXX
でキーを環境変数でセットして
「AWS environment variables」
を使用することで東京リージョンへデプロイ出来た。
既存のVPCへデプロイしたい
docker-compose.ymlの先頭に x-aws-vpc
を付与
x-aws-vpc: "vpc-114514"
services:
hoge:
image: nginx
ports:
- 80:80
オートスケールしたい
x-aws-autoscaling
を使う。
services:
hoge:
deploy:
x-aws-autoscaling:
min: 1
max: 3
Docker HubのPrivateレポジトリを使いたい
アクセストークンを使うとDocker Hubのイメージでもデプロイできる。
まずアクセストークンを生成する。Docker Hubの設定→Securty項目より発行
次に適当な場所で
$ cat dockerhub-credentials.json
{
"username":"amanekey",
"password":"xxxxxxxxxxxxxxxxxxxxx"
}
のようなJSONを作成
認証 pullpullは適当なので任意の名前に変更する
docker secret create pullpull dockerhub-credentials.json
すると 「arn:aws:secretsmanager:xxxxxxxxxxxx」となにかが表示されるので控えておく。
最後にデプロイしたいdocker-compose.ymlで
services:
app:
image: DockerHubID/privateimage
x-aws-pull_credentials: arn:aws:secretsmanager:xxxxxxxxxxxx
ports:
- 80:80
のように変更して docker compose up
でデプロイできる。
公式でいい感じの説明とかチュートリアルないの?
残念ながらチュートリアル記事はまだないっぽい。(2020年12月30日現在)が、Githubに上がっているドキュメントが例付きで、かなりわかりやすいと思う。
- compose-cli/ecs-compose-examples.md at main · docker/compose-cli
- compose-cli/ecs-compose-features.md at main · docker/compose-cli
正直まだ未熟な部分もあるけど、今までの「面倒」な点が確実に改善されているので、これから良くなりつつ普及していくんじゃないでしょうか(願望
Discussion
docker compose up
に-f
のオプションなくないですか?解決済みかもしれませんが…
記事内のコマンドの表記に少々誤りがあったようですね。
とすれば動くかと思います。
要は「docker compose up」に-fのオプションをつけるのではなく、「docker compose」に-fオプションをつける必要があったみたいです。