Начиная с версии 17.06 – у Docker Swarm появилась поддержка новой концепции хранения и подключения файлов настроек для сервисов – configs
.
А ещё ранее, с версии 1.13 – secrets
, для хранения и передачи зашифрованных данных между менеджерами и нодами.
Ниже – описание и применение secrets
и configs
в Docker Swarm.
Содержание
Подготовка
VirtualBox
Создаём машинку в VirtualBox – это будет наш Swarm manager и он же – worker:
[simterm]
$ VBoxManage createvm --name dc_swarm --register Virtual machine 'dc_swarm' is created and registered. UUID: f2552be5-6e06-4594-acb5-e565444df11a Settings file: '/home/setevoy/VirtualBox VMs/dc_swarm/dc_swarm.vbox'
[/simterm]
Создаём сетевой интерфейс:
[simterm]
$ VBoxManage modifyvm dc_swarm --nic1 bridged --bridgeadapter1 enp0s25 --nictype1 82540EM --cableconnected1 on
[/simterm]
Устанавливаем тип ОС:
[simterm]
$ VBoxManage modifyvm dc_swarm --ostype Debian_64
[/simterm]
Создаём жёсткий диск:
[simterm]
$ cd /home/setevoy/VirtualBox\ VMs/dc_swarm/ && VBoxManage createhd --filename dc_swarm.vdi --size 10000 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% Medium created. UUID: 14f607dc-4513-4f01-9eef-8d99f4a2f2fb
[/simterm]
К машине добавляем IDE контроллер:
[simterm]
$ VBoxManage storagectl dc_swarm --name "IDE Controller" --add ide
[/simterm]
Подключаем диск:
[simterm]
$ VBoxManage storageattach dc_swarm --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium dc_swarm.vdi
[/simterm]
Подключаем ISO с Debian:
[simterm]
$ VBoxManage storageattach dc_swarm --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium /home/setevoy/OS/debian-9.1.0-amd64-netinst.iso
[/simterm]
Увеличиваем память на машине до 2-х гигабайт:
[simterm]
$ VBoxManage modifyvm dc_swarm --memory 2048
[/simterm]
И наконец – запускаем машину:
[simterm]
$ VBoxManage startvm dc_swarm Waiting for VM "dc_swarm" to power on... VM "dc_swarm" has been successfully started.
[/simterm]
Выполняем установку ОС:
Обновляем пакеты:
[simterm]
# apt update && apt upgrade
[/simterm]
Устанавливаем Docker:
[simterm]
# curl https://get.docker.com/ | bash
[/simterm]
(вы ведь в курсе, что под рутом через пайп не стоит запускать скрипты из интернета? только из доверенных источников)
Добавляем пользователя setevoy
в группу docker
, что бы не пользоваться sudo
:
[simterm]
# usermod -aG docker setevoy
[/simterm]
Проверяем docker
:
[simterm]
setevoy@dcswarm:~$ docker version Client: Version: 17.10.0-ce API version: 1.33 Go version: go1.8.3 Git commit: f4ffd25 Built: Tue Oct 17 19:02:43 2017 OS/Arch: linux/amd64 Server: Version: 17.10.0-ce API version: 1.33 (minimum version 1.12) Go version: go1.8.3 Git commit: f4ffd25 Built: Tue Oct 17 19:01:22 2017 OS/Arch: linux/amd64 Experimental: false
[/simterm]
Docker
Создание Docker Swarm
Создаём Swarm:
[simterm]
setevoy@dcswarm:~$ docker swarm init Swarm initialized: current node (dfl55pzcsugb73eojmcfy58h4) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-1fo611jv34gf9ib6zkh9t9lmova6jvqarw5bj3d2rydaqbe5op-bkzz114rc7v2cs1v16k9b9q6k 10.11.100.163:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[/simterm]
Проверяем:
[simterm]
setevoy@dcswarm:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS dfl55pzcsugb73eojmcfy58h4 * dcswarm Ready Active Leader
[/simterm]
На одной машине сейчас работает и Swarm manager и worker.
Для проверки – создадим сервис и запустим простой контейнер с NGINX:
[simterm]
root@dcswarm:/home/setevoy# docker service create --name nginx -p 80:80 nginx ioid8welvkfy77ad1brampqdm overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker service ls ID NAME MODE REPLICAS IMAGE PORTS ioid8welvkfy nginx replicated 1/1 nginx:latest *:80->80/tcp
[/simterm]
Docker configs
Swarm service configs позволяет хранить некритичные данные, такие как файлы конфигурации, вне docker-образа или контейнера: вместо того, что бы подключать файл настроек через volume (-v
) или передавать переменные с параметрами – вы можете создать объект конфига и подключить его напрямую к файловой системе в создаваемом сервисе/контейнере.
Когда вы создаёте такой config
– Docker отправляет его на manager-ноду кластера по TLS, где он хранится в зашифрованных Raft логах (/var/lib/docker/swarm/raft
), которые реплицируются по всем менеджерам swarm-а.
Хороший обзор по Raft в Docker Swarm есть тут>>>.
Когда вы даёте доступ к конфигу для нового или уже запущенного сервиса в Swarm – он монтируется в файловую систему контейнера, по умолчанию для Linux это будет /<config_name>
.
Вы можете так же отозвать доступ к конфигу или добавить дополнительный в любой момент.
Создание configs
Создать конфиг очень просто, например – создадим файл настроек виртуалхоста для NGINX:
server { listen 80; root /usr/share/nginx/html/; index index.html index.htm index.nginx-debian.html; server_name dc-swarm.local; location / { try_files $uri $uri/ =404; } }
Создаём объект Docker config
:
[simterm]
root@dcswarm:/home/setevoy# docker config create vhost_nginx nginx_vhost.conf i7ckjge352lvght06qr8dzonc
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker config ls ID NAME CREATED UPDATED i7ckjge352lvght06qr8dzonc vhost_nginx 15 seconds ago 15 seconds ago
[/simterm]
Просмотреть его содержимое:
[simterm]
root@dcswarm:/home/setevoy# docker config inspect vhost_nginx --pretty ID: i7ckjge352lvght06qr8dzonc Name: vhost_nginx Created at: 2017-11-15 12:09:50.035131215 +0000 utc Updated at: 2017-11-15 12:09:50.035131215 +0000 utc Data: server { listen 80; root /usr/share/nginx/html/; index index.html index.htm index.nginx-debian.html; server_name dc-swarm.local; location / { try_files $uri $uri/ =404; } }
[/simterm]
Теперь можно удалить исходный файл, и использовать созданный конфиг.
Применение configs
Обновляем сервис, подключаем конфиг:
[simterm]
root@dcswarm:/home/setevoy# docker service update --config-add vhost_nginx nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti 2ca2986076ef cat /vhost_nginx server { listen 80; root /usr/share/nginx/html/; index index.html index.htm index.nginx-debian.html; server_name dc-swarm.local; location / { try_files $uri $uri/ =404; } }
[/simterm]
Что бы подключить конфиг в определённый каталог – используем src
и target
:
[simterm]
root@dcswarm:/home/setevoy# docker service update --config-add src=vhost_nginx,target="/etc/nginx/conf.d/dc-swarm.local.conf" nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') ls -l /etc/nginx/conf.d total 8 -r--r--r-- 1 root root 242 Nov 15 12:25 dc-swarm.local.conf -rw-r--r-- 1 root root 1093 Sep 14 16:35 default.conf
[/simterm]
Пробуем получить доступ к dc-swarm.local с хоста:
[simterm]
$ sudo sh -c "echo '10.11.100.163 dc-swarm.local' >> /etc/hosts"
[/simterm]
Проверяем:
[simterm]
$ curl -I dc-swarm.local HTTP/1.1 200 OK Server: nginx/1.13.6 Date: Wed, 15 Nov 2017 12:27:34 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Thu, 14 Sep 2017 16:35:09 GMT Connection: keep-alive ETag: "59baafbd-264" Accept-Ranges: bytes
[/simterm]
Аналогично можно добавить любые данные.
Например – повторим для создания индексного файла:
[simterm]
root@dcswarm:/home/setevoy# echo "This is dc-swarm.local" > index_local.html root@dcswarm:/home/setevoy# docker config create dc_index index_local.html 4ych3x1inktdkuqfz6q9hklby
[/simterm]
Подключаем конфиг к сервису:
[simterm]
root@dcswarm:/home/setevoy# docker service update --config-add src=dc_index,target="/usr/share/nginx/html/dc_index.html" nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Обновление configs
Обновляем настройки виртуалхоста – поменяем индексный файл:
server { listen 80; root /usr/share/nginx/html/; index dc_index.html; server_name dc-swarm.local; location / { try_files $uri $uri/ =404; } }
Создаём конфиг с именем vhost_nginx_v2:
[simterm]
root@dcswarm:/home/setevoy# docker config create vhost_nginx_v2 nginx_vhost.conf h13yug0d1jfcmdznosttyvqbp
[/simterm]
Отключаем конфиг от сервиса:
[simterm]
root@dcswarm:/home/setevoy# docker service update --config-rm vhost_nginx nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Удаляем старый конфиг из Swarm:
[simterm]
root@dcswarm:/home/setevoy# docker config rm vhost_nginx vhost_nginx
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker config ls ID NAME CREATED UPDATED 4ych3x1inktdkuqfz6q9hklby dc_index 5 minutes ago 5 minutes ago h13yug0d1jfcmdznosttyvqbp vhost_nginx_v2 About a minute ago About a minute ago
[/simterm]
Подключаем новый, v2:
[simterm]
root@dcswarm:/home/setevoy# docker service update --config-add src=vhost_nginx_v2,target="/etc/nginx/conf.d/dc-swarm.local.conf" nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Проверяем сервис:
[simterm]
$ curl dc-swarm.local This is dc-swarm.local
[/simterm]
Всё работает – новый конфиг подключился к NGINX.
Docker secrets
secrets
– это данные, например пароль или SSH ключ, которые не должны храниться в открытом виде в Dockerfile
и не должны передаваться в таком виде по сети.
Главное отличие secrets
от configs
это то, что configs
подключаются к файловой системе контейнера, тогда как secrets
– монтируются в память (/run/
).
Когда вы явно указываете доступ к секрету для сервиса или контейнера – по умолчанию он будет помещён в /run/secrets/<secret_name>
.
Создание secrets
Создаём новый “секрет”:
[simterm]
root@dcswarm:/home/setevoy# echo "password" > pwd.txt root@dcswarm:/home/setevoy# docker secret create pwd pwd.txt urgibv1kmkz3o3850n8msc0ej
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker secret ls ID NAME DRIVER CREATED UPDATED urgibv1kmkz3o3850n8msc0ej pwd About a minute ago About a minute ago
[/simterm]
Даём доступ к этому секрету для сервиса nginx
:
[simterm]
root@dcswarm:/home/setevoy# docker service update --secret-add pwd nginx ID NAME DRIVER CREATED UPDATED urgibv1kmkz3o3850n8msc0ej pwd About a minute ago About a minute ago
[/simterm]
Проверяем /var/run/secrets
в контейнере:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') ls -l /var/run/secrets total 4 -r--r--r-- 1 root root 9 Nov 15 14:37 pwd
[/simterm]
И содержимое файла:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') cat /var/run/secrets/pwd password
[/simterm]
Аналогично с configs
– можно указать точку монтирования.
Отключаем секрет от контейнера:
[simterm]
root@dcswarm:/home/setevoy# docker service update --secret-rm pwd nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
И подключаем его в /etc/pwd
:
[simterm]
root@dcswarm:/home/setevoy# docker service update --secret-add src=pwd,target="/etc/pwd" nginx nginx overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') cat /etc/pwd password
[/simterm]
Docker secrets
vs configs
Как говорилось, основная разница в том, что configs
при подключении к контейнеру становится частью файловой системы, тогда как secret
– помещается в памяти.
Проверить это можно сделав новый образ запущенного контейнера.
Сейчас у нас есть сервис nginx
к которому подключен config
dc_index и vhost_nginx_v2, и secret
– pwd:
[simterm]
root@dcswarm:/home/setevoy# docker service inspect nginx | jq '.[0].Spec.TaskTemplate.ContainerSpec.Secrets , .[0].Spec.TaskTemplate.ContainerSpec.Configs' [ { "File": { "Name": "/etc/pwd", "UID": "0", "GID": "0", "Mode": 292 }, "SecretID": "urgibv1kmkz3o3850n8msc0ej", "SecretName": "pwd" } ] [ { "File": { "Name": "/usr/share/nginx/html/dc_index.html", "UID": "0", "GID": "0", "Mode": 292 }, "ConfigID": "4ych3x1inktdkuqfz6q9hklby", "ConfigName": "dc_index" }, { "File": { "Name": "/etc/nginc/conf.d/dc-swarm.local.conf", "UID": "0", "GID": "0", "Mode": 292 }, "ConfigID": "h13yug0d1jfcmdznosttyvqbp", "ConfigName": "vhost_nginx_v2" }, { "File": { "Name": "/etc/nginx/conf.d/dc-swarm.local.conf", "UID": "0", "GID": "0", "Mode": 292 }, "ConfigID": "h13yug0d1jfcmdznosttyvqbp", "ConfigName": "vhost_nginx_v2" } ]
[/simterm]
Создаём новый образ из этого запущенного контейнера:
[simterm]
root@dcswarm:/home/setevoy# docker commit $(docker ps | tail -n 1 | awk '{print $1}') nginx_copy sha256:4987a44e070804ff20f2146f0060e79b94b8b98fc31a734f720a76b3e907d002
[/simterm]
Проверяем образы:
[simterm]
root@dcswarm:/home/setevoy# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx_copy latest 4987a44e0708 16 seconds ago 108MB nginx <none> 40960efd7b8f 10 days ago 108MB
[/simterm]
Запускаем новый контейнер из созданного образа:
[simterm]
root@dcswarm:/home/setevoy# docker run -tid --name=nginx_copy nginx_copy c62fce9e32fd728e3cebd6da2257828818b9ed4f4420fc6addeeaf0810684a9c
[/simterm]
Проверяем файлы configs
:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti nginx_copy ls -l /etc/nginx/conf.d total 4 -rwxr-xr-x 1 root root 0 Nov 15 14:40 dc-swarm.local.conf -rw-r--r-- 1 root root 1093 Sep 14 16:35 default.conf
[/simterm]
ОК – на месте.
И secret
:
[simterm]
root@dcswarm:/home/setevoy# docker exec -ti nginx_copy ls -l /run/ total 12 drwxrwxrwt 2 root root 4096 Oct 9 00:00 lock drwxr-xr-x 2 root root 4096 Oct 9 00:00 mount -rw-r--r-- 1 root root 2 Nov 15 15:11 nginx.pid -rw-rw-r-- 1 root utmp 0 Oct 9 00:00 utmp
[/simterm]
Пусто.
Docker secrets и configs в Compose
Устанавливаем Docker Compose:
[simterm]
# curl -o /usr/local/bin/docker-compose -L "https://github.com/docker/compose/releases/download/1.15.0/docker-compose-$(uname -s)-$(uname -m)" # curl -o /usr/local/bin/docker-compose -L "https://github.com/docker/compose/releases/download/1.15.0/docker-compose-$(uname -s)-$(uname -m)"
[/simterm]
Что бы использовать secrets
и configs
в Compose файле – используем configs
и secrets
:
version: "3.3" configs: vhost_nginx: file: ./nginx_vhost.conf dc_index: file: ./index_local.html secrets: pwd: file: ./pwd.txt services: nginx: image: nginx secrets: - pwd configs: - source: vhost_nginx target: /etc/nginc/conf.d/dc-swarm.local.conf - source: dc_index target: /usr/share/nginx/html/dc_index.html
Создаём стек:
[simterm]
root@dcswarm:/home/setevoy# docker stack deploy -c compose_secrets_configs.yml nginx Creating service nginx_nginx
[/simterm]
Проверяем:
[simterm]
root@dcswarm:/home/setevoy# docker service inspect nginx_nginx | jq '.[0].Spec.TaskTemplate.ContainerSpec.Secrets , .[0].Spec.TaskTemplate.ContainerSpec.Configs' [ { "File": { "Name": "pwd", "UID": "0", "GID": "0", "Mode": 292 }, "SecretID": "uxr0m6wib0otfqglnwwwis19s", "SecretName": "nginx_pwd" } ] [ { "File": { "Name": "/usr/share/nginx/html/dc_index.html", "UID": "0", "GID": "0", "Mode": 292 }, "ConfigID": "twcghzoyzxb7j3l4yg15inwil", "ConfigName": "nginx_dc_index" }, { "File": { "Name": "/etc/nginc/conf.d/dc-swarm.local.conf", "UID": "0", "GID": "0", "Mode": 292 }, "ConfigID": "pulxlolcovj6ew4qniruvy3r5", "ConfigName": "nginx_vhost_nginx" } ]
[/simterm]
Готово.
Ссылки по теме
Manage sensitive data with Docker secrets
Store configuration data using Docker Configs
Docker Security: Using Docker Secrets with Swarm