使用 Docker Config 存储配置数据

关于 config

Docker swarm 服务配置允许您存储非敏感信息、 例如配置文件、服务镜像外部或正在运行的容器。 这使您可以使镜像尽可能通用,而无需 将配置文件绑定到容器中或使用环境变量。

配置的工作方式与 secret 类似,不同之处在于它们是 未静态加密,直接挂载到容器的文件系统中 不使用 RAM 磁盘。可以在 Service 中添加或删除 Configs: 任何时候,服务都可以共享一个配置。您甚至可以在 与环境变量或标签结合使用,以获得最大的灵活性。 Config 值可以是通用字符串或二进制内容(最大 500 kb)。

注意

Docker 配置仅适用于 swarm 服务,而不适用于 独立容器。要使用此功能,请考虑调整您的容器 作为规模为 1 的服务运行。

Linux 和 Windows 服务都支持配置。

Windows 支持

Docker 包括对 Windows 容器上的配置的支持,但存在差异 在实施中,这些实施在下面的示例中进行了调用。保留 请注意以下显著差异:

  • 具有自定义目标的配置文件不会直接绑定到 Windows 中 containers 的 S 实例,因为 Windows 不支持非目录文件绑定挂载。 相反,容器的配置都挂载在 (实现细节 应用程序不应依赖)。符号 链接用于从那里指向 config 的所需目标 容器。默认目标是 。C:\ProgramData\Docker\internal\configsC:\ProgramData\Docker\configs

  • 创建使用 Windows 容器的服务时,要指定 配置不支持 UID、GID 和 mode。配置目前仅 管理员和在 容器。system

  • 在 Windows 上,使用 格式创建或更新服务。这将传递 gMSA 凭据文件 直接发送到节点。不写入 gMSA 凭据 复制到 Worker 节点上的磁盘。有关更多信息,请参阅将服务部署到 swarm--credential-specconfig://<config-name>

Docker 如何管理配置

当您将配置添加到 swarm 时,Docker 会将配置发送到 swarm 管理器 通过双向 TLS 连接。该配置存储在 Raft log 中,即 加密。整个 Raft 日志在其他 manager 之间复制,确保 配置与 Swarm 的其余部分具有相同的高可用性保证 管理数据。

当您向新创建或正在运行的服务授予对配置的访问权限时,配置 作为文件挂载到容器中。挂载点在 容器默认为 在 Linux 容器中。在 Windows 中 containers 中,配置都挂载到 和 将创建到所需位置的符号链接,该位置默认为 。/<config-name>C:\ProgramData\Docker\configsC:\<config-name>

您可以使用 数字 ID 或用户或组的名称。您还可以指定文件 权限 ()。对于 Windows 容器,这些设置将被忽略。uidgidmode

  • 如果未设置,则配置由运行容器的用户拥有 command (经常 ) 和该用户的默认组 (也经常 )。rootroot
  • 如果未设置,则配置具有全局可读权限(模式),除非在容器中设置了 a,在这种情况下,模式受 那个值。0444umaskumask

您可以更新服务以授予它访问其他配置的权限或撤销其 随时访问给定的配置。

仅当节点是 swarm manager 或 swarm manager 时,节点才能访问配置 运行已授予配置访问权限的服务任务。当 容器任务停止运行,则共享给它的配置将从 in-memory 文件系统中,并从节点的内存中刷新。

如果节点在运行任务容器时失去与 swarm 的连接 通过访问配置,任务容器仍然可以访问其配置,但 在节点重新连接到 Swarm 之前,无法接收更新。

您可以随时添加或检查单个配置,或列出所有配置 configs 的 Configs。您无法删除正在运行的服务所在的配置 用。请参阅 轮换配置 以了解 在不中断正在运行的服务的情况下删除配置。

要更轻松地更新或回滚配置,请考虑添加版本 number 或 date 添加到配置名称中。通过控制能力,这变得更加容易 给定容器中配置的挂载点。

要更新堆栈,请更改 Compose 文件,然后重新运行 .如果您在 该文件,您的服务将开始使用它们。请记住,配置 是不可变的,因此您无法更改现有服务的文件。 相反,您可以创建一个新配置来使用不同的文件docker stack deploy -c <new-compose-file> <stack-name>

您可以运行以停止应用程序并关闭堆栈。这 删除 使用同一堆栈创建的任何配置 名字。这将删除所有配置,包括那些未被 services 和 在 .docker stack rmdocker stack deploydocker service update --config-rm

阅读有关 docker config 命令的更多信息

