Dockerを使ったローカルでの開発から本番環境へのデプロイまで

119
Dockerを使ったローカルでの開発から 本番環境へのデプロイまで (日本語版) http://www.slideshare.net/jpetazzo/from-development-environments-to-production-deployments-with-docker-compose-machine-swarm-and-ecs-cli-aws-reinvent-2015

Transcript of Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Page 1: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Dockerを使ったローカルでの開発から 本番環境へのデプロイまで

(日本語版)

http://www.slideshare.net/jpetazzo/from-development-environments-to-production-deployments-with-docker-compose-machine-swarm-and-ecs-cli-aws-reinvent-2015

Page 2: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

このセッションに期待できること

これからお話しするのは…

• 開発環境のための Docker Compose • その環境を本番稼動させるまでの話

- Dockerクラスタのプロビジョニング - コンテナイメージのビルドとそのデプロイ - サービスディスカバリ

• Docker Compose, Machine, Swarm, ECS

みなさんが Dockerの基本は知っている前提で進めます!

Page 3: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

自己紹介

• Jérôme Petazzoni ( @jpetazzo )

• 2010年から dotCloud社でいろんなものをコンテナにしてました - polyglot PAAS - microservice - プロビジョニング、メトリクス、スケーリング…

- LXCの大規模デプロイメント

• 2013年からは Docker社でいろんなものをコンテナにしてました  (dotCloudは 2013年にDockerと社名を変えました…)

• 今年 3年目となる技術を 5年間さわってます

Page 4: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

自己紹介 Take2

• こんにちは、Jérômeです!

• ソフトウェアエンジニアです。新しい仕事始めようとしてます!

• 実は明日から DockerCoins* を手がけようかと

(ブロックチェーンをもつ暗号通貨的なアレ)

• 同僚があらゆるところで Dockerを使って開発するので

• 僕の仕事は、それをスケールする形でデプロイすることです

* 架空のプロジェクトです。 DockerCoinでピザやコーヒーを買うことはできません(今はね)。

Page 5: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

準備しよう

Page 6: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

初仕事1日目に備える

• ちょうど新しいラップトップを受け取ったよ!

• セットアップ手順書にはたった一行:

  「Docker Toolboxをインストールしましょう」

• Windows版 MacOS版、ダウンロードサイズは 180MB未満です

Page 7: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Video: https://www.youtube.com/watch?v=g-g94H_AiOE

Page 8: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Composeを使った開発

Page 9: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Compose 新人向け作業ステップ

• 次の3ステップです

1) git clone git://github.com/jpetazzo/dockercoins (*1) cd dockercoins 2) docker-compose up 3) ブラウザでアプリを開きます (*2)

*1 訳者注: Docker Quickstart Terminalを起動し、コマンドを入力します *2 訳者注: http://{次のページの画面に表示されるIPアドレス}:8000/ でアクセスできます

Page 10: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Video: https://www.youtube.com/watch?v=sk3yYh1MgE0

Page 11: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

これだけでなんで動くの?

• “docker-compose up” は Composeにアプリを起動するよう伝えます

• 必要なら、そのアプリはまずビルドされます

• なぜ Composeは自分のすべき仕事がわかるのか

• Composeは Compose file (docker-compose.yml) を読み、動きます

Page 12: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

docker-compose.yml - シンプルな例

web: build: . ports: - “80:5000” links: - redis

redis: image: redis

Page 13: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

docker-compose.yml - 複雑な例(今回のアプリ)

rng: build: rng ports: - “8001:80”

hasher: build: hasher ports: - “8002:80”

redis: image: redis

worker: build: worker links: - rng - hasher - redis

webui: build: webui links: - redis ports: - “8000:80”

volumes: - “./webui/files/:/files/”

Page 14: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

これでなんで動くの?

• アプリケーションは、サービス単位に分割されていて

• サービスはそれぞれ 1つのコンテナとして動きます

• コンテナは、以下のいずれかをベースにして起動します - レジストリと呼ばれるライブラリに置いてある、

事前にビルドされたイメージ - Dockerfileというビルドレシピ

• Compose fileにはそれらサービスの定義が書かれています

(そのパラメタも。storage, network, env vars…)

Page 15: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

https://github.com/jpetazzo/dockercoins

Page 16: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

今回のサンプルアプリケ〡ション

• マイクロサービスアーキテクチャー

• 各サービスはそれぞれ異なる言語とフレームワークで構成 - Ruby + Sinatra - Python + Flask - Node.js + Express

• それぞれサービスの種類もバラバラ - バックグラウンドワーカー - REST APIをもった Webサービス - ステートフルなデータストア - Webフロントエンド

Page 17: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

