App Engine のFlexible 環境が高すぎて(f1-smallと同じスペックで月4,000円超)こりゃ厳しいと思い、GCEに逃げることにした。
ロードバランサーとかも組み込まれているようなので、アクセス数がそれなりにある場合は App Engine が大活躍だと思うが、超小規模 Web サービスには厳しかった。
今後のことも考えて docker で運用していきたい。
やること
- Cloud Build で Rails アプリケーションのイメージ化
- インスタンス作成
- SSL証明書取得
- Webアプリケーション起動
- cloudsql proxy との接続
Cloud Build で Rails アプリケーションのイメージ化
この記事 で Code Build を使ってイメージ化済み
インスタンス作成
Container-Optimized OS を選択し、イメージのデプロイはこのタイミングでは行わない。(docker-compose.yml で一括管理したいので)
SSL証明書取得
起動したインスタンスにSSH接続をして以下のコマンドを叩いておく。
DOMAIN_NAMEとEMAILは使う環境に合わせて変更する。
$ docker run \
--rm \
-p 80:80 -p 443:443 \
-v letsencrypt:/etc/letsencrypt \
certbot/certbot:latest certonly \
--non-interactive --agree-tos \
--domain DOMAIN_NAME --email EMAIL \
--standalone
これでインスタンス内に証明書が保存される。
更新時は webroot に変えて cron を使ってやれば良い。
注意
volume の指定を -v /etc/letsencrypt:/etc/letsencrypt
のようにホストの /etc/
に保存させてしまうと、インスタンス再起動時になくなってしまう。
これは Container-Optimized OS のセキュリティのため。詳しくはこちら
Webアプリケーション起動 & cloudsql proxy との接続
docker-compose を使えるようにする
Container-Optimized OS ではデフォルトで docker-compose は入っていない。
docker 経由で docker-compose を行えるようにする方法が公式に記載されている。
なお、ドキュメントの docker-compose イメージのバージョンが相当古いのでここで最新のバージョンを確認すると良い。
# エイリアス作成
$ echo alias docker-compose="'"'docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD:/rootfs/$PWD" \
-w="/rootfs/$PWD" \
docker/compose:1.22.0'"'" >> ~/.bashrc
# 反映
$ source ~/.bashrc
docker-compose で他のコンテナを構築
Container Registry のプライベートイメージをpullするにはちょっとだけ手間が必要。
GCEインスタンス作成時に指定すると持ってきてくれるけど、構築しにくかったので手動で持ってくるようにする。
詳細はここ参照。
以下のコマンドを実行すると、Container Registry にアクセスするための JSON ファイルが生成される
$ docker-credential-gcr configure-docker
事前に docker pull でイメージを取得しておく。(ここでいう docker-compose は実質 docker 内での挙動なので先程の JSON を見てくれないっぽい?)
あとは docker-compose で起動
docker-compose.yml と nginx の設定ファイルは ここ に置いた。
docker-compose.ymlと同じディレクトリに .env
ファイルを作成して、 NGINX_CONFIG_PATH と INSTANCE_CONNECTION_NAME を指定する。
※ NGINX_CONFIG_PATH を指定する理由は docker イメージ内の docker-compose で動くからかわからないが、パスがずれるので絶対パスで指定すると動いたため。
cloudsql proxy との接続
docker-compose.yml 内の
app:
volumes:
- /mnt/stateful_partition/cloudsql:/cloudsql
gce-proxy:
container_name: gce-proxy
image: gcr.io/cloudsql-docker/gce-proxy
command: /cloud_sql_proxy -dir=/cloudsql -instances=${INSTANCE_CONNECTION_NAME}
volumes:
- /mnt/stateful_partition/cloudsql:/cloudsql
の部分で UNIX ソケット通信している。 volume で /mnt/stateful_partition/cloudsql
としているのは、 /cloudsql
とするとインスタンス再起動時に初期化されてしまうため。
ロギング
少しハマったので別記事にまとめる。
完成
これで GAE っぽい雰囲気を出しつつロードバランサーを抜いて GCE の金額のみで運用できそうな気がする。