Compartir comentarios
Las respuestas se generan en base a la documentación.

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).

Note

Las 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 es C:\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 system dentro del contenedor.

  • En Windows, crea o actualiza un servicio utilizando --credential-spec con el formato config://<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 menudo root).
  • Si no se establece, la configuración tiene permisos de lectura global (modo 0444), a menos que se establezca una umask dentro del contenedor, en cuyo caso el modo se verá afectado por ese valor de umask.

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.

Note

Estos 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.

  1. Añade una configuración a Docker. El comando docker config create lee 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 -
    
  2. Crea un servicio redis y 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ón target .

    $ docker service create --name redis --config my-config redis:alpine
    
  3. Verifica 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 ago
    
  4. Obtén el ID del contenedor de la tarea del servicio redis utilizando docker ps, de modo que puedas usar docker container exec para 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 config
    
  5. Intenta eliminar la configuración. La eliminación fallará porque el servicio redis está 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: redis
    
  6. Quita el acceso a la configuración del servicio redis en ejecución actualizando el servicio.

    $ docker service update --config-rm my-config redis
    
  7. Repite 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 update vuelve 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 directory
    
  8. Deté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.

  1. 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>
  2. Si aún no lo has hecho, inicializa o únete al swarm.

    docker swarm init
  3. Guarda el archivo index.html como una configuración de swarm llamada homepage.

    docker config create homepage index.html
  4. Crea 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:nanoserver
  5. Accede al servicio IIS en http://localhost:8000/. Debería servir el contenido HTML del primer paso.

  6. 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.

  1. 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>
  2. Guarda el archivo index.html.tmpl como una configuración de swarm llamada homepage. Proporciona el parámetro --template-driver y especifica golang como motor de plantillas.

    $ docker config create --template-driver golang homepage index.html.tmpl
    
  3. Crea 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:alpine
    
  4. Verifica 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.

  1. Genera una clave raíz.

    $ openssl genrsa -out "root-ca.key" 4096
    
  2. Genera 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'
    
  3. Configura la CA raíz. Edita un nuevo archivo llamado root-ca.cnf y 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=hash
  4. Firma 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_ca
    
  5. Genera la clave del sitio.

    $ openssl genrsa -out "site.key" 4096
    
  6. Genera 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'
    
  7. Configura el certificado del sitio. Edita un nuevo archivo llamado site.cnf y 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=hash
  8. Firma 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 server
    
  9. El servicio Nginx no necesita los archivos site.csr y site.cnf, pero los necesitarás si deseas generar un nuevo certificado para el sitio. Protege el archivo root-ca.key.

Configurar el contenedor Nginx

  1. 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.conf con 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;
        }
    }
  2. 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.crt
    
  3. Guarda el archivo site.conf en 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.conf
    

    Lista las configuraciones:

    $ docker config ls
    
    ID                          NAME                CREATED             UPDATED
    4ory233120ccg7biwvy11gl5z   site.conf           4 seconds ago       4 seconds ago
    
  4. Crea un servicio que ejecute Nginx y que tenga acceso a los dos secretos y a la configuración. Establece el modo en 0440 para 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
  5. 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 ago
    
  6. Verifica 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)
    
  7. A menos que vayas a continuar con el siguiente ejemplo, limpia el entorno después de ejecutar este ejemplo eliminando el servicio nginx y 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.

  1. Edita el archivo site.conf localmente. Añade index.php a la línea index y 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;
        }
    }
  2. Crea una nueva configuración de Docker utilizando el nuevo site.conf, llamada site-v2.conf.

    $ docker config create site-v2.conf site.conf
  3. Actualiza el servicio nginx para 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 \
      nginx
    
  4. Verifica que el servicio nginx se haya vuelto a desplegar por completo utilizando docker service ps nginx. Una vez hecho esto, puedes eliminar la antigua configuración site.conf.

    $ docker config rm site.conf
    
  5. Para 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.