gokitで作成したアプリケーションをdocker-composeでデプロイする(AWS Fargate)
gokitで作成したアプリケーションをdocker-composeでデプロイする(AWS Fargate)
こんにちは!情報科学専門学校のモノづくりサークル、MakeITのkentyです!
今回は、
- gokitについて
- AWS Fargateを用いて簡単にAWS上にデプロイする方法
についてお話ししたいと思います!
(公式ドキュメントはこちら)
- gokit
- AWS Fargate
前提知識
今回の記事は、
- golangについて基本文法程度の知識
- Docker,Docker Composeに対する基礎的な知識
- AWSについて簡単なサービスの理解(IAM/ECS)
があれば大丈夫です!
簡単な解説
gokitとは?
Go言語でマイクロサービスを構築するためのツールキットです。
Go kitは、分散システムの開発に必要な一般的なパターン、設計原則、コンポーネントを提供し、マイクロサービスの構築を簡素化することができます。
ただ、今回はお試しで触ったということもあり、tutorialの一番最初でできる部分である、
について行います。AWS Fargateとは?
AWS Fargateは、Amazon Web Services(AWS)のコンテナオーケストレーションサービスであり、マネージドなコンテナ実行環境を提供します。Fargateを使用することで、コンテナを実行するためのインフラストラクチャの管理やセキュリティの設定をすべて自動で行ってくれます。
解説
今回は、自分が作成したこちらのリポジトリをもとに解説していきます。
各ファイルの解説
├── .air.toml // airの設定ファイル
├── Dockerfile.dev //開発環境用のdocker file. airによって自動リロード
├── Dockerfile.prod //本番環境用のdocker file. buildして実行
├── docker-compose.yml //開発環境用のcompose.yml volume,buildが指定してある
├── go.mod //いつもの
├── go.sum //いつもの
├── main.go //アプリケーション
├── .env //環境変数
└── production.yml // 開発環境用のcompose.yml ECRでのimageを指定
順を追って説明します。
main.go
今回のアプリケーションです。
内容そのものは、リクエストボディでもらった文字列を大文字にしたり、その文字数をカウントする、という簡素なものです。
他にも、gokit特有の物事(Endpoint,Middleware,Transportなど)があるのですが、それらについては自分がまだ完全に理解しきれていないというのと、すでに良い記事がありましたのでこちらをご紹介させてください。
Dockerfile.dev, Dockerfile.prod
それぞれ開発環境用、本番環境用のDockerfileです。
開発環境用では、airを使うことによってホットリロードを行っています。
本番環境ではホットリロードをする必要はなく、そもそもbuildしたものを実行すればよいのでこのような中身になっております。
docker-compose.yml, production.yml
どちらもほぼ最小といってよいと思います。
開発環境用のdocker-composeの方はvolumeを指定することによってマウントしています。
逆に、productionの方はECRに予めpushしたimageを使用しています。
こちらのアカウントIDはenvのほうで指定します。
.env
今回指定する必要があるのは、今後デプロイに使用するAWS IAMユーザーのアカウントIDのみです。
AWS_ACCOUNT_ID=XXXXXXXXXXX
デプロイしてみる
アカウント周り
まず、デプロイを行うためには以下2つのアカウントが必要です。
- Dockerアカウント
- AWSアカウント(IAMユーザー)
Dockerアカウントに関しては、Docker Hubよりユーザー登録を行ってください。
特に設定はいらず、ユーザー名とパスワードだけ覚えておいてください。
AWSアカウントに関してはIAMユーザーを作成し、以下の権限を与えてください。
今回、リージョンはap-southeast-1に作成します。
- AmazonEC2ContainerRegistryFullAccess
- AmazonECS_FullAccess
- AWSCloudFormationFullAccess
(過剰かもしれないです)
ECRにimageをpush
Dockerfile.prodを利用してimageをbuildし、それをECRへpushします。
まずは、以下コマンドを実行しimageをbuildします。
$ docker build -t {アカウントID}.dkr.ecr.ap-southeast-1.amazonaws.com/stringsvc -f Dockerfile.prod .
その後、以下コマンドを用いてECRのリポジトリを作成します。
$ aws ecr create-repository --repository-name stringsvc --region ap-southeast-1
これらが完了した場合、imageをpushします。
$ docker push {アカウントID}.dkr.ecr.ap-southeast-1.amazonaws.com/stringsvc
これで、上記URLからimageを利用することができます。
もし、これらのコマンドの過程でAWSやDockerへの認証へ失敗している、というようなことがある場合は、このあたりのページを参考にしてみてください。
Amazon ECS用のコンテキスト作成
先ほど作成したIAMユーザーの認証情報を用います。
$ docker context create ecs stringsvc
? Create a Docker context using: AWS secret and token credentials
Retrieve or create AWS Access Key and Secret on https://console.aws.amazon.com/iam/home?#security_credential
? AWS Access Key ID MYACCESSKEYID
? Enter AWS Secret Access Key *********
? Region ap-southeast-1
Successfully created ecs context "stringsvc"
実行後、docker context lsで作成したコンテキストがあることを確認し、
$ docker context use stringsvc
などでコンテキストを変更しましょう。
その後、docker compose upを行うだけでAWS上で自動的にデプロイされます。
これには数分から数十分かかることもあるため、気長に待ちましょう。
特に初回は20程度かかるようなこともあるかと思います。
$ docker compose -f production.yml up
WARNING services.scale: unsupported attribute
[+] Running 5/10
⠋ stringsvc CreateInProgress User Initiated 19.0s
⠿ DefaultNetwork CreateComplete 5.2s
⠋ LoadBalancer CreateInProgress Resource creation Initiated 16.0s
⠋ AppTCP8080TargetGroup CreateInProgress Resource creation Initiated 16.0s
⠿ LogGroup CreateComplete 1.2s
⠋ CloudMap CreateInProgress Resource creation Initiated 16.0s
⠋ AppTaskExecutionRole CreateInProgress Resource creation Initiated 16.0s
⠿ Cluster CreateComplete 5.2s
⠿ DefaultNetworkIngress CreateComplete 1.0s
⠿ Default8080Ingress CreateComplete
起動確認後、docker compose ps
を行うことによって、どのようなURL,portからアクセスできるか確認できます。
$ docker compose ps
NAME COMMAND SERVICE STATUS PORTS
task/stringsvc/62faa404da0d4f77a03511947730d396 "" app Running {hogehogehogehoge}.elb.us-east-1.amazonaws.com:8080:8080->8080/tcp
また、AWS コンソールなどでどのようなサービスを利用しているかを確認することができます。
ハマったポイント
ここからは、ハマったポイントについて触れていければと思います。
buildせずにそのままデプロイしようとした
docker-composeのままデプロイできるということで、buildとかもそのままできるのかな?と思っていましたができず、少し後になって、自作のimageを使うような場合はECRなどにpushする必要がある
ことに気づきました。このような、通常のdocker,docker-composeを扱う際との違いを明確に意識していなかったために起きた問題です。
volumeを使用しようとしていた
上記に加え、当初のproduction.ymlではvolumesを使ってgo run main.goを行おうとしており、これが原因でAWS CloudFormationのスタック作成に失敗していました。
volumeはファイルシステムにバインドするものなので、もし仮にvolumeを使いたい場合はAWS EFSなどを用いて、仮想的にマウントできるファイルストレージを使う必要があり、ローカルで行ういわゆる
~~~~~~
volumes:
- .:/app
~~~~~~
というようなことはできません。
とはいえ、今回はそもそも本番環境ではgoアプリケーションそのものをbuildしてしまえばvolumeを使う必要もなかったので、妙に複雑化することなく、原因さえ分かってしまえば解決しました。
最後に
今回はアプリケーションサーバー1台のみという質素なcompose.ymlでしたが、とはいえ想像以上に簡単にデプロイすることができました。
今後はフロントエンドやネットワーク構成なども含めて、手元で作ったアプリケーションを手軽に公開していきたいですね。
参考にさせていただいた記事
Discussion