スポンサーが1社付いてるのですぐに消えたりはしないはず。
メール送信数制限の都合で1日のユーザー登録数には上限がある。
メールが届かない時は暫く待つか24時間後に再送信。
とはいえ5万なので上限になることはないか。
環境
- AWS
- EC2 Container Service
- ecs-cli
- RDS(PostgreSQL)
- ElastiCache(Redis)
- S3
- CloudFront
- ALB
- SES
やれるだけやって分散した。
いくらでもサーバー増やせるけどたぶんそこまで必要にはならない。
最後SESのsandbox解除待ちで時間かかった…。
途中段階の役に立たないメモ
ローカルで動かすだけならVagrantのほうが早い。
最初から管理者アカウントも作られる。
docker-composeはproduction用。
git clone https://github.com/tootsuite/mastodon
cd mastodon
sudo curl -o /usr/local/bin/ecs-cli https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-darwin-amd64-latest
sudo chmod +x /usr/local/bin/ecs-cli
ecs-cli help
ecs-cli configure -p default --cluster mastodon
ecs-cli up ...
aws ecr get-login
docker login ...
aws ecr create-repository --repository-name mastodon
docker build -t mastodon .
docker tag mastodon:latest ...
docker push ...
docker-compose.ymlを編集
- buildの代わりにimage: mastodon
- DB永続化するためコメントを消す
ecs-cli compose service up
ここで上手く動かなくなった。
Elastic Beanstalkでやろうとしたけどこっちもだめ。
いろいろやってるうちにオリジナルのdocker-compose.ymlが事前に用意したDocker image使うようになってた。
ECS使う方法に戻る…。
assetsを削除して再生成してS3にアップ。
precompileを繰り返すとファイルが増える…?
rm -rf ./public/assets
docker-compose run --rm web rails assets:precompile
aws s3 cp ./public/assets s3://{S3バケット}/assets --recursive --acl public-read --cache-control "max-age=604800"
S3に置くと/public/assets以下がないのでprecompile済みファイルが使われない。
sprockets-manifestが必要。
S3に置くのはやめた。
image: gargron/mastodon
は使わず自分でビルドする方法に戻る…。
.dockerignoreを変更してimageにassetsも含まれるように。
#public/assets
docker-compose.ymlをコピーしてaws.ymlを作りこっちを書き換えて行く。
docker-compose.ymlはローカル用に元のまま。
あ、当然gitのブランチは分けてる。
AWSのECSでは
-
build
が使えない -
volumes
で相対パスが使えない
という仕様なのでそれに合わせる。
volumes
はよくわからないのでほぼ使わないように…。
ここからも色々苦労したけど細かすぎてもう忘れたのでメモ程度。
AWSのサービスで使えるものは使う。
db,redisはもちろん分離。
S3も当たり前に使う。
nginxは不要だった。nginx使おうとして無駄に混乱…。
ポートマッピングはELB。
httpsへのリダイレクトはCF。
LOCAL_HTTPS=false
でも問題なくhttpsで動くけどメール内のURLだけhttpになる。
リダイレクトされるので妥協。
ecs-cli compose serviceで--load-balancer-name
付きで起動だけどうしてもできなかったので諦めた。
/api/v1/streaming
はサブドメインにした。
STREAMING_API_BASE_URL
で指定すればそれが使われる。
LOCAL_HTTPS=false
だとwebsocketでエラー出てたので無理矢理な対応。
S3_BUCKET
とS3_HOSTNAME
はS3のドメインそのまま使う用で
自分のサブドメイン使う場合はS3_CLOUDFRONT_HOST
も設定する。
CF使ってるかに関係なく静的ホスティングなら。
nginx使わなくても動いてるけど何か問題あれば後で修正していく。
docker-compose.ymlあるから簡単に動かせるかと思ったけどそんなことはなかった。
EC2上でdocker-compose up
すれば簡単だけどそれじゃAWSの意味がない。
ALBの使用
その後調べて分かったので追記。
--load-balancer-name
はClassic Load Balancer用なので違う。
ALBは--target-group-arn
を使う。
ただしサービスごとに一つしか設定できないのでサービスを複数作るしかない?
ecs-cli compose -f aws.yml --project-name mastodon-web service create --target-group-arn {web用のターゲットグループ} --container-name web --container-port 3000 --role ecsServiceRole
ecs-cli compose -f aws.yml --project-name mastodon-api service create --target-group-arn {streaming用のターゲットグループ} --container-name streaming --container-port 4000 --role ecsServiceRole
--project-name
の指定も必要になった。
ecs-cli compose -f aws.yml --project-name mastodon-web service up
AutoScalingでEC2インスタンス数を増減。
一つのEC2内で複数のタスクが動くし、タスクもAutoScalingできるようになった。
サービスを分けるならaws.ymlも分割したほうがメモリの無駄もない。
最終版
ごちゃごちゃしたのでまとめ。
最終的にはすっきり。
aws-web.yml
mem_limitは分からないので仮。
portsは動的ポートのために。
"3000"か"0:3000"の書き方。
version: '2'
services:
web:
image: {自分のimage}
env_file: .env.production
command: bundle exec rails s -p 3000 -b '0.0.0.0'
mem_limit: 536870912
ports:
- "3000"
aws-api.yml
version: '2'
services:
streaming:
image: {自分のimage}
env_file: .env.production
command: npm run start
mem_limit: 268435456
ports:
- "4000"
sidekiq:
image: {自分のimage}
env_file: .env.production
command: bundle exec sidekiq -q default -q mailers -q pull -q push
mem_limit: 268435456
volumes:
- /var/app/system:/mastodon/public/system
sidekiqのvolumesはどこでもいいので指定しておく。
なにかファイルを書き込めないエラーが出ることがあった。
ALB
ターゲットグループ
- port3000のweb用
- port4000のstreaming用
を作る。
リスナーHTTPS 443
ヘルスチェックのポートをトラフィックポートにする。
- HostがAPI用のサブドメインならstreaming
- Pathが/ならweb
というルールを設定する。
CloudFrontはこのALBをOriginにする。
/assets
以下はキャッシュ強く。他は短めというかなしでいいくらい。
Route53はCloudFrontを指定。
上手く行かないときはCFを外してみる。
今後のためのアップデート手順
masterブランチを最新にしてからマージ。
DB_HOSTはRDSを指定してるのでdb:migrateはローカルから直接行う。
これはどうなんだろうとは思うけど他の方法が分からなかった。
docker-compose build
docker-compose run --rm web rails db:migrate
docker-compose run --rm web rails assets:precompile
docker imageの更新はECRの手順通りに。
aws ecr get-login --region ap-northeast-1 | bash
docker build ...
docker tag ...
docker push ...
後はup。upはymlが変更されてないと以前のタスクのままなのでimageだけ更新した場合は更新されない。
CIで動かしてdocker tagを設定してymlの書き換えまで自動化かな。
ecs-cli compose -f aws-web.yml --project-name mastodon-web service up
ecs-cli compose -f aws-api.yml --project-name mastodon-api service up
動きさえすれば運用段階では楽になる。