使用这些链接阅读有关特定命令的信息,或继续阅读有关将配置与服务结合使用的示例

例子

本节包含一些分级示例,这些示例说明了如何使用 Docker 配置。

注意

这些示例使用单引擎 swarm 和未扩展的服务 单纯。这些示例使用 Linux 容器,但也使用 Windows 容器 支持配置。

在 compose 文件中定义和使用配置

该命令支持在 Compose 文件中定义配置。 但是,不支持该密钥。有关详细信息,请参阅 Compose file 参考docker stackconfigsdocker compose

简单示例:开始使用 config

这个简单的例子展示了配置是如何在几个命令中工作的。对于 实际示例,请继续 高级示例:将配置与 Nginx 服务一起使用

  1. 向 Docker 添加配置。该命令读取 standard input,因为最后一个参数(表示要读取 config from 设置为 .docker config create-

    $ echo "This is a config" | docker config create my-config -
    
  2. 创建服务并授予其对配置的访问权限。默认情况下, 容器可以在 ,但 您可以使用该选项自定义容器上的文件名。redis/my-configtarget

    $ docker service create --name redis --config my-config redis:alpine
    
  3. 使用 验证任务是否正在运行且没有问题。如果 一切正常,输出看起来类似于:docker service ps

    $ 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. 使用 获取服务任务容器的 ID,以便 您可以使用 连接到容器并读取内容 的配置文件中,它默认为 all 可读,并且具有 与配置的名称相同。下面的第一个命令说明了 如何找到容器 ID,第二个和第三个命令使用 shell completion 自动执行此操作。redisdocker psdocker container exec

    $ 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. 尝试删除配置。删除失败,因为该服务是 正在运行并有权访问 config。redis

    
    $ 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. 通过更新 服务。redis

    $ docker service update --config-rm my-config redis
    
  7. 再次重复步骤 3 和 4,验证该服务是否不再具有访问权限 添加到配置中。容器 ID 不同,因为该命令会重新部署服务。service update

    $ 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. 停止并删除服务,然后从 Docker 中删除配置。

    $ docker service rm redis
    
    $ docker config rm my-config
    

简单示例:在 Windows 服务中使用配置

这是一个非常简单的示例,它展示了如何在 Microsoft 中使用配置。 在 Docker for Windows 上运行的 IIS 服务在 上运行 Windows 容器 Microsoft Windows 10 的。这是一个将网页存储在 config 中的天真示例。

此示例假定您已安装 PowerShell。

  1. 将以下内容保存到 new file 中。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. 如果尚未初始化或加入 swarm,请初始化或加入 swarm。

    docker swarm init
  3. 将文件另存为名为 的 swarm 配置。index.htmlhomepage

    docker config create homepage index.html
  4. 创建 IIS 服务并授予其对配置的访问权限。homepage

    docker service create
        --name my-iis
        --publish published=8000,target=8000
        --config src=homepage,target="\inetpub\wwwroot\index.html"
        microsoft/iis:nanoserver
  5. 访问 IIS 服务。它应该服务 第一步中的 HTML 内容。http://localhost:8000/

  6. 删除服务和配置。

    docker service rm my-iis
    
    docker config rm homepage

示例:使用模板化配置

要创建将使用 template engine 中,使用参数并指定 engine name 作为其参数。创建容器时,将呈现模板。--template-driver

  1. 将以下内容保存到 new file 中。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. 将文件另存为名为 的 swarm 配置。提供 参数并指定为模板引擎。index.html.tmplhomepage--template-drivergolang

    $ docker config create --template-driver golang homepage index.html.tmpl
    
  3. 创建运行 Nginx 并有权访问环境变量的服务 HELLO 和配置。

    $ 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. 验证服务是否正常运行:您可以访问 Nginx 服务器,并且 正在提供正确的输出。

    $ 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>
    

高级示例:将 config 与 Nginx 服务一起使用

此示例分为两部分。第一部分是关于生成 站点证书,根本不直接涉及 Docker 配置,但 它设置了第二个部分,用于存储 并使用站点证书作为一系列 secret 和 Nginx 配置 作为配置。该示例展示了如何在配置上设置选项,例如 目标位置和文件权限 ()。mode

生成站点证书

为站点生成根 CA 和 TLS 证书和密钥。用于生产 sites 中,您可能希望使用服务,例如生成 TLS 证书和密钥,但此示例使用命令行工具。此步骤 有点复杂,但只是一个设置步骤,以便您拥有 作为 Docker 密钥存储的内容。如果要跳过这些子步骤, 您可以使用 Let's Encrypt 来 生成站点密钥和证书,将文件命名为 和 ,然后跳至配置 Nginx 容器Let’s Encryptsite.keysite.crt

  1. 生成根密钥。

    $ openssl genrsa -out "root-ca.key" 4096
    
  2. 使用根密钥生成 CSR。

    $ 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. 配置根 CA。编辑一个名为 and paste 的新文件 以下内容放入其中。这会将根 CA 限制为仅签名 叶证书,而不是中间 CA。root-ca.cnf

    [root_ca]
    basicConstraints = critical,CA:TRUE,pathlen:1
    keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
    subjectKeyIdentifier=hash
  4. 签署证书。

    $ 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. 生成站点密钥。

    $ openssl genrsa -out "site.key" 4096
    
  6. 生成站点证书并使用站点密钥对其进行签名。

    $ openssl req -new -key "site.key" -out "site.csr" -sha256 \
              -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
    
  7. 配置站点证书。编辑一个名为 和 的新文件 将以下内容粘贴到其中。这会限制网站 certificate 的 ID 证书,使其只能用于对服务器进行身份验证,并且 不能用于对证书进行签名。site.cnf

    [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. 对站点证书进行签名。

    $ 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. Nginx 服务不需要 and 文件,但 如果要生成新的站点证书,则需要它们。保护 文件。site.csrsite.cnfroot-ca.key

配置 Nginx 容器

  1. 生成一个非常基本的 Nginx 配置,通过 HTTPS 提供静态文件。 TLS 证书和密钥存储为 Docker 机密,以便它们 可以轻松旋转。

    在当前目录中,创建一个名为 以下内容:site.conf

    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. 创建两个密钥,分别表示密钥和证书。您可以存储 任何文件作为密钥,只要它小于 500 KB。这允许您 将密钥和证书与使用它们的服务分离。 在这些示例中,密钥名称和文件名相同。

    $ docker secret create site.key site.key
    
    $ docker secret create site.crt site.crt
    
  3. 将文件保存在 Docker 配置中。第一个参数是 name 的配置,第二个参数是要从中读取它的文件。site.conf

    $ docker config create site.conf site.conf
    

    列出配置:

    $ docker config ls
    
    ID                          NAME                CREATED             UPDATED
    4ory233120ccg7biwvy11gl5z   site.conf           4 seconds ago       4 seconds ago
    
  4. 创建一个运行 Nginx 的服务,并有权访问这两个 secret 和 config。将 mode 设置为 ,以便文件只能由其 owner 和该 owner's group,而不是 world。0440

    $ 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;'"
    

    在正在运行的容器中,现在存在以下三个文件:

    • /run/secrets/site.key
    • /run/secrets/site.crt
    • /etc/nginx/conf.d/site.conf
  5. 验证 Nginx 服务是否正在运行。

    $ 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. 验证服务是否正常运行:您可以访问 Nginx 服务器,并且正在使用正确的 TLS 证书。

    $ 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. 除非您要继续下一个示例,否则请在运行 此示例通过删除服务和存储的密钥以及 config。nginx

    $ docker service rm nginx
    
    $ docker secret rm site.crt site.key
    
    $ docker config rm site.conf
    

您现在已经配置了一个 Nginx 服务,其配置与 它的形象。您可以使用完全相同的图片运行多个网站,但 单独的配置,根本不需要构建自定义镜像。

示例:旋转配置

要轮换配置,您首先要保存一个名称与 一个当前正在使用的。然后,您重新部署该服务,删除旧的 config 并在容器内的同一挂载点添加新配置。 此示例通过旋转配置文件构建在上一个示例的基础上。site.conf

  1. 在本地编辑文件。Add 添加到该行,然后 保存文件。site.confindex.phpindex

    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. 使用名为 的新 创建新的 Docker 配置。site.confsite-v2.conf

    $ docker config create site-v2.conf site.conf
  3. 更新服务以使用新配置而不是旧配置。nginx

    $ docker service update \
      --config-rm site.conf \
      --config-add source=site-v2.conf,target=/etc/nginx/conf.d/site.conf,mode=0440 \
      nginx
    
  4. 使用 验证服务是否已完全重新部署。如果是这样,您可以删除旧配置。nginxdocker service ps nginxsite.conf

    $ docker config rm site.conf
    
  5. 要进行清理,您可以删除该服务,以及 secret 和 configs 的 Configs。nginx

    $ docker service rm nginx
    
    $ docker secret rm site.crt site.key
    
    $ docker config rm site-v2.conf
    

您现在已经更新了服务的配置,而无需 重建其镜像。nginx