概要
docker swarm + docker-compose を試してみました
docker stack という機能を使うことが実現できるのでその使い方を紹介します
環境
- macOS 10.14.5
- Vagrant 2.1.1
- Ubuntu 16.04 LTS
- docker 18.09.7
Swarm 環境構築
Vagrant でパパっと構築していきます
vim Vagrantfile
Vagrant.configure("2") do |config|
config.vm.define "vm01" do |v|
v.vm.box = "ubuntu/xenial64"
v.vm.network "private_network", type: "dhcp"
v.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
end
config.vm.define "vm02" do |v|
v.vm.box = "ubuntu/xenial64"
v.vm.network "private_network", type: "dhcp"
v.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
end
end
vagrant up
vagrant ssh
それぞれにログインして作業します
docker をインストールして Swarm クラスタを構築します
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo gpasswd -a $USER docker
sudo hostnamectl set-hostname vm01
これで docker のインストールは完了です
docker swarm init
docker swarm join --token SWMTKN-1-19rwa01lw9elmef3qiz9fmgn2mkvzfvdwivyxv1bgihhj3k3wv-6mcld04qufib76sni5a1kj82n 172.28.128.3:2377
vm01 で init を実行し vm02 で join コマンドを実行しましょう
docker node ls
これで Swarm の準備は OK です
とりあえず docker-compose の作成
とりあえずコンテナを複数デプロイする docker-compose.yml を作成してみます
確認のため環境変数 DUDE に動作しているコンテナホスト名を設定しています
vim docker-compose.yml
version: '3.4'
services:
nginx:
image: nginx
environment:
DUDE: "{{.Node.Hostname}}"
deploy:
replicas: 3
これを Swarm 上にデプロイしてみます
デプロイする場合は stack deploy を使います
docker stack deploy -c docker-compose.yml test
スタックの一覧を確認すると「test」というスタックが確認できます
docker stack ls
デプロイが完了したら ps コマンドで確認してみましょう
docker stack ps test
vm01 と vm02 に分散されてコンテナがデプロイされているのがわかります
exec コンテナが動作しているホストに対して docker ps
を実行しコンテナ ID か名前を取得してそれに対して実行しましょう
以下を実行するとちゃんと DUDE 変数にコンテナホスト名 vm01 が設定されているのが確認できると思います
docker exec test_nginx.1.ww8tdxhvkbhqh92vv822d7qx7 env
動作が確認できたらスタックを削除します
スタックを削除するとコンテナもすべて削除されます
docker stack rm test
ポートを使ってみる
今度はポートを使ってみます
stack deploy を使った場合、nginx プロセスが立ち上がりコンテナを自動でロードバランシングしてくれます
vim docker-compose.yml
version: '3.4'
services:
nginx:
image: valian/nginx-test-page
ports:
- "80:80"
deploy:
replicas: 3
イメージは動作確認しやすいイメージにしています
これでデプロイしてみましょう
docker stack deploy -c docker-compose.yml test
先程同様に test という stack が作成されています
これで vm01 or vm02 で localhost にアクセスしてみるとコンテナにアクセスできるのが確認できると思います
service について
ports を指定すると service も自動で作成されます
docker service ls
vm01 のコンテナホストに nginx のプロセスが立ち上がり overlay ネットワークを通して各コンテナホストにデプロイされたコンテナにアクセスすることができます
vm01 のコンテナホストに curl してみると以下のようにバランシングされていることが確認できます (この結果は vm02 から実行しても同じになります)
vagrant@vm01:~$ curl localhost
HOSTNAME=c0e0d2ae816c
vagrant@vm01:~$ curl localhost
HOSTNAME=8680d41c963b
vagrant@vm01:~$ curl localhost
HOSTNAME=4461b5233fc3
また docker ps -a
で確認するとわかりますがホストのポートにはバインドしておらず dockerd が直接ルーティングしていることがわかります
sudo lsof -i:80
ボリュームを使ってみる (ホストボリュームマウント)
次にボリュームを使ってみます
まずはコンテナホストのボリュームをマウントしてみます
version: '3.4'
services:
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./data:/data
deploy:
placement:
constraints: [node.role == manager]
mkdir data
docker stack deploy -c docker-compose.yml test
これで実行すると redis コンテナが 1 つ vm01 側で起動します
また service を確認すると 6379 へのルーティングが設定されており vm01, vm02 どちらの localhost にアクセスしても redis コンテナにアクセスできるようになっています
redis-cli set a a
redis-cli get a
=> a
また stack を rm して再度 deploy しても同じ値が再度取得できるのが確認できると思います
次に動作するコンテナホストを変更してみます
vim docker-compose.yml
version: '3.4'
services:
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./data:/data
deploy:
placement:
constraints: [node.role == worker]
mkdir data
docker stack deploy -c docker-compose.yml test
これで vm02 でコンテナが起動したら先程のデータが取得できるか確認してみましょう
redis-cli get a
=> nil
という感じでデータがないのが確認できます
これは当然と言えば当然ですが vm01 の ./data
をマウントしておりそこにデータも保存しているため起動するコンテナホストを vm02 にしたら当然保存したデータもありません
というわけで
service について
docker service ls
nginx のとき同様で dockerd が iptables を使って 6379 ポートをルーティングしてくれています
sudo iptables -L DOCKER-INGRESS
sudo lsof -i:6379
ボリュームを使ってみる (ボリューム領域作成)
ではホストの領域をマウントする方式ではなくボリュームを作成したらどうなるか確認してみます
vim docker-compose.yml
version: '3.4'
services:
redis:
image: redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
deploy:
placement:
constraints: [node.role == manager]
volumes:
redis_data:
driver: local
これで起動しデータをセットします
docker stack deploy -c docker-compose.yml test
redis-cli set a aa
そして docker-compose.yml 上は同じ volume を指定し動作させるコンテナホストを変更してみます
先程と同じように constraints: [node.role == worker]
に変更して rm -> deploy してみましょう
docker stack rm test
docker stack deploy -c docker-compose.yml test
redis-cli get a
=> nil
するとデータは nil で別のボリュームを参照していることが確認できると思います
各コンテナホストで docker volume ls
してみるとわかりますがそれぞれでボリュームが作成されており領域的には別になっていることが確認できます
これを回避する方法はいくつかありますが簡単そうなのは
- ボリュームコンテナを起動してその領域をマウントする
- nfs ドライバを使う
かなと思います
ただ docker-compose 3 系からは volumes_from
が使えないようなので前者は厳しいと思います
となると後者の nfs を選択するしかなさそうです
Tips
コンテナを起動するコンテナホストにイメージがない場合は最初に docker pull が走るためコンテナの起動が遅れます
最後に
docker Swarm + docker-compose を試してみました
基本的には stack 機能を使えば OK です
stack deploy, rm, ls など基本的なコマンドは覚えておきましょう
service と network は dockerd が良い感じにやってくれるのでそこまで苦労はしないと思います
一番辛そうなのは volume かなと思います
どうやらこれだけはデフォルトだとコンテナホスト間で共有するすべがなさそうです
NFS が一番簡単そうですが driver のインストールから必要になります
0 件のコメント:
コメントを投稿