Almacenar datos de configuración usando Docker Configs
Acerca de las configuraciones (configs)
Las configuraciones (configs) de servicios de Docker Swarm te permiten almacenar información no confidencial, como archivos de configuración, fuera de la imagen del servicio o de los contenedores en ejecución. Esto te permite mantener tus imágenes lo más genéricas posible, sin necesidad de montar archivos de configuración en los contenedores ni de usar variables de entorno.
Las configuraciones funcionan de manera similar a los secretos, con la diferencia de que no se cifran en reposo y se montan directamente en el sistema de archivos del contenedor sin utilizar discos RAM. Las configuraciones se pueden añadir o eliminar de un servicio en cualquier momento, y los servicios pueden compartir una configuración. Incluso puedes usar configuraciones junto con variables de entorno o etiquetas para obtener la máxima flexibilidad. Los valores de configuración pueden ser cadenas genéricas o contenido binario (de hasta 500 KB de tamaño).
NoteLas configuraciones de Docker solo están disponibles para servicios de swarm, no para contenedores independientes. Para usar esta característica, considera adaptar tu contenedor para que se ejecute como un servicio con una escala de 1.
Las configuraciones son compatibles tanto con servicios de Linux como de Windows.
Soporte en Windows
Docker incluye soporte para configuraciones en contenedores de Windows, pero existen diferencias en las implementaciones que se detallan en los ejemplos a continuación. Ten en cuenta las siguientes diferencias importantes:
Los archivos de configuración con destinos personalizados no se montan directamente en contenedores de Windows, ya que Windows no admite montajes de archivos individuales que no sean directorios. En su lugar, todas las configuraciones de un contenedor se montan en
C:\ProgramData\Docker\internal\configs(un detalle de implementación en el que las aplicaciones no deberían confiar) dentro del contenedor. Se utilizan enlaces simbólicos para apuntar desde allí al destino deseado de la configuración dentro del contenedor. El destino predeterminado esC:\ProgramData\Docker\configs.Al crear un servicio que utiliza contenedores de Windows, no se admiten las opciones para especificar UID, GID y modo para las configuraciones. Las configuraciones solo son accesibles por administradores y usuarios con acceso
systemdentro del contenedor.En Windows, crea o actualiza un servicio utilizando
--credential-speccon el formatoconfig://<config-name>. Esto pasa el archivo de credenciales de gMSA directamente a los nodos antes de que comience el contenedor. No se escriben credenciales de gMSA en el disco de los nodos trabajadores. Para obtener más información, consulta Desplegar servicios en un swarm.
Cómo gestiona Docker las configuraciones
Cuando añades una configuración al swarm, Docker la envía al administrador del swarm a través de una conexión TLS mutua. La configuración se almacena en el registro de Raft, que está cifrado. Todo el registro de Raft se replica en los demás administradores, lo que garantiza para las configuraciones la misma alta disponibilidad que para el resto de los datos de gestión del swarm.
Cuando concedes a un servicio recién creado o en ejecución acceso a una configuración, la configuración se monta como un archivo en el contenedor. La ubicación del punto de montaje dentro del contenedor predeterminada es /<config-name> en contenedores de Linux. En contenedores de Windows, todas las configuraciones se montan en C:\ProgramData\Docker\configs y se crean enlaces simbólicos a la ubicación deseada, que por defecto es C:\<config-name>.
Puedes establecer la propiedad (uid y gid) de la configuración, utilizando el ID numérico o el nombre del usuario o grupo. También puedes especificar los permisos del archivo (mode). Estos ajustes se ignoran en los contenedores de Windows.
- Si no se establece, la configuración pertenece al usuario que ejecuta el comando del contenedor (a menudo
root) y al grupo predeterminado de ese usuario (también a menudoroot). - Si no se establece, la configuración tiene permisos de lectura global (modo
0444), a menos que se establezca unaumaskdentro del contenedor, en cuyo caso el modo se verá afectado por ese valor deumask.
Puedes actualizar un servicio para concederle acceso a configuraciones adicionales o revocar su acceso a una configuración determinada en cualquier momento.
Un nodo solo tiene acceso a las configuraciones si es un administrador de swarm o si está ejecutando tareas de servicio a las que se les ha concedido acceso a la configuración. Cuando una tarea de contenedor deja de ejecutarse, las configuraciones compartidas con ella se desmontan del sistema de archivos en memoria de ese contenedor y se eliminan de la memoria del nodo.
Si un nodo pierde la conectividad con el swarm mientras está ejecutando un contenedor de tareas con acceso a una configuración, el contenedor de tareas seguirá teniendo acceso a sus configuraciones, pero no podrá recibir actualizaciones hasta que el nodo se vuelva a conectar al swarm.
Puedes añadir o inspeccionar una configuración individual en cualquier momento, o listar todas las configuraciones. No puedes eliminar una configuración que un servicio en ejecución esté utilizando. Consulta Rotar una configuración para conocer una forma de eliminar una configuración sin interrumpir los servicios en ejecución.
Para actualizar o revertir configuraciones con mayor comodidad, considera añadir un número de versión o una fecha al nombre de la configuración. Esto se ve facilitado por la posibilidad de controlar el punto de montaje de la configuración dentro de un contenedor determinado.
Para actualizar una pila (stack), realiza los cambios en tu archivo Compose y luego vuelve a ejecutar docker stack deploy -c <new-compose-file> <stack-name>. Si utilizas una nueva configuración en ese archivo, tus servicios comenzarán a usarla. Ten en cuenta que las configuraciones son inmutables, por lo que no puedes cambiar el archivo de un servicio existente. En su lugar, debes crear una nueva configuración para usar un archivo diferente.
Puedes ejecutar docker stack rm para detener la aplicación y retirar la pila. Esto elimina cualquier configuración que haya sido creada por docker stack deploy con el mismo nombre de pila. Esto elimina todas las configuraciones, incluidas las que no están referenciadas por servicios y las que quedan después de un comando docker service update --config-rm.
Más información sobre los comandos docker config
Utiliza estos enlaces para leer sobre comandos específicos o continúa con el ejemplo sobre el uso de configuraciones con un servicio.
Ejemplos
Esta sección incluye ejemplos progresivos que ilustran cómo utilizar las configuraciones de Docker.
NoteEstos ejemplos utilizan un swarm de un solo motor y servicios no escalados para mayor simplicidad. Los ejemplos utilizan contenedores de Linux, pero los contenedores de Windows también admiten configuraciones.
Definir y usar configuraciones en archivos compose
El comando docker stack admite la definición de configuraciones en un archivo Compose. Sin embargo, la clave configs no es compatible con docker compose. Consulta la
referencia del archivo Compose para más detalles.
Ejemplo simple: Primeros pasos con las configuraciones
Este ejemplo simple muestra cómo funcionan las configuraciones en solo unos pocos comandos. Para un ejemplo del mundo real, continúa en Ejemplo avanzado: Usar configuraciones con un servicio Nginx.
Añade una configuración a Docker. El comando
docker config createlee la entrada estándar porque el último argumento, que representa el archivo del cual leer la configuración, está establecido en-.$ echo "This is a config" | docker config create my-config -Crea un servicio
redisy concédele acceso a la configuración. Por defecto, el contenedor puede acceder a la configuración en/my-config, pero puedes personalizar el nombre del archivo en el contenedor utilizando la opcióntarget.$ docker service create --name redis --config my-config redis:alpineVerifica que la tarea se esté ejecutando sin problemas utilizando
docker service ps. Si todo está funcionando, la salida se verá similar a esto:$ docker service ps redis ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS bkna6bpn8r1a redis.1 redis:alpine ip-172-31-46-109 Running Running 8 seconds agoObtén el ID del contenedor de la tarea del servicio
redisutilizandodocker ps, de modo que puedas usardocker container execpara conectarte al contenedor y leer el contenido del archivo de datos de configuración. Este archivo, por defecto, es legible por todos y tiene el mismo nombre que la configuración. El primer comando a continuación ilustra cómo encontrar el ID del contenedor, y el segundo y tercer comando utilizan la autocompletación de la terminal para hacerlo automáticamente.$ docker ps --filter name=redis -q 5cb1c2348a59 $ docker container exec $(docker ps --filter name=redis -q) ls -l /my-config -r--r--r-- 1 root root 12 Jun 5 20:49 my-config $ docker container exec $(docker ps --filter name=redis -q) cat /my-config This is a configIntenta eliminar la configuración. La eliminación fallará porque el servicio
redisestá en ejecución y tiene acceso a la configuración.$ docker config ls ID NAME CREATED UPDATED fzwcfuqjkvo5foqu7ts7ls578 hello 31 minutes ago 31 minutes ago $ docker config rm my-config Error response from daemon: rpc error: code = 3 desc = config 'my-config' is in use by the following service: redisQuita el acceso a la configuración del servicio
redisen ejecución actualizando el servicio.$ docker service update --config-rm my-config redisRepite los pasos 3 y 4 de nuevo, verificando que el servicio ya no tenga acceso a la configuración. El ID del contenedor es diferente porque el comando
service updatevuelve a desplegar el servicio.$ docker container exec -it $(docker ps --filter name=redis -q) cat /my-config cat: can't open '/my-config': No such file or directoryDetén y elimina el servicio, y elimina la configuración de Docker.
$ docker service rm redis $ docker config rm my-config
Ejemplo simple: Usar configuraciones en un servicio de Windows
Este es un ejemplo muy simple que muestra cómo usar configuraciones con un servicio de Microsoft IIS que se ejecuta en Docker para Windows con contenedores de Windows en Microsoft Windows 10. Es un ejemplo sencillo que almacena la página web en una configuración.
Este ejemplo asume que tienes PowerShell instalado.
Guarda el siguiente contenido en un nuevo archivo
index.html.<html lang="en"> <head><title>Hello Docker</title></head> <body> <p>Hello Docker! You have deployed a HTML page.</p> </body> </html>Si aún no lo has hecho, inicializa o únete al swarm.
docker swarm initGuarda el archivo
index.htmlcomo una configuración de swarm llamadahomepage.docker config create homepage index.htmlCrea un servicio IIS y concédele acceso a la configuración
homepage.docker service create --name my-iis --publish published=8000,target=8000 --config src=homepage,target="\inetpub\wwwroot\index.html" microsoft/iis:nanoserverAccede al servicio IIS en
http://localhost:8000/. Debería servir el contenido HTML del primer paso.Elimina el servicio y la configuración.
docker service rm my-iis docker config rm homepage
Ejemplo: Usar una configuración con plantilla
Para crear una configuración en la que el contenido se generará utilizando un motor de plantillas, utiliza el parámetro --template-driver y especifica el nombre del motor como su argumento. La plantilla se renderizará cuando se cree el contenedor.
Guarda el siguiente contenido en un nuevo archivo
index.html.tmpl.<html lang="en"> <head><title>Hello Docker</title></head> <body> <p>Hello {{ env "HELLO" }}! I'm service {{ .Service.Name }}.</p> </body> </html>Guarda el archivo
index.html.tmplcomo una configuración de swarm llamadahomepage. Proporciona el parámetro--template-drivery especificagolangcomo motor de plantillas.$ docker config create --template-driver golang homepage index.html.tmplCrea un servicio que ejecute Nginx y que tenga acceso a la variable de entorno HELLO y a la configuración.
$ docker service create \ --name hello-template \ --env HELLO="Docker" \ --config source=homepage,target=/usr/share/nginx/html/index.html \ --publish published=3000,target=80 \ nginx:alpineVerifica que the servicio esté operativo: que puedas acceder al servidor Nginx y que se esté sirviendo la salida correcta.
$ curl http://0.0.0.0:3000 <html lang="en"> <head><title>Hello Docker</title></head> <body> <p>Hello Docker! I'm service hello-template.</p> </body> </html>
Ejemplo avanzado: Usar configuraciones con un servicio Nginx
Este ejemplo está dividido en dos partes. La primera parte trata sobre la generación del certificado del sitio y no involucra directamente las configuraciones de Docker, pero prepara la segunda parte, donde se almacena y utiliza el certificado del sitio como una serie de secretos y la configuración de Nginx como una configuración de Docker. El ejemplo muestra cómo establecer opciones en la configuración, como la ubicación de destino dentro del contenedor y los permisos del archivo (mode).
Generar el certificado del sitio
Genera una CA raíz y un certificado y clave TLS para tu sitio. Para sitios de producción, es recomendable usar un servicio como Let’s Encrypt para generar el certificado y la clave TLS, pero este ejemplo utiliza herramientas de línea de comandos. Este paso es un poco complicado, pero es solo un paso de configuración para que tengas algo que almacenar como secreto de Docker. Si deseas omitir estos subpasos, puedes usar Let's Encrypt para generar la clave y el certificado del sitio, nombrar los archivos site.key y site.crt, y saltar a Configurar el contenedor Nginx.
Genera una clave raíz.
$ openssl genrsa -out "root-ca.key" 4096Genera un CSR utilizando la clave raíz.
$ openssl req \ -new -key "root-ca.key" \ -out "root-ca.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA'Configura la CA raíz. Edita un nuevo archivo llamado
root-ca.cnfy pega el siguiente contenido en él. Esto restringe la CA raíz para que solo firme certificados de hoja y no CAs intermedias.[root_ca] basicConstraints = critical,CA:TRUE,pathlen:1 keyUsage = critical, nonRepudiation, cRLSign, keyCertSign subjectKeyIdentifier=hashFirma el certificado.
$ openssl x509 -req -days 3650 -in "root-ca.csr" \ -signkey "root-ca.key" -sha256 -out "root-ca.crt" \ -extfile "root-ca.cnf" -extensions \ root_caGenera la clave del sitio.
$ openssl genrsa -out "site.key" 4096Genera el certificado del sitio y fírmalo con la clave del sitio.
$ openssl req -new -key "site.key" -out "site.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'Configura el certificado del sitio. Edita un nuevo archivo llamado
site.cnfy pega el siguiente contenido en él. Esto limita el certificado del sitio para que solo se pueda utilizar para autenticar un servidor y no para firmar otros certificados.[server] authorityKeyIdentifier=keyid,issuer basicConstraints = critical,CA:FALSE extendedKeyUsage=serverAuth keyUsage = critical, digitalSignature, keyEncipherment subjectAltName = DNS:localhost, IP:127.0.0.1 subjectKeyIdentifier=hashFirma el certificado del sitio.
$ openssl x509 -req -days 750 -in "site.csr" -sha256 \ -CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial \ -out "site.crt" -extfile "site.cnf" -extensions serverEl servicio Nginx no necesita los archivos
site.csrysite.cnf, pero los necesitarás si deseas generar un nuevo certificado para el sitio. Protege el archivoroot-ca.key.
Configurar el contenedor Nginx
Produce una configuración de Nginx muy básica que sirva archivos estáticos a través de HTTPS. El certificado y la clave TLS se almacenan como secretos de Docker para que se puedan rotar sin complicaciones.
En el directorio actual, crea un nuevo archivo llamado
site.confcon el siguiente contenido:server { listen 443 ssl; server_name localhost; ssl_certificate /run/secrets/site.crt; ssl_certificate_key /run/secrets/site.key; location / { root /usr/share/nginx/html; index index.html index.htm; } }Crea dos secretos que representen la clave y el certificado. Puedes almacenar cualquier archivo como secreto siempre que sea inferior a 500 KB. Esto te permite desacoplar la clave y el certificado de los servicios que los utilizan. En estos ejemplos, el nombre del secreto y el del archivo son iguales.
$ docker secret create site.key site.key $ docker secret create site.crt site.crtGuarda el archivo
site.confen una configuración de Docker. El primer parámetro es el nombre de la configuración y el segundo parámetro es el archivo del cual leerla.$ docker config create site.conf site.confLista las configuraciones:
$ docker config ls ID NAME CREATED UPDATED 4ory233120ccg7biwvy11gl5z site.conf 4 seconds ago 4 seconds agoCrea un servicio que ejecute Nginx y que tenga acceso a los dos secretos y a la configuración. Establece el modo en
0440para que el archivo solo sea legible por su propietario y el grupo de ese propietario, no por todo el mundo.$ docker service create \ --name nginx \ --secret site.key \ --secret site.crt \ --config source=site.conf,target=/etc/nginx/conf.d/site.conf,mode=0440 \ --publish published=3000,target=443 \ nginx:latest \ sh -c "exec nginx -g 'daemon off;'"Dentro de los contenedores en ejecución, ahora existen los siguientes tres archivos:
/run/secrets/site.key/run/secrets/site.crt/etc/nginx/conf.d/site.conf
Verifica que el servicio Nginx se esté ejecutando.
$ docker service ls ID NAME MODE REPLICAS IMAGE zeskcec62q24 nginx replicated 1/1 nginx:latest $ docker service ps nginx NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS nginx.1.9ls3yo9ugcls nginx:latest moby Running Running 3 minutes agoVerifica que el servicio esté operativo: que puedas acceder al servidor Nginx y que se esté utilizando el certificado TLS correcto.
$ curl --cacert root-ca.crt https://0.0.0.0:3000 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support, refer to <a href="https://nginx.org">nginx.org</a>.<br/> Commercial support is available at <a href="https://www.nginx.com">www.nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>$ openssl s_client -connect 0.0.0.0:3000 -CAfile root-ca.crt CONNECTED(00000003) depth=1 /C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA verify return:1 depth=0 /C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost verify return:1 --- Certificate chain 0 s:/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost i:/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA --- Server certificate -----BEGIN CERTIFICATE----- … -----END CERTIFICATE----- subject=/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost issuer=/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA --- No client certificate CA names sent --- SSL handshake has read 1663 bytes and written 712 bytes --- New, TLSv1/SSLv3, Cipher is AES256-SHA Server public key is 4096 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : AES256-SHA Session-ID: A1A8BF35549C5715648A12FD7B7E3D861539316B03440187D9DA6C2E48822853 Session-ID-ctx: Master-Key: F39D1B12274BA16D3A906F390A61438221E381952E9E1E05D3DD784F0135FB81353DA38C6D5C021CB926E844DFC49FC4 Key-Arg : None Start Time: 1481685096 Timeout : 300 (sec) Verify return code: 0 (ok)A menos que vayas a continuar con el siguiente ejemplo, limpia el entorno después de ejecutar este ejemplo eliminando el servicio
nginxy los secretos y configuraciones almacenados.$ docker service rm nginx $ docker secret rm site.crt site.key $ docker config rm site.conf
Ahora has configurado un servicio Nginx con su configuración desacoplada de su imagen. Podrías ejecutar múltiples sitios con exactamente la misma imagen pero con configuraciones separadas, sin necesidad de construir una imagen personalizada en absoluto.
Ejemplo: Rotar una configuración
Para rotar una configuración, primero guardas una nueva configuración con un nombre diferente al de la que está en uso. Luego vuelves a desplegar el servicio, eliminando la configuración anterior y añadiendo la nueva en el mismo punto de montaje dentro del contenedor. Este ejemplo se basa en el anterior al rotar el archivo de configuración site.conf.
Edita el archivo
site.conflocalmente. Añadeindex.phpa la líneaindexy guarda el archivo.server { listen 443 ssl; server_name localhost; ssl_certificate /run/secrets/site.crt; ssl_certificate_key /run/secrets/site.key; location / { root /usr/share/nginx/html; index index.html index.htm index.php; } }Crea una nueva configuración de Docker utilizando el nuevo
site.conf, llamadasite-v2.conf.$ docker config create site-v2.conf site.confActualiza el servicio
nginxpara usar la nueva configuración en lugar de la anterior.$ docker service update \ --config-rm site.conf \ --config-add source=site-v2.conf,target=/etc/nginx/conf.d/site.conf,mode=0440 \ nginxVerifica que el servicio
nginxse haya vuelto a desplegar por completo utilizandodocker service ps nginx. Una vez hecho esto, puedes eliminar la antigua configuraciónsite.conf.$ docker config rm site.confPara limpiar, puedes eliminar el servicio
nginx, así como los secretos y las configuraciones.$ docker service rm nginx $ docker secret rm site.crt site.key $ docker config rm site-v2.conf
Ahora has actualizado la configuración de tu servicio nginx sin necesidad de volver a construir su imagen.