summaryrefslogtreecommitdiff
path: root/devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html')
-rw-r--r--devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html236
1 files changed, 236 insertions, 0 deletions
diff --git a/devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html b/devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html
new file mode 100644
index 00000000..913b4ce8
--- /dev/null
+++ b/devdocs/docker/engine%2Fswarm%2Fconfigs%2Findex.html
@@ -0,0 +1,236 @@
+<h1>Store configuration data using Docker Configs</h1>
+
+<h2 id="about-configs">About configs</h2> <p>Docker swarm service configs allow you to store non-sensitive information, such as configuration files, outside a service’s image or running containers. This allows you to keep your images as generic as possible, without the need to bind-mount configuration files into the containers or use environment variables.</p> <p>Configs operate in a similar way to <a href="../secrets/index">secrets</a>, except that they are not encrypted at rest and are mounted directly into the container’s filesystem without the use of RAM disks. Configs can be added or removed from a service at any time, and services can share a config. You can even use configs in conjunction with environment variables or labels, for maximum flexibility. Config values can be generic strings or binary content (up to 500 kb in size).</p> <blockquote> <p><strong>Note</strong>: Docker configs are only available to swarm services, not to standalone containers. To use this feature, consider adapting your container to run as a service with a scale of 1.</p> </blockquote> <p>Configs are supported on both Linux and Windows services.</p> <h3 id="windows-support">Windows support</h3> <p>Docker includes support for configs on Windows containers, but there are differences in the implementations, which are called out in the examples below. Keep the following notable differences in mind:</p> <ul> <li> <p>Config files with custom targets are not directly bind-mounted into Windows containers, since Windows does not support non-directory file bind-mounts. Instead, configs for a container are all mounted in <code class="language-plaintext highlighter-rouge">C:\ProgramData\Docker\internal\configs</code> (an implementation detail which should not be relied upon by applications) within the container. Symbolic links are used to point from there to the desired target of the config within the container. The default target is <code class="language-plaintext highlighter-rouge">C:\ProgramData\Docker\configs</code>.</p> </li> <li> <p>When creating a service which uses Windows containers, the options to specify UID, GID, and mode are not supported for configs. Configs are currently only accessible by administrators and users with <code class="language-plaintext highlighter-rouge">system</code> access within the container.</p> </li> <li> <p>On Windows, create or update a service using <code class="language-plaintext highlighter-rouge">--credential-spec</code> with the <code class="language-plaintext highlighter-rouge">config://&lt;config-name&gt;</code> format. This passes the gMSA credentials file directly to nodes before a container starts. No gMSA credentials are written to disk on worker nodes. For more information, refer to <a href="../services/index#gmsa-for-swarm">Deploy services to a swarm</a>.</p> </li> </ul> <h2 id="how-docker-manages-configs">How Docker manages configs</h2> <p>When you add a config to the swarm, Docker sends the config to the swarm manager over a mutual TLS connection. The config is stored in the Raft log, which is encrypted. The entire Raft log is replicated across the other managers, ensuring the same high availability guarantees for configs as for the rest of the swarm management data.</p> <p>When you grant a newly-created or running service access to a config, the config is mounted as a file in the container. The location of the mount point within the container defaults to <code class="language-plaintext highlighter-rouge">/&lt;config-name&gt;</code> in Linux containers. In Windows containers, configs are all mounted into <code class="language-plaintext highlighter-rouge">C:\ProgramData\Docker\configs</code> and symbolic links are created to the desired location, which defaults to <code class="language-plaintext highlighter-rouge">C:\&lt;config-name&gt;</code>.</p> <p>You can set the ownership (<code class="language-plaintext highlighter-rouge">uid</code> and <code class="language-plaintext highlighter-rouge">gid</code>) for the config, using either the numerical ID or the name of the user or group. You can also specify the file permissions (<code class="language-plaintext highlighter-rouge">mode</code>). These settings are ignored for Windows containers.</p> <ul> <li>If not set, the config is owned by the user running the container command (often <code class="language-plaintext highlighter-rouge">root</code>) and that user’s default group (also often <code class="language-plaintext highlighter-rouge">root</code>).</li> <li>If not set, the config has world-readable permissions (mode <code class="language-plaintext highlighter-rouge">0444</code>), unless a <code class="language-plaintext highlighter-rouge">umask</code> is set within the container, in which case the mode is impacted by that <code class="language-plaintext highlighter-rouge">umask</code> value.</li> </ul> <p>You can update a service to grant it access to additional configs or revoke its access to a given config at any time.</p> <p>A node only has access to configs if the node is a swarm manager or if it is running service tasks which have been granted access to the config. When a container task stops running, the configs shared to it are unmounted from the in-memory filesystem for that container and flushed from the node’s memory.</p> <p>If a node loses connectivity to the swarm while it is running a task container with access to a config, the task container still has access to its configs, but cannot receive updates until the node reconnects to the swarm.</p> <p>You can add or inspect an individual config at any time, or list all configs. You cannot remove a config that a running service is using. See <a href="index#example-rotate-a-config">Rotate a config</a> for a way to remove a config without disrupting running services.</p> <p>To update or roll back configs more easily, consider adding a version number or date to the config name. This is made easier by the ability to control the mount point of the config within a given container.</p> <p>To update a stack, make changes to your Compose file, then re-run <code class="language-plaintext highlighter-rouge">docker stack deploy -c &lt;new-compose-file&gt; &lt;stack-name&gt;</code>. If you use a new config in that file, your services start using them. Keep in mind that configurations are immutable, so you can’t change the file for an existing service. Instead, you create a new config to use a different file</p> <p>You can run <code class="language-plaintext highlighter-rouge">docker stack rm</code> to stop the app and take down the stack. This removes any config that was created by <code class="language-plaintext highlighter-rouge">docker stack deploy</code> with the same stack name. This removes <em>all</em> configs, including those not referenced by services and those remaining after a <code class="language-plaintext highlighter-rouge">docker service update --config-rm</code>.</p> <h2 id="read-more-about-docker-config-commands">Read more about <code class="language-plaintext highlighter-rouge">docker config</code> commands</h2> <p>Use these links to read about specific commands, or continue to the <a href="#advanced-example-use-configs-with-a-nginx-service">example about using configs with a service</a>.</p> <ul> <li><a href="../../reference/commandline/config_create/index"><code class="language-plaintext highlighter-rouge">docker config create</code></a></li> <li><a href="../../reference/commandline/config_inspect/index"><code class="language-plaintext highlighter-rouge">docker config inspect</code></a></li> <li><a href="../../reference/commandline/config_ls/index"><code class="language-plaintext highlighter-rouge">docker config ls</code></a></li> <li><a href="../../reference/commandline/config_rm/index"><code class="language-plaintext highlighter-rouge">docker config rm</code></a></li> </ul> <h2 id="examples">Examples</h2> <p>This section includes graduated examples which illustrate how to use Docker configs.</p> <blockquote> <p><strong>Note</strong>: These examples use a single-Engine swarm and unscaled services for simplicity. The examples use Linux containers, but Windows containers also support configs.</p> </blockquote> <h3 id="defining-and-using-configs-in-compose-files">Defining and using configs in compose files</h3> <p>The <code class="language-plaintext highlighter-rouge">docker stack</code> command supports defining configs in a Compose file. However, the <code class="language-plaintext highlighter-rouge">configs</code> key is not supported for <code class="language-plaintext highlighter-rouge">docker compose</code>. See <a href="../../../compose/compose-file/compose-file-v3/index#configs">the Compose file reference</a> for details.</p> <h3 id="simple-example-get-started-with-configs">Simple example: Get started with configs</h3> <p>This simple example shows how configs work in just a few commands. For a real-world example, continue to <a href="#advanced-example-use-configs-with-a-nginx-service">Advanced example: Use configs with a Nginx service</a>.</p> <ol> <li> <p>Add a config to Docker. The <code class="language-plaintext highlighter-rouge">docker config create</code> command reads standard input because the last argument, which represents the file to read the config from, is set to <code class="language-plaintext highlighter-rouge">-</code>.</p> <div class="highlight"><pre class="highlight" data-language="">$ echo "This is a config" | docker config create my-config -
+</pre></div> </li> <li> <p>Create a <code class="language-plaintext highlighter-rouge">redis</code> service and grant it access to the config. By default, the container can access the config at <code class="language-plaintext highlighter-rouge">/my-config</code>, but you can customize the file name on the container using the <code class="language-plaintext highlighter-rouge">target</code> option.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service create --name redis --config my-config redis:alpine
+</pre></div> </li> <li> <p>Verify that the task is running without issues using <code class="language-plaintext highlighter-rouge">docker service ps</code>. If everything is working, the output looks similar to this:</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>Get the ID of the <code class="language-plaintext highlighter-rouge">redis</code> service task container using <code class="language-plaintext highlighter-rouge">docker ps</code>, so that you can use <code class="language-plaintext highlighter-rouge">docker container exec</code> to connect to the container and read the contents of the config data file, which defaults to being readable by all and has the same name as the name of the config. The first command below illustrates how to find the container ID, and the second and third commands use shell completion to do this automatically.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>Try removing the config. The removal fails because the <code class="language-plaintext highlighter-rouge">redis</code> service is running and has access to the config.</p> <div class="highlight"><pre class="highlight" data-language="">
+$ 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
+</pre></div> </li> <li> <p>Remove access to the config from the running <code class="language-plaintext highlighter-rouge">redis</code> service by updating the service.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service update --config-rm my-config redis
+</pre></div> </li> <li> <p>Repeat steps 3 and 4 again, verifying that the service no longer has access to the config. The container ID is different, because the <code class="language-plaintext highlighter-rouge">service update</code> command redeploys the service.</p> <pre>$ docker container exec -it $(docker ps --filter name=redis -q) cat /my-config
+
+cat: can't open '/my-config': No such file or directory
+</pre> </li> <li> <p>Stop and remove the service, and remove the config from Docker.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service rm redis
+
+$ docker config rm my-config
+</pre></div> </li> </ol> <h3 id="simple-example-use-configs-in-a-windows-service">Simple example: Use configs in a Windows service</h3> <p>This is a very simple example which shows how to use configs with a Microsoft IIS service running on Docker for Windows running Windows containers on Microsoft Windows 10. It is a naive example that stores the webpage in a config.</p> <p>This example assumes that you have PowerShell installed.</p> <ol> <li> <p>Save the following into a new file <code class="language-plaintext highlighter-rouge">index.html</code>.</p> <div class="highlight"><pre class="highlight" data-language="">&lt;html lang="en"&gt;
+ &lt;head&gt;&lt;title&gt;Hello Docker&lt;/title&gt;&lt;/head&gt;
+ &lt;body&gt;
+ &lt;p&gt;Hello Docker! You have deployed a HTML page.&lt;/p&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre></div> </li> <li> <p>If you have not already done so, initialize or join the swarm.</p> <div class="highlight"><pre class="highlight" data-language="">docker swarm init
+</pre></div> </li> <li> <p>Save the <code class="language-plaintext highlighter-rouge">index.html</code> file as a swarm config named <code class="language-plaintext highlighter-rouge">homepage</code>.</p> <div class="highlight"><pre class="highlight" data-language="">docker config create homepage index.html
+</pre></div> </li> <li> <p>Create an IIS service and grant it access to the <code class="language-plaintext highlighter-rouge">homepage</code> config.</p> <div class="highlight"><pre class="highlight" data-language="">docker service create
+ --name my-iis
+ --publish published=8000,target=8000
+ --config src=homepage,target="\inetpub\wwwroot\index.html"
+ microsoft/iis:nanoserver
+</pre></div> </li> <li> <p>Access the IIS service at <code class="language-plaintext highlighter-rouge">http://localhost:8000/</code>. It should serve the HTML content from the first step.</p> </li> <li> <p>Remove the service and the config.</p> <div class="highlight"><pre class="highlight" data-language="">docker service rm my-iis
+
+docker config rm homepage
+</pre></div> </li> </ol> <h3 id="example-use-a-templated-config">Example: Use a templated config</h3> <p>To create a configuration in which the content will be generated using a template engine, use the <code class="language-plaintext highlighter-rouge">--template-driver</code> parameter and specify the engine name as its argument. The template will be rendered when container is created.</p> <ol> <li> <p>Save the following into a new file <code class="language-plaintext highlighter-rouge">index.html.tmpl</code>.</p> <div class="highlight"><pre class="highlight" data-language="">&lt;html lang="en"&gt;
+ &lt;head&gt;&lt;title&gt;Hello Docker&lt;/title&gt;&lt;/head&gt;
+ &lt;body&gt;
+ &lt;p&gt;Hello {{ env "HELLO" }}! I'm service {{ .Service.Name }}.&lt;/p&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre></div> </li> <li> <p>Save the <code class="language-plaintext highlighter-rouge">index.html.tmpl</code> file as a swarm config named <code class="language-plaintext highlighter-rouge">homepage</code>. Provide parameter <code class="language-plaintext highlighter-rouge">--template-driver</code> and specify <code class="language-plaintext highlighter-rouge">golang</code> as template engine.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker config create --template-driver golang homepage index.html.tmpl
+</pre></div> </li> <li> <p>Create a service that runs Nginx and has access to the environment variable HELLO and to the config.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>Verify that the service is operational: you can reach the Nginx server, and that the correct output is being served.</p> <div class="highlight"><pre class="highlight" data-language="">$ curl http://0.0.0.0:3000
+
+&lt;html lang="en"&gt;
+ &lt;head&gt;&lt;title&gt;Hello Docker&lt;/title&gt;&lt;/head&gt;
+ &lt;body&gt;
+ &lt;p&gt;Hello Docker! I'm service hello-template.&lt;/p&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre></div> </li> </ol> <h3 id="advanced-example-use-configs-with-a-nginx-service">Advanced example: Use configs with a Nginx service</h3> <p>This example is divided into two parts. <a href="#generate-the-site-certificate">The first part</a> is all about generating the site certificate and does not directly involve Docker configs at all, but it sets up <a href="#configure-the-nginx-container">the second part</a>, where you store and use the site certificate as a series of secrets and the Nginx configuration as a config. The example shows how to set options on the config, such as the target location within the container and the file permissions (<code class="language-plaintext highlighter-rouge">mode</code>).</p> <h4 id="generate-the-site-certificate">Generate the site certificate</h4> <p>Generate a root CA and TLS certificate and key for your site. For production sites, you may want to use a service such as <code class="language-plaintext highlighter-rouge">Let’s Encrypt</code> to generate the TLS certificate and key, but this example uses command-line tools. This step is a little complicated, but is only a set-up step so that you have something to store as a Docker secret. If you want to skip these sub-steps, you can <a href="https://letsencrypt.org/getting-started/">use Let’s Encrypt</a> to generate the site key and certificate, name the files <code class="language-plaintext highlighter-rouge">site.key</code> and <code class="language-plaintext highlighter-rouge">site.crt</code>, and skip to <a href="#configure-the-nginx-container">Configure the Nginx container</a>.</p> <ol> <li> <p>Generate a root key.</p> <div class="highlight"><pre class="highlight" data-language="">$ openssl genrsa -out "root-ca.key" 4096
+</pre></div> </li> <li> <p>Generate a CSR using the root key.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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'
+</pre></div> </li> <li> <p>Configure the root CA. Edit a new file called <code class="language-plaintext highlighter-rouge">root-ca.cnf</code> and paste the following contents into it. This constrains the root CA to only sign leaf certificates and not intermediate CAs.</p> <pre>[root_ca]
+basicConstraints = critical,CA:TRUE,pathlen:1
+keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
+subjectKeyIdentifier=hash
+</pre> </li> <li> <p>Sign the certificate.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>Generate the site key.</p> <div class="highlight"><pre class="highlight" data-language="">$ openssl genrsa -out "site.key" 4096
+</pre></div> </li> <li> <p>Generate the site certificate and sign it with the site key.</p> <div class="highlight"><pre class="highlight" data-language="">$ openssl req -new -key "site.key" -out "site.csr" -sha256 \
+ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
+</pre></div> </li> <li> <p>Configure the site certificate. Edit a new file called <code class="language-plaintext highlighter-rouge">site.cnf</code> and paste the following contents into it. This constrains the site certificate so that it can only be used to authenticate a server and can’t be used to sign certificates.</p> <pre>[server]
+authorityKeyIdentifier=keyid,issuer
+basicConstraints = critical,CA:FALSE
+extendedKeyUsage=serverAuth
+keyUsage = critical, digitalSignature, keyEncipherment
+subjectAltName = DNS:localhost, IP:127.0.0.1
+subjectKeyIdentifier=hash
+</pre> </li> <li> <p>Sign the site certificate.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>The <code class="language-plaintext highlighter-rouge">site.csr</code> and <code class="language-plaintext highlighter-rouge">site.cnf</code> files are not needed by the Nginx service, but you need them if you want to generate a new site certificate. Protect the <code class="language-plaintext highlighter-rouge">root-ca.key</code> file.</p> </li> </ol> <h4 id="configure-the-nginx-container">Configure the Nginx container</h4> <ol> <li> <p>Produce a very basic Nginx configuration that serves static files over HTTPS. The TLS certificate and key are stored as Docker secrets so that they can be rotated easily.</p> <p>In the current directory, create a new file called <code class="language-plaintext highlighter-rouge">site.conf</code> with the following contents:</p> <pre>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;
+ }
+}
+</pre> </li> <li> <p>Create two secrets, representing the key and the certificate. You can store any file as a secret as long as it is smaller than 500 KB. This allows you to decouple the key and certificate from the services that use them. In these examples, the secret name and the file name are the same.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker secret create site.key site.key
+
+$ docker secret create site.crt site.crt
+</pre></div> </li> <li> <p>Save the <code class="language-plaintext highlighter-rouge">site.conf</code> file in a Docker config. The first parameter is the name of the config, and the second parameter is the file to read it from.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker config create site.conf site.conf
+</pre></div> <p>List the configs:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker config ls
+
+ID NAME CREATED UPDATED
+4ory233120ccg7biwvy11gl5z site.conf 4 seconds ago 4 seconds ago
+</pre></div> </li> <li> <p>Create a service that runs Nginx and has access to the two secrets and the config. Set the mode to <code class="language-plaintext highlighter-rouge">0440</code> so that the file is only readable by its owner and that owner’s group, not the world.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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;'"
+</pre></div> <p>Within the running containers, the following three files now exist:</p> <ul> <li><code class="language-plaintext highlighter-rouge">/run/secrets/site.key</code></li> <li><code class="language-plaintext highlighter-rouge">/run/secrets/site.crt</code></li> <li><code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/site.conf</code></li> </ul> </li> <li> <p>Verify that the Nginx service is running.</p> <div class="highlight"><pre class="highlight" data-language="">$ 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
+</pre></div> </li> <li> <p>Verify that the service is operational: you can reach the Nginx server, and that the correct TLS certificate is being used.</p> <div class="highlight"><pre class="highlight" data-language="">$ curl --cacert root-ca.crt https://0.0.0.0:3000
+
+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Welcome to nginx!&lt;/title&gt;
+&lt;style&gt;
+ body {
+ width: 35em;
+ margin: 0 auto;
+ font-family: Tahoma, Verdana, Arial, sans-serif;
+ }
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;
+&lt;p&gt;If you see this page, the nginx web server is successfully installed and
+working. Further configuration is required.&lt;/p&gt;
+
+&lt;p&gt;For online documentation and support, refer to
+&lt;a href="https://nginx.org"&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;
+Commercial support is available at
+&lt;a href="https://www.nginx.com"&gt;www.nginx.com&lt;/a&gt;.&lt;/p&gt;
+
+&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+</pre></div> <div class="highlight"><pre class="highlight" data-language="">$ 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)
+</pre></div> </li> <li> <p>Unless you are going to continue to the next example, clean up after running this example by removing the <code class="language-plaintext highlighter-rouge">nginx</code> service and the stored secrets and config.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service rm nginx
+
+$ docker secret rm site.crt site.key
+
+$ docker config rm site.conf
+</pre></div> </li> </ol> <p>You have now configured a Nginx service with its configuration decoupled from its image. You could run multiple sites with exactly the same image but separate configurations, without the need to build a custom image at all.</p> <h3 id="example-rotate-a-config">Example: Rotate a config</h3> <p>To rotate a config, you first save a new config with a different name than the one that is currently in use. You then redeploy the service, removing the old config and adding the new config at the same mount point within the container. This example builds upon the previous one by rotating the <code class="language-plaintext highlighter-rouge">site.conf</code> configuration file.</p> <ol> <li> <p>Edit the <code class="language-plaintext highlighter-rouge">site.conf</code> file locally. Add <code class="language-plaintext highlighter-rouge">index.php</code> to the <code class="language-plaintext highlighter-rouge">index</code> line, and save the file.</p> <pre>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;
+ }
+}
+</pre> </li> <li> <p>Create a new Docker config using the new <code class="language-plaintext highlighter-rouge">site.conf</code>, called <code class="language-plaintext highlighter-rouge">site-v2.conf</code>.</p> <pre>$ docker config create site-v2.conf site.conf
+</pre> </li> <li> <p>Update the <code class="language-plaintext highlighter-rouge">nginx</code> service to use the new config instead of the old one.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service update \
+ --config-rm site.conf \
+ --config-add source=site-v2.conf,target=/etc/nginx/conf.d/site.conf,mode=0440 \
+ nginx
+</pre></div> </li> <li> <p>Verify that the <code class="language-plaintext highlighter-rouge">nginx</code> service is fully re-deployed, using <code class="language-plaintext highlighter-rouge">docker service ps nginx</code>. When it is, you can remove the old <code class="language-plaintext highlighter-rouge">site.conf</code> config.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker config rm site.conf
+</pre></div> </li> <li> <p>To clean up, you can remove the <code class="language-plaintext highlighter-rouge">nginx</code> service, as well as the secrets and configs.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker service rm nginx
+
+$ docker secret rm site.crt site.key
+
+$ docker config rm site-v2.conf
+</pre></div> </li> </ol> <p>You have now updated your <code class="language-plaintext highlighter-rouge">nginx</code> service’s configuration without the need to rebuild its image.</p>
+<p><a href="https://docs.docker.com/search/?q=swarm">swarm</a>, <a href="https://docs.docker.com/search/?q=configuration">configuration</a>, <a href="https://docs.docker.com/search/?q=configs">configs</a></p>
+<div class="_attribution">
+ <p class="_attribution-p">
+ &copy; 2019 Docker, Inc.<br>Licensed under the Apache License, Version 2.0.<br>Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.<br>Docker, Inc. and other parties may also have trademark rights in other terms used herein.<br>
+ <a href="https://docs.docker.com/engine/swarm/configs/" class="_attribution-link">https://docs.docker.com/engine/swarm/configs/</a>
+ </p>
+</div>