使用 Docker Config 存储配置数据

关于 config

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

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

注意

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

Linux 和 Windows 服务都支持配置。

Windows 支持

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

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

  • 创建使用 Windows 容器的服务时,要指定 配置不支持 UID、GID 和 mode。配置目前仅 管理员和用户可通过以下方式访问system访问权限 容器。

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

Docker 如何管理配置

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

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

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

  • 如果未设置,则配置由运行容器的用户拥有 命令(通常是root)和该用户的默认组(通常也经常root).
  • 如果未设置,则配置具有全局可读权限(模式0444),除非umask在容器内设置,在这种情况下,模式会受到 那umask价值。

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

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

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

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

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

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

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

阅读更多docker config命令

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

例子

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

注意

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

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

docker stack命令支持在 Compose 文件中定义配置。 但是,configs不支持 keydocker compose.有关详细信息,请参阅 Compose file 参考

简单示例:开始使用 config

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

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

    $ echo "This is a config" | docker config create my-config -
    
  2. 创建一个redis服务并授予其访问配置的权限。默认情况下, 容器可以在/my-config但 您可以使用target选择。

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

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

    
    $ 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. 将以下内容保存到新文件中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. 保存index.html文件作为名为homepage.

    docker config create homepage index.html
  4. 创建 IIS 服务并授予其访问homepageconfig。

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

  6. 删除服务和配置。

    docker service rm my-iis
    
    docker config rm homepage

示例:使用模板化配置

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

  1. 将以下内容保存到新文件中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. 保存index.html.tmpl文件作为名为homepage.提供 参数--template-driver并指定golang作为模板引擎。

    $ 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 中,您可能需要使用Let’s Encrypt要生成 TLS 证书和密钥,但此示例使用命令行工具。此步骤 有点复杂,但只是一个设置步骤,以便您拥有 作为 Docker 密钥存储的内容。如果要跳过这些子步骤, 您可以使用 Let's Encrypt 来 生成站点密钥和证书,为文件命名site.keysite.crt,然后跳至配置 Nginx 容器

  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。编辑一个名为root-ca.cnf和粘贴 以下内容放入其中。这会将根 CA 限制为仅签名 叶证书,而不是中间 CA。

    [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. 配置站点证书。编辑一个名为site.cnf和 将以下内容粘贴到其中。这会限制网站 certificate 的 ID 证书,使其只能用于对服务器进行身份验证,并且 不能用于对证书进行签名。

    [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. site.csrsite.cnf文件不需要 Nginx 服务,但 如果要生成新的站点证书,则需要它们。保护 这root-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. 保存site.conf文件。第一个参数是 name 的配置,第二个参数是要从中读取它的文件。

    $ 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 设置为0440以便文件只能由其 owner 和该 owner's group,而不是 world。

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

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

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

示例:旋转配置

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

  1. 编辑site.conf文件。加index.phpindexline 和 保存文件。

    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. 使用新的site.confsite-v2.conf.

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

    $ docker service update \
      --config-rm site.conf \
      --config-add source=site-v2.conf,target=/etc/nginx/conf.d/site.conf,mode=0440 \
      nginx
    
  4. 验证nginx服务已完全重新部署,使用docker service ps nginx.当它出现时,您可以删除旧的site.confconfig。

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

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

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