Introducing Docker Secrets Management で紹介されているパスワードなどの機密情報管理の仕組みを試してみました。
サーバー3台を起動
いつものように DigitalOcean で Docker 1.13 on Ubuntu 16.04 のサーバーを3台立ち上げます
$ doctl compute droplet ls
ID Name Public IPv4 Public IPv6 Memory VCPUs Disk Region Image Status Tags
39553388 docker1 128.199.166.69 2048 2 40 sgp1 Ubuntu Docker 1.13.0 on 16.04 active
39553389 docker2 128.199.166.74 2048 2 40 sgp1 Ubuntu Docker 1.13.0 on 16.04 active
39553390 docker3 128.199.166.111 2048 2 40 sgp1 Ubuntu Docker 1.13.0 on 16.04 active
Swarm cluster を作成する
root@docker1:~# docker swarm init --listen-addr eth1 --advertise-addr eth1
Swarm initialized: current node (belgib92ppl2xq75aliayfpfu) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-3avyjkw67sm3c6mpkmspb1g68vn3pp2xjd60e20j591qpaingi-eo53e4b2q029frqg868n9errv \
10.130.6.155:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
2377/tcp で待ち受けるよってことですが、
root@docker1:~# ufw status
Status: active
To Action From
-- ------ ----
22 LIMIT Anywhere
2375/tcp ALLOW Anywhere
2376/tcp ALLOW Anywhere
22 (v6) LIMIT Anywhere (v6)
2375/tcp (v6) ALLOW Anywhere (v6)
2376/tcp (v6) ALLOW Anywhere (v6)
開いてないので開けましょう (3台とも)
# ufw allow in on eth1 proto tcp to any port 2377
Rule added
Rule added (v6)
# ufw allow out on eth1 proto tcp to any port 2377
Rule added
Rule added (v6)
2台目、3台目を worker として swarm の join させる
root@docker2:~# docker swarm join --listen-addr eth1 --advertise-addr eth1 \
> --token SWMTKN-1-3avyjkw67sm3c6mpkmspb1g68vn3pp2xjd60e20j591qpaingi-eo53e4b2q029frqg868n9errv \
> 10.130.6.155:2377
This node joined a swarm as a worker.
root@docker3:~# docker swarm join --listen-addr eth1 --advertise-addr eth1 \
> --token SWMTKN-1-3avyjkw67sm3c6mpkmspb1g68vn3pp2xjd60e20j591qpaingi-eo53e4b2q029frqg868n9errv \
> 10.130.6.155:2377
This node joined a swarm as a worker.
3台の swarm cluster ができました
root@docker1:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
49tnhxfj2f935pzf0oa6hiia5 docker2 Ready Active
belgib92ppl2xq75aliayfpfu * docker1 Ready Active Leader
o71mxiuvxb1uxqzsc9n84ymud docker3 Ready Active
secret の作成
Manage sensitive data with Docker secrets にいろんな例がありますが標準入力からの文字列を登録してみます。
root@docker1:~# echo "This is a secret" | docker secret create my_secret_data -
j64qa46dokdye82drqmjiy0z7
root@docker1:~# docker secret ls
ID NAME CREATED UPDATED
j64qa46dokdye82drqmjiy0z7 my_secret_data About a minute ago About a minute ago
root@docker1:~# docker secret inspect my_secret_data
[
{
"ID": "j64qa46dokdye82drqmjiy0z7",
"Version": {
"Index": 21
},
"CreatedAt": "2017-02-10T14:19:29.170169762Z",
"UpdatedAt": "2017-02-10T14:19:29.170169762Z",
"Spec": {
"Name": "my_secret_data"
}
}
]
コンテナから secret にアクセスする
なんでもいいけど redis のサービスを --secret="my_secret_data"
つきで作成する
root@docker1:~# docker service create --name="redis" --secret="my_secret_data" redis:alpine
t7pnaiho5b26uilcz58q7ej8x
root@docker1:~# docker service ls
ID NAME MODE REPLICAS IMAGE
t7pnaiho5b26 redis replicated 1/1 redis:alpine
root@docker1:~# docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
sxiapghqb6ev redis.1 redis:alpine docker1 Running Running 4 minutes ago
docker1 上で起動しているので docker1 サーバー上で docker exec します
root@docker1:~# docker exec $(docker ps --filter name=redis -q) ls -l /run/secrets
total 4
-r--r--r-- 1 root root 17 Feb 10 14:20 my_secret_data
/run/secrets/my_secret_data
というファイルが確認できます 中身を見てみます
root@docker1:~# docker exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data
This is a secret
docker secret create に渡した This is a secret ができました。 コンテナの /run/secrets ディレクトリに secret の名前のファイルができるわけですね。 コンテナ起動中には使われている secret は削除できないようです
root@docker1:~# docker secret rm my_secret_data
Error response from daemon: rpc error: code = 3 desc = secret 'my_secret_data' is in use by the following service: redis
コンテナから消したい場合は service の update を行う必要があるようです。
root@docker1:~# docker service update --secret-rm="my_secret_data" redis
redis
root@docker1:~# docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
9i9axnogc4cz redis.1 redis:alpine docker2 Running Running 2 seconds ago
sxiapghqb6ev \_ redis.1 redis:alpine docker1 Shutdown Shutdown 6 seconds ago
今度は docker2 サーバーですね
root@docker2:~# docker exec $(docker ps --filter name=redis -q) cat /run/secrets/my_secret_data
cat: can't open '/run/secrets/my_secret_data': No such file or directory
当該ファイルにアクセスできなくなりました
secret 名を別名で渡す
Manage sensitive data with Docker secrets の例に Wordpress + MySQL のものがあります。
$ docker service create \
--name mysql \
--replicas 1 \
--network mysql_private \
--mount type=volume,source=mydata,destination=/var/lib/mysql \
--secret source=mysql_root_password,target=mysql_root_password \
--secret source=mysql_password,target=mysql_password \
-e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
-e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
-e MYSQL_USER="wordpress" \
-e MYSQL_DATABASE="wordpress" \
mysql:latest
$ docker service create \
--name wordpress \
--replicas 1 \
--network mysql_private \
--publish 30000:80 \
--mount type=volume,source=wpdata,destination=/var/www/html \
--secret source=mysql_password,target=wp_db_password,mode=0400 \
-e WORDPRESS_DB_USER="wordpress" \
-e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \
-e WORDPRESS_DB_HOST="mysql:3306" \
-e WORDPRESS_DB_NAME="wordpress" \
wordpress:latest
MySQL コンテナで mysql_password として使ったものを Wordpress では wp_db_password として見せたいので --secret source=mysql_password,target=wp_db_password,mode=0400
と source と target で別の名前を使っています。mode で permission も指定できるのですね。 secret は値を更新することができないので、この source と target を駆使して service update する必要があるようです。あるいは一度 secret を削除して作りなおす、ただし、削除するにはコンテナを停止する必要がある。
Swarm mode はやっぱり簡単だよなぁ。1.12 の時は rolling update でもなぜか network が一旦切れるという問題があってこりゃまだ使えないなという感じだったけど 1.13 でもちょっと試してみよう。