概要
かなり有名な手法ですが jwilder/nginx-proxy を使ってコンテナのゼロダウンデプロイを試してみました
nginx-proxy は VIRTUAL_HOST
を使ってコンテナのロードバランスをしてくれるコンテナです
環境
- macOS 10.14.3
- docker 18.09.2
アプリ作成
なんでも OK です
今回はホスト名を返すアプリを Ruby で作成しました
docker で動かせるように Dockerfile も作成します
bundle init
vim Gemfile
gem "sinatra"
vim app.rb
require 'sinatra'
get '/' do
`hostname`.strip
end
- vim Dockerfile
FROM ruby
ADD . /home
WORKDIR /home
RUN bundle install --path vendor
EXPOSE 4567
CMD ["bundle", "exec", "ruby", "app.rb", "-o", "0.0.0.0"]
こんな感じです
テストするのであれば以下のような感じで実行してホスト名が取得できれば OK です
docker build -t app .
docker run --rm -p 4567:4567 app
curl localhost:4567
docker-compose に組み込む
作成したアプリを jwilder/nginx-proxy
と連携するために docker-compose.yml を作成しましょう
vim docker-compose.yml
version: '2'
services:
proxy:
image: jwilder/nginx-proxy
restart: always
ports:
- "14567:80"
volumes:
- "/var/run/docker.sock:/tmp/docker.sock:ro"
app:
build: .
restart: always
ports:
- "4567"
environment:
- VIRTUAL_HOST=localhost
- VIRTUAL_PORT=4567
app_a:
extends:
service: app
app
と app_a
2 つアプリを作成します
このアプリを nginx-proxy
配下にぶら下げます
3 つ 4 つ増やしても問題ないです
ポイントは VIRTUAL_HOST
でバランシングしている点です
nginx-proxy はもしアプリが死んでいる場合、そちらにはリクエストを送信しません
なのでこれで app
と app_a
と交互に入れ替えることでゼロダウンタイムなデプロイを実現します
テスト
では実際に試してみます
まずは docker-compose でコンテナを立ち上げます
nginx-proxy にアクセスしてアプリにバランシングされているか確認しましょう
バランシング方式は単純なラウンドロビンっぽいです
docker-compose up -d
curl localhost:14567
ここからが本番です
まずは app_a
を停止してみましょう
docker-compose stop app_a
これでアクセスしてもちゃんとエラーにならずにレスポンスが返り続けます
app_a
コンテナを再作成してみましょう
docker-compose up -d --force-recreate app_a
再作成後しばらくするとリクエストが新しい app_a
にも振られるようになると思います
あとは同じように app
に対しても行えば OK です
今回は --force-recreate
でコンテナを再作成しただけですがコードが変更されておりイメージのビルドも必要な場合は以下のような感じでイメージの再ビルドもしましょう
git pull
docker-compose rm app_a
docker-compose build app_a
docker-compose up -d app_a
レジストリに登録しておき pull しても OK だと思います
Tips
例えば Let's Encrypt
で取得した証明書を使って SSL を有効にするには以下のように変更します
まず docker-compose.yml でアプリの VIRTUAL_HOST
の部分をちゃんとしたドメインに変更します
environment:
- VIRTUAL_HOST=hoge.fuga.com
- VIRTUAL_PORT=9292
そして proxy 側の定義の部分に証明書をマウントする定義を記載します
443 を LISTEN しましょう
そして証明書をコンテナの /etc/nginx/certs
にマウントします
この時、鍵 (.key
) と証明書 (.crt
) の名前は VIRTUAL_HOST
で指定したドメイン名にします
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/tmp/docker.sock:ro"
- "./keys/privkey.pem:/etc/nginx/certs/hoge.fuga.com.key"
- "./keys/fullchain.pem:/etc/nginx/certs/hoge.fuga.com.crt"
すると SSL で受け付けるための conf ファイルを自動で作成してくれます
なお SSL を有効にすると http 側のアクセスはすべて https にリダイレクトするようになっています
最後に
nginx-proxy を使ってコンテナをバランシングしてダウンタイム無しでコンテナをデプロイする方法を紹介しました
実際はこれ以外に証明書やコンテナ間のセッション情報の共有やデータベースなどが絡むのでアプリ側の改修も必要になるかもしれません
過去に haproxy を使ってロードバランシングした記事を紹介したのですがこれを使っても同じようなことができると思います
0 件のコメント:
コメントを投稿