マイクロサ〡ビスア〡キテクチャ不可避

• マイクロサービスのメリット

- チームを小さく保てる( Jeff Bezosの two-pizzaルール)

- 「適切な道具を使って適切な仕事を」が実現できる

- サービスはそれぞれ独立したデプロイ/スケールができる

- “Adrian Cockroft, Microservices” などで映像を検索してみよう

• マイクロサービスのデメリット - 分散システムにするのは難しい

(疑わしく思うなら、aphyr.comをみて)

- 負荷分散とサービスディスカバリが極めて重要

- “Microservices Not A Free Lunch” などで記事を探してみよう

Page 18: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

クラウド上のサ〡バにデプロイする

• ローカルと同じ手順です:

1) リモートの Dockerホストに SSH接続

2) git clone

3) docker-compose up

4) ブラウザでアプリを開きます

• Demoを見てみよう

Page 19: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• ssh • git clone git://github.com/jpetazzo/dockercoins cd dockercoins • docker-compose up

• ブラウザでアプリを開きます(http://サーバIPアドレス:8000/)

• ^C

Page 20: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Composeを使った開発フロ〡

• シンプルな4ステップです

1) ソースコードを編集します

2) docker-compose build 3) docker-compose up

4) ブラウザを更新

Page 21: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• webui/files/index.htmlを編集

• cssを変更

• docker-compose build • docker-compose up

• ブラウザを更新

• ^C

Video: https://www.youtube.com/watch?v=O3Bps01THBQ

Page 22: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Composeでコンテナをテイクアウト!

• Dockerは環境を抽象化してくれます

• Dockerホストさえあれば、どんな環境にもデプロイできます - ローカル環境

( Docker Toolboxで) - オンデマンドなクラウドインスタンス

( Docker Machineで)

- Bring-Your-Own-Server (オンプレやハイブリッドクラウドのために)

• 抵抗のない乗り換え(& コンテキストスイッチ)

• では、スケーラブルに、本番環境にデプロイする方法は?

Page 23: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

いま欠けていること

• クラスタのプロビジョニング

• ソースコードのビルドとデプロイ

• サービスディスカバリ

(これがすべてではない…)

引き続き、これらにどう取り組めばいいのかを見ていきましょう。

より深く掘り下げ、ライブデモももっとお見せします!

Page 24: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

クラスタのプロビジョニング

Page 25: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

プロビジョニング

• 手動でのインスタンス起動(CLIまたはコンソール)

• AWS CLIで自動化

• Auto Scalingグループ

• CloudFormationテンプレート

• Docker Machine

• ECS CLI

Page 26: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Docker Machine

• Docker Machineは Docker Toolboxに付属してます

• Dockerホストを作成することができます:

- EC2、またはその他クラウド上に

- ローカル環境上に( VirtualBox, OpenStack…)

• Docker Swarmと組み合わせればクラスタも生成できます

• 現在ある制約(いずれ改善すると期待しててください)

- 一度に起動できるのは 1台

- クレデンシャルは中央管理

Page 27: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

export TOKEN=$(docker run swarm create) echo $TOKEN

docker-machine create -d amazonec2 --swarm \

--swarm-master --swarm-discovery token://$TOKEN node00 &

for N in $(seq 1 4); do sleep 3 docker-machine create -d amazonec2 --swarm \

--swarm-discovery token://$TOKEN node0$N &

done

wait

Video: https://www.youtube.com/watch?v=LFjwusorazs

Page 28: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECS CLI

• 盗み見!?

• 最先端のクラスタ生成

• AWSのベストプラクティス:

- CloudFormationテンプレート

- AutoScalingグループ

- IAMとのインテグレーション

Page 29: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• ecs-cli configure • ecs-cli up --keypair jpetazzo --capability-iam --size 10

• (ELBの追加)

• (AutoScalingグループにロードバランサを関連づけ)

• (DNSエントリの追加)

• (ELBと ASGのためのセキュリティグループ設定)

Video: https://www.youtube.com/watch?v=KqEpIDFxjNc

Page 30: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ソ〡スコ〡ドのビルドとデプロイ

Page 31: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Dockerを使ったビルドとデプロイ

• アプリの Dockerイメージをビルドするために

引き続き Composeを使ってみましょう

• そしてそのイメージを Docker Registryに保存します

- Docker Hub ( GitHubのような SaaS。パブリックイメージは無料)

- Docker Trusted Registry ( 商用。AWS Marketplaceなどを通してお使いいただけます)

- 自前管理のレジストリ、コミュニティバージョン

Page 32: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

その具体的なプラン

• デプロイのたびに:

1) Composeですべてのコンテナを build

2) イメージにユニークなバージョン番号のタグをつける

3) レジストリにイメージを push

4) ビルド & プッシュしたイメージを参照している

新しい docker-compose.ymlファイルを生成

• これをスクリプトで実行しましょう

Page 33: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

スクリプトあるよ!

• これから使うスクリプトはすべて GitHubで公開しています

• 使うのもコピーも改変も、ぜひご自由にどうぞ~

そのスクリプトあるよ! みんな、スクリプトあるよ〡!!

URL: https://github.com/jpetazzo/orchestration-workshop

Page 34: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• build-tag-push.py • その結果ファイル (YAML) を確認する

これで Dockerイメージが固まりました。

イメージは “永遠に” 維持され、もし後から必要になっても大丈夫。 (たとえば、バージョンを巻き戻したい、など)

See: https://hub.docker.com/r/jpetazzo/dockercoins_webui/tags/

Page 35: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

サ〡ビスディスカバリ

Page 36: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

なぜサ〡ビスディスカバリが必要?

• サービス Aが、サービス Bと通信する必要がある

• Aはどうやって Bと通信する手段を把握するのか

- サービス Aに必要なもの: アドレス、ポート、クレデンシャル

• もし Bのサーバが複数あったら?

- 例: 負荷分散、レプリケーション

• もし Bのロケーションが時間とともに変わるなら? - 例: スケーリング、フェールオーバー

• サービスディスカバリはこれらの懸念に対処しようというもの

Page 37: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

開発サイドにみられる サ〡ビスディスカバリ

Page 38: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ハ〡ドコ〡ドされたサ〡ビスディスカバリ

• 開発用セットアップ:

$db = mysql_connect(“localhost”); cache = Redis.new(:host => “localhost”, :port => 16379)

conn, err := net.Dial(“tcp”, “localhost:8000”)

Page 39: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ハ〡ドコ〡ドされたサ〡ビスディスカバリ

• 開発用セットアップ、別の例:

$db = mysql_connect(“192.168.1.2”); cache = Redis.new(:host => “192.168.1.3”, :port => 6380)

conn, err := net.Dial(“tcp”, “192.168.1.4:8080”)

Page 40: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ハ〡ドコ〡ドされたサ〡ビスディスカバリ

• 本番用セットアップ:

$db = mysql_connect(“foo.rds.amazonaws.com”, “produser”, “sesame”); cache = Redis.new(:url => “redis://:[email protected]/15”) conn, err := net.Dial(“tcp”, “api-42.elb.amazonaws.com:80”)

Page 41: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ハ〡ドコ〡ドされたサ〡ビスディスカバリ

• 環境を切り替えるためのコード変更点が多い

• エラーを起こしやすい

• コードリポジトリに設定ファイルの大幅な変更、頻繁な変更が入る

• 新しいサービスの追加にはこれらすべての設定変更が必要になる

• メンテナンスが高コスト ( S個のサービス × E個の環境)

• 👻

Page 42: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Twelve-Factor App*

• 環境変数:

$db = mysql_connect($_ENV[“DB_HOST”], $_ENV[“DB_USER”], $_ENV[“DB_PASS”]);

cache = Redis.new(:url => “redis://:#{ENV[“REDIS_PASS”]}@” +

“#{ENV[“REDIS_HOST”]}:#{ENV[“REDIS_PORT”]}/” + “#{ENV[“REDIS_DB”]}”)

conn, err := net.Dial(“tcp”, os.ExpandEnv(“${API_HOST}:${API_PORT}”))

*訳者注: http://twelve-factor-ja.herokuapp.com/

Page 43: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Twelve-Factor App

• ソースコードと環境変数を明示的に分離する ( 環境は、文字通り環境変数によって定義されます)

• 依然として設定ファイルのメンテナンスは必要 (環境変数のリストもメンテ対象)

• 本番環境のパラメタを、容易にコードリポジトリ管理外にできる

• 激しいエラーはより起きにくくなる

• 😐

Page 44: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

設定デ〡タベ〡スの利用

• 動的ルックアップ( Zookeeperで):

$zk = new Zookeeper(‘127.0.0.1:2181’) $db = mysql_connect(

$zk->get(‘/apps/foo/prod/db/host’), $zk->get(‘/apps/foo/prod/db/user’), $zk->get(‘/apps/foo/prod/db/pass’));

zk = Zookeeper.new(‘127.0.0.1:2181’)

redis_pass = zk.get(:path => ‘/apps/foo/prod/redis/pass’) redis_host = zk.get(:path => ‘/apps/foo/prod/redis/host’) redis_port = zk.get(:path => ‘/apps/foo/prod/redis/port’) redis_db = zk.get(:path => ‘/apps/foo/prod/redis/db’) cache = Redis.new(:url => “redis://:#{redis_pass}@#{redis_host}:#{redis_port}/#{redis_db}”)

c, _, err := zk.Connect([]string[“127.0.0.1”], time.Second) api_host, _, err := c.get(“/apps/foo/prod/api/host”) api_port, _, err := c.get(“/apps/foo/prod/api/port”) conn, err := net.Dial(“tcp”, fmt.Sprintf(“%s:%s”, api_host, api_port))

Page 45: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

設定デ〡タベ〡スの利用

• 開発環境と本番環境で同じコードを使いたいなら 開発環境にも設定 DBをデプロイしなければならない

• 設定ファイルのメンテナンスをする代わりに Zookeeper*クラスタの管理をしなければいけない

• …もしくは開発・本番環境で異なるルックアップロジックを入れる

• 😥

*他のお気に入り設定 DBでも。etcdや Consulなど。

Page 46: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ロ〡カル負荷分散/ル〡ティング

• よく知られたロケーションに接続する:

$db = mysql_connect(“localhost”); cache = Redis.new(:host => “localhost”) conn, err := net.Dial(“tcp”, “localhost:8001”)

• 開発環境:すべてのコンポーネントはローカルで稼働

• 本番環境:ローカルのロードバランサがトラフィックを捌く (例: Airbnbの SmartStack)

Page 47: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ロ〡カル負荷分散/ル〡ティング

• ソースコードは開発・本番間で一致させることができる

• デプロイは以下の点で変わってくる - 開発環境は直接接続される - 本番環境はプロキシ、ルータ、ロードバランサが介在する

• 「設定」は単に静的なポート割り当てを示したもの (どのサービスがどのポートを Listenしているのか)

• 開発はしやすい。運用サイドはやることあるけど..

• 😏

Page 48: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アンバサダ〡パタ〡ン

Page 49: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アンバサダ〡を使ったコ〡ドベ〡ス

• よく知られたDNS名を使います

$db = mysql_connect(“db”); cache = Redis.new(:host => “redis”) conn, err := net.Dial(“tcp”, “api:8000”)

Page 50: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

接続が必要なサービスを参照するよう適切に設定した /etc/hosts を各コンテナにおきましょう。

例えば “worker” には:

172.17.0.1 hasher 172.17.0.2 rng 172.17.0.3 redis

開発環境では

webui 172.17.0.5

redis 172.17.0.3

worker 172.17.0.4

hasher 172.17.0.1

rng 172.17.0.2

containerhost

Page 51: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

IPアドレスの振り方は異なりますが、ソースコードは同じものが利用できます。

“worker” 上の /etc/hosts:

10.0.0.10 hasher 10.0.0.15 rng 10.0.0.12 redis

また別の開発環境では

webui 10.0.0.4

redis 10.0.0.12

worker 10.0.0.20

hasher 10.0.0.10

rng 10.0.0.15

containerhost

Page 52: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Composeは Dockerの「links」を使って /etc/hosts の設定を自動でやってくれます。

Composeさえ使えば、もう開発環境のことはケアされています!

では、複数ホストにまたがる本番環境はどうでしょうか?

朗報です

webui 172.17.0.5

redis 172.17.0.3

worker 172.17.0.4

hasher 172.17.0.1

rng 172.17.0.2

containerhost

Page 53: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

workerは実際の redis, hasher, rngコンテナとは接続しません。接続するのはアンバサダーです。

アンバサダーは本来接続したいコンテナへトラフィックを向かわせます*。

*フォワード、負荷分散、プロキシ…

本番環境では

redis 172.17.0.3

worker 172.17.0.4

hasher 172.17.0.1

rng 172.17.0.2

containerhost ambassador

Page 54: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

本番環境では

redis 172.17.0.3

worker 172.17.0.4

hasher 172.17.0.1

rng 172.17.0.2

containerhost ambassador

hasher 172.17.0.5

rng 172.17.0.4

hasher 172.17.0.8

redis 172.17.0.7

webui 172.17.0.8

redis 172.17.0.6

Page 55: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アンバサダ〡を使えば

• ソースコードは読みやすく、クリーンに保てる

• プラミング(サービスディスカバリ、ルーティング、負荷分散などコンテナ同士を繋げる作業)をなくせました! (依然として誰かはやらなければいけないけど)

• プラミングは開発環境の邪魔をするものではない

• プラミングについての変更は、コードベースに影響しない

• 😊

Page 56: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

運用サイドにみられる サ〡ビスディスカバリ

Page 57: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

どのくらいの早さでサービス更新してる?

Page 58: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ゆっくり更新

• デプロイは滅多にしない - 毎週、定刻で - ちょっとのダウンタイムは OK(数分、まぁ1時間くらいなら)

• デプロイの失敗はまれ(年に1回未満) かつ/またはクリティカルな影響はない

• 再設定は緊急ではない: - デプロイプロセスの中で対応している - サービス障害やダウンタイムの原因になっても、まあ OK

Page 59: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ゆっくり更新するアプリへの戦略

• 再設定はデプロイプロセスの中で実施する

(再ビルド、再プッシュ、再デプロイ)

• もしくは、デプロイの後で手で変更すればいいし(!)

• 緊急なら: SSH + vi(!)

Page 60: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

その結果

• メリット - 前払い費用は発生しない - わかりやすい*

• デメリット - 各デプロイ、各変更がリスクそのもの - 長期的にみると高コスト

*アプリが落ちて、復旧にしばらく時間がかかるときのあなたの上司は除く

Page 61: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

まあまあ更新

• コードのデプロイ - 毎日やってる - ダウンタイムは OKじゃない(ほんのちょっとした不備ならいいかも)

• 定期的にデプロイに失敗する 迅速に解決しなければいけない

• 再設定は頻繁にある:

- スケール up/down、ワークロードの増減、データベースの変更

- A/Bテストのためのパラメタ変更

Page 62: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

まあまあ更新するアプリへの戦略

• デプロイ後の設定差し込み

• パラメタを変更したかったら:

再設定(すべてを再デプロイするのではなく)

• 「pushボタン」スクリプトによるプロセスの自動化

Page 63: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

その結果

• メリット - わかりやすいし実装しやすい - 不要な更新作業がない (pushボタンスクリプトだけは余分だけど)

• デメリット - サービスが再設定できる作りになっていなければいけない - 再設定は各設定値の変更後に走らなければいけない - デプロイシステムが不具合を起こすリスクがある

Page 64: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ワイルド*に更新

• コードのデプロイ - 継続的に起こる(1日に 10, 100, 1000回以上)

- ダウンタイムは OKじゃない(散発的なリクエストの失敗さえも)

• デプロイの失敗はいつも起こっている 復旧プロセスは完全に自動化されていなければならない

• 再設定はアプリのライフサイクルの一部: - 計画的、非計画的なスケールにも対応した自動スケーリング - 一般化された blue/greenデプロイメント、カナリーテストなど

* Wildly.「Move fast and break things」としても知られているもの

Page 65: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ワイルドに更新するアプリへの戦略

• 必須:変更があればそれを検知する仕組み • 以下を連携して使う

- 監視 - 受信可能なイベントのライブストリーム - 自分自身を登録することができるサービス - 速いサイクルのポーリング

• デプロイ、スケーリング、サービス停止、メトリクス閾値超の後: 自動再設定

Page 66: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

その結果

• メリット - すべてが自動で動く - デプロイするとき、他に実行すべきステップはない - よりモジュラーになる (サービスの種類ごとに異なるプロセスに任せられる)

• デメリット - メンテナンスが必要な余分な更新作業・サービスが増える - デプロイシステムそのものの失敗が、より危険に

Page 67: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

まとめ

更新頻度

ゆっくり まあまあ ワイルド 開発サイド 運用サイド スケール 失敗

ハードコード ✅ 🚫 🚫 😃 😃 😠 😰

12-Factor ✅ 🔄 🚫 😃 😃 😕 😕

設定DB ✅ ✅ ✅ 😩 😠 😎 😎

ローカル LB/ルーター ✅ ✅ ✅ 😐 😐 😎 😎

アンバサダー ✅ ✅ ✅ 😃 😐 😎 😎

うまくいくか 対処方法

Page 68: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

まとめ(字幕版)

更新頻度

ゆっくり まあまあ ワイルド 開発サイド 運用サイド スケール 失敗

ハードコード OK NO NO easy easy painfully horribly

12-Factor OK OK withRESTARTS NO easy easy meh meh

設定DB OK OK OK hard hard cool cool

ローカル LB/ルーター OK OK OK medium medium/hard cool cool

アンバサダー OK OK OK easy medium/hard cool cool

うまくいくか 対処方法

Page 69: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

実践アンバサダ〡

Page 70: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

プラン

• シンプルなアプリケーションのデプロイ(trainingwheels) - ECSで

- Swarmで

• 複雑なアプリケーションのデプロイ(dockercoins) - ECSで

- Swarmで

Page 71: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

シンプルなアプリケ〡ション,“trainingwheels”

• 2つのサービス

- Webサーバ

- Redisデータストア

• どのサーバがリクエストに応答しているかを教えてくれます • 応答リクエスト数をカウントします • 各サーバごとに独立したカウンターをもちます

Page 72: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• cd ~ • git clone git://github.com/jpetazzo/trainingwheels cd trainingwheels • docker-compose up • ブラウザでアプリを開きます

• ^C

Page 73: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECSでのデプロイ

• ECSでは、コンテナはタスクのメンバーとして生成されます

• タスクは Task Definitionsで定義します

• Task Definitionsは概念的には Composeファイルと似ています (が、フォーマットが異なります)

• ECS CLIがデプロイを支援してくれます!

Page 74: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECSでのデプロイ

• ECS CLIがしてくれること:

- Composeファイルから Task Definitionsを生成し

- その Task Definitionsを ECSに登録します

- その Task Definitionsをもとに、ECSインスタンス(EC2)を起動します

• ECS CLIがしないこと:

- Composeファイルに buildセクションがあると動きません (imageセクションしか受け付けません)

• 既出の “build-tag-push” スクリプトを使いましょう!

Page 75: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo

• build-tag-push.py • 環境変数 COMPOSE_FILEをセット

• fixup-yaml.sh

Page 76: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECSで “trainingwheels”をスケ〡ルさせる

現在、デプロイ & スケールさせようとすると、アプリを複数コピーすることになります。それぞれが Redisをもってしまうわけです。

これを避けるために、最初のアンバサダーをデプロイします!

こんな感じで:

• Redisサービスのために新しい Composeファイルを作り

• Redisを起動するために ECS CLIを使い、そのロケーションをメモ

• Redisサービスが実際の Redisコンテナを指し示すアンバサダーになるよう、メインの Composeファイルを更新します

Page 77: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

jpetazzo/hambaのご紹介

• たくさんのコンテナを、簡単にアンバサダー配下に!

• シェルなら:

docker run jpetazzo/hamba <frontend-port> \ [backend1-addr] [backend1-port] \ [backend2-addr] [backend2-port] …

• Composeファイルなら:

redis: image: jpetazzo/hamba command: <front-port> [backend1-addr] [backend1-port] …

Page 78: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (1/2)

• mkdir ~/myredis • cp $COMPOSE_FILE ~/myredis • cd ~/myredis • $COMPOSE_FILEを編集

- 6379ポートをさらします

- wwwサービスを削除

• ecs-cli compose up • ecs-cli compose ps

• ホスト名とポート番号をメモします

Page 79: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (2/2)

• cd ~/trainingwheels • $COMPOSE_FILEを編集

- redisのイメージを “image: jpetazzo/hamba” に入れ替えます

- “command: 6379 <redishost> <redisport>” という一文を追加

• ecs-cli compose up • ecs-cli compose scale 4 • watch ecs-cli compose ps • ブラウザでアプリを開きます

Page 80: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

クリ〡ンアップ

• ecs-cli compose down • redisは後でまた使うので、走らせたままで OK

Page 81: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Swarmで “trainingwheels”をスケ〡ルさせる

• ちょっと違ったアイディア!

• Composeファイルは 1つをキープ

• docker linksをアンバサダーで置き換え

- ローカルアドレスの利用(127.X.Y.Z)

- (同一ホスト上の)コンテナ間で namespaceを共有

• 他のサービスに接続する各コンテナは、そのサービスを示す

プライベートなロードバランサを得ることになる • たくさんのロードバランサが必要になるけど大丈夫、

低コストなサーバリソースで動作します

Page 82: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

redisコンテナと wwwコンテナは

Swarmによって配置されますが、異なるホスト上になる可能性があります。

wwwコンテナの /etc/hostsはこんな感じ。

127.127.0.2 redis

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

Page 83: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

このタイミングでは、 wwwから

redisへの接続は「接続が拒否されました」となり、失敗します。

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

Page 84: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アンバサダーが起動します。

そのアンバサダーは wwwコンテナとネットワークの名前空間を共有しているので、つまり、同じループバックインターフェイスをもっていることになります。 (お互いに localhost上で会話できます)

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

ambassador 127.127.0.2

Page 85: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

しかし依然として接続は失敗します。(「接続が拒否されました」か「タイムアウトしました」ですが、それはロードバランサの設定によります)

アプリはこれに行儀よく対処する必要があります。

(クラッシュか再起動でも十分行儀がいいといえます)

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

⛔ ⌛

ambassador 127.127.0.2

Page 86: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アンバサダーが redisコンテナのパブリックアドレスを含むその設定を受け取ります。

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

ambassador 127.127.0.2

Page 87: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

wwwから redisへのトラフィックが正常に流れます。

Network namespaceアンバサダ〡

redis 172.17.2.5

containerhost ambassador

www 172.17.0.4

ambassador 127.127.0.2

Page 88: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (1/2)

• eval $(docker-machine env nod00 --swarm

• $COMPOSE_FILEを編集 - redisが使うイメージを “image: redis” にもどします

- “command:” セクションを削除

• link-to-ambassadors.pyを実行

• docker-compose up -d • docker-compose ps

• ブラウザでアプリを開きます

• (まだ動きません..)

Page 89: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (2/2)

• create-ambassadors.pyを実行

• configure-ambassadors.pyを実行

• ブラウザでアプリを開きます

• docker-compose scale www=4

• create-ambassadors.pyを実行

• configure-ambassadors.pyを実行

• ブラウザでアプリを開きます

Page 90: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

アプリをスケールさせるまえに、アンバサダーとセットにした

wwwコンテナをひとつ起動。

(この例では、ステップを明確にするために redisコンテナも一緒に起動してしまいます)

アンバサダ〡つきのスケ〡リング

redis

containerhost ambassador

www

ambassador

Page 91: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

docker-compose scale www=4

4つの wwwコンテナが起動しましたが、そのうち 3つはまだ redisと通信することができません。

アンバサダ〡つきのスケ〡リング

redis

containerhost ambassador

www

ambassador

www

www www

Page 92: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

create-ambassadors.py

新しい 3つの wwwコンテナが自分のアンバサダーを確保しますが、まだ設定がされていません。

アンバサダ〡つきのスケ〡リング

redis

containerhost ambassador

www

ambassador

www

www www

ambassador

ambassador ambassador

Page 93: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

configure-ambassadors.py

新しい 3つの wwwコンテナが設定を受け取り、redisサービスへのトラフィックをルートできるようになります。

アンバサダ〡つきのスケ〡リング

redis

containerhost ambassador

www

ambassador

www

www www

ambassador

ambassador ambassador

Page 94: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

クリ〡ンアップ

• docker-compose kill • docker-compose rm -f

Page 95: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECSで “dockercoins”をスケ〡ルさせる

• 同じテクニックを適用してみましょう

• Redisサービスを分割します

• Composeファイルの “redis” をアンバサダーに置き換えます

• 残りは ECSに任せましょう

Page 96: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (1/2)

• redisのホスト名とポート番号を確認 - cd ~/myredis - ecs-cli compose ps

• cd ~/dockercoins • 環境変数 COMPOSE_FILEをセット

• $COMPOSE_FILEを編集 - “image: redis” を “image: jpetazzo/hamba” に変更

- “command: 6379 <redishost> <redisport>” を追加

- すべてのコンテナに “mem_limit: 100000000” を追加

- volumesを削除

• fixup-yaml.sh

Page 97: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (2/2)

• ecs-cli compose up • watch ecs-cli compose ps • ブラウザでアプリを開きます

• ecs-cli compose scale www=4

• watch ecs-cli compose ps • ブラウザでアプリを開きます

• 繰り返し!

Page 98: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• redisサービスから始めましょう…

containerhost ambassador

redis

ECSで “dockercoins”をスケ〡ルさせる

Page 99: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• アンバサダー入りのサービスグループをひとつ起動します

webui

containerhost ambassador

worker

redis

redis

ECSで “dockercoins”をスケ〡ルさせる

rnghasher

Page 100: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• 2番目のサービスグループを追加します

webui

containerhost ambassador

worker

redis

redis

ECSで “dockercoins”をスケ〡ルさせる

rnghasher

webui

worker

redis

rnghasher

Page 101: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• もうひとつ…など

webui

containerhost ambassador

worker

redis

redis

ECSで “dockercoins”をスケ〡ルさせる

rnghasher

webui

worker

redis

rnghasher

webui

worker

redis

rnghasher

Page 102: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Swarmで “dockercoins”をスケ〡ルさせる

• 同じテクニックを適用しましょう

• Composeファイルの “redis” をアンバサダーに置き換えます

• コンテナを起動します

• アンバサダーを追加します

• アンバサダーに設定を差し込みます

Page 103: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (1/2)

• $COMPOSE_FILEを編集 - redisが使うイメージを “image: redis” にもどします

- redisの “command:” セクションを削除

• link-to-ambassadors.pyを実行

• docker-compose up -d • create-ambassadors.py • configure-ambassadors.py • docker-compose ps webui

• ブラウザで webuiを開きます

Page 104: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Demo (2/2)

• docker compose scale webui=2 worker=10 rng=20 hasher=5 • create-ambassadors.pyを実行

• configure-ambassadors.pyを実行

• ブラウザでアプリを開きます

Page 105: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• 単純化のために、2つの Dockerホストだとします

Swarmで “dockercoins”をスケ〡ルさせる

containerhost ambassador

Page 106: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

containerhost ambassador

• docker-compose up - 繋がっていないコンテナが起動します

Swarmで “dockercoins”をスケ〡ルさせる

webui

worker

redis

rng

hasher

Page 107: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

containerhost ambassador

• 必要に応じてコンテナにアンバサダーを生成します

Swarmで “dockercoins”をスケ〡ルさせる

webui

redis

worker

redis

rng

hasher

hasher

rng

redis

Page 108: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

containerhost ambassador

• アンバサダーを設定。アプリが起動します

Swarmで “dockercoins”をスケ〡ルさせる

webui

redis

worker

redis

rng

hasher

hasher

rng

redis

Page 109: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

containerhost ambassador

• docker-compose scale

Swarmで “dockercoins”をスケ〡ルさせる

webui

redis

worker

redis

rng

hasher

hasher

rng

redis

worker

worker

hasher

rng

hasher

rng

rng

rng

Page 110: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

containerhost ambassador

• 新しいアンバサダーの生成

Swarmで “dockercoins”をスケ〡ルさせる

webui

redis

worker

redis

rng

hasher

hasher

rng

redis

worker

worker

hasher

rng

hasher

rng

rng

rng

redis

hasher

rng

redis

hasher

rng

Page 111: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

• 新しいアンバサダーに設定を差し込み

containerhost ambassador

Swarmで “dockercoins”をスケ〡ルさせる

webui

redis

worker

redis

hasher

hasher

rng

redis

worker

worker

redis

hasher

rng

redis

hasher

rnghasher

rng

rng

rng

hasher

rng

rng

Page 112: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

注目点

• そうだね、たしかにアンバサダー多いよね

• でもすごく軽いんで(~1MB) docker stat $(docker ps | grep hamba | awk ‘{print $1}’)

• アンバサダーを追加してもホップ数は増えません - アンバサダーはそのクライアントに対してローカル (仮想的にレイテンシはゼロ)

- 外部のロードバランサと比較すればより効率的

- アンバサダーがダウンしたら、おそらくクライアントも同時にダウン

Page 113: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

おさらい

Page 114: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

Docker Compose

• アプリケーションの可搬性:

- Docker Compose + Docker Toolbox - Docker Compose + Docker Swarm - ECS CLI + ECS

• インターフェース:

- Composeファイル

- Docker Registry

Page 115: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ECS & Swarm ハイライト

• どちらも簡単なプロビジョニングを支援するもの

• ECS = AWSエコシステム:

- IAMやELBなど、AWSリソースの利用

- ヘルスチェックや自己回復機能の提供

• Swarm = Dockerエコシステム: - ローカルの開発環境との類似性を提案

- Docker APIを通じてリアルタイムイベントを出力

• どちらもビルドするためのツールが別途必要 ( Swarmには予備的なビルドサポートはある)

• どちらもプラミング/サービスディスカバリのために要追加作業

Page 116: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

将来への指針、アイディア…

• みなさんからのフィードバック、心よりお待ちしております!

• 特定アプリに特化したアンバサダー ( SQLバウンサー*、クレデンシャルインジェクター…)

• オフィシャルイメージを使ったサービスの自動的な置き換え - redis, memcached -> elasticache - mysql, postgresql -> RDS - etc.

* 訳者注:不正な入力をブロックするセキュリティソフトウェアのこと

Page 117: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

その他実装

• Docker APIのイベントストリームを Listenして、 コンテナの start/stopを検知する

- 自動的なロードバランサの設定(ehazlett/interlock)

- 設定データベースへのコンテナの追加(gliderlabs/registrator)

• オーバーレイネットワーク - サードパーティ: weave, flannel, pipework - Docker network plugin(experimental.docker.com)

Page 118: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

ありがとうございました!

Page 119: Dockerを使ったローカルでの開発から本番環境へのデプロイまで

コ〡ドリポジトリ:https://github.com/aws/amazon-ecs-clihttps://github.com/jpetazzo/dockercoinshttps://github.com/jpetazzo/trainingwheelshttps://github.com/jpetazzo/orchestration-workshop

ビデオ:https://www.youtube.com/watch?v=g-g94H_AiOE

Twitterでフォロ〡してね:@docker @jpetazzo

https://www.youtube.com/watch?v=sk3yYh1MgE0

https://www.youtube.com/watch?v=KqEpIDFxjNchttps://www.youtube.com/watch?v=LFjwusorazs

備忘:ビデオには導入やデプロイプロセスの様子のみが録画されています。 もし要望がたくさんあれば、他のデモも撮影するつもりです。

https://www.youtube.com/watch?v=O3Bps01THBQ