✦ For everyone, free.

Practical knowledge for real and everyday life

Home

17.2.2.2 Mounted Config Practice

A focused guide to Mounted Config Practice, connecting core concepts with practical Docker and container operations.

Mounted config practice addresses file-based configuration delivered through a volume or bind mount, a distinct mechanism from environment variables better suited to structured, multi-value configuration, certificates, and any content too large or too complex to reasonably express as a flat list of key-value pairs.

When a mounted file is the better choice than an environment variable

Environment variables work well for simple, scalar configuration values, but a structured configuration document, a full YAML or JSON config file with nested sections, a TLS certificate and key pair, or a configuration template needing to retain its original, specific formatting, is generally better delivered as an actual file:

docker run -e LOG_LEVEL=info -e DATABASE_URL=postgres://db:5432/app my-api
docker run -v /etc/myapp/config.yaml:/app/config.yaml:ro my-api

Attempting to flatten a genuinely structured, nested configuration document into individual environment variables, one per leaf value, becomes unwieldy quickly and loses the document's own natural structure and relationships, which a mounted file preserves directly and faithfully.

Mounting configuration as read-only by default

Unless the application genuinely needs to write back to its own configuration file, mounting it read-only prevents an accidental or malicious write from corrupting the configuration the application depends on:

docker run -v /etc/myapp/config.yaml:/app/config.yaml:ro my-api
services:
  api:
    volumes:
      - ./config.yaml:/app/config.yaml:ro

This is a small but meaningful safeguard, since a configuration file should generally be treated as input the application reads, not state it manages and writes back to itself during normal operation.

Configuration reload without a full restart

For applications that support it, signaling a configuration reload, often through SIGHUP or a dedicated reload endpoint, allows picking up a changed mounted configuration file without restarting the entire container, which is useful for configuration changes that genuinely do not warrant the disruption of a full restart:

docker kill --signal=HUP my-proxy
events {}
http {
    include /etc/nginx/conf.d/*.conf;
}

Nginx's own configuration reload behavior, triggered by this same signal, is a common, well-established example of this pattern, reapplying an updated, mounted configuration file's contents without dropping any currently active connections.

Templating configuration at container startup

For configuration files that need values substituted from environment variables at the moment a container starts, a templating tool applied during the entrypoint sequence bridges the gap between environment-variable-based configuration and the need for a fully rendered, structured configuration file:

envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
nginx -g "daemon off;"
ENTRYPOINT ["docker-entrypoint.sh"]

This pattern keeps the actual configuration template version-controlled and reviewable as part of the image, while still allowing environment-specific values to be substituted in at runtime, combining the structural benefit of a file-based configuration with the deployment-time flexibility environment variables provide.

Mounting certificates and key material

TLS certificates and private keys are a natural fit for mounted file delivery, since they are inherently structured, multi-line content that does not translate sensibly into a single environment variable value, and they additionally warrant the access restriction a mounted file, rather than an environment variable visible through docker inspect, provides:

docker run -v /etc/certs/server.crt:/app/certs/server.crt:ro \
           -v /etc/certs/server.key:/app/certs/server.key:ro \
           my-api

Restricting host-side file permissions on the certificate and especially the private key file, in addition to the read-only mount itself, layers an additional, meaningful access control on top of the container-level restriction.

Configuration directories versus individual files

For an application expecting an entire directory of configuration, rather than a single file, mounting the whole directory keeps the configuration cohesive and avoids needing a separate mount declaration for every individual file within it:

docker run -v /etc/myapp/conf.d:/app/conf.d:ro my-api

This is particularly useful for applications, like many proxy and web servers, designed around a convention of loading every file within a specific configuration directory, where mounting the directory as a whole matches that expected structure directly.

Validating mounted configuration before relying on it

Because a mounted configuration file's content depends on whatever is actually present at the host path at run time, validating its content directly, rather than assuming it matches what was intended, catches a misconfiguration before the application starts and potentially fails in a less clear, more confusing way:

docker run --rm -v /etc/myapp/config.yaml:/app/config.yaml:ro alpine \
  cat /app/config.yaml

A quick, direct check like this confirms the mounted file's actual content matches expectation before relying on it within an actual running container.

Common mistakes

  • Flattening a genuinely structured, nested configuration document into many individual environment variables rather than delivering it as an actual, mounted file.
  • Mounting a configuration file as writable when the application has no genuine need to write back to it, removing an easy, low-cost safeguard against accidental corruption.
  • Not supporting or using a configuration reload mechanism for changes that do not genuinely warrant a full container restart.
  • Templating configuration with hardcoded values baked in rather than using a startup-time substitution mechanism that bridges environment variables and file-based configuration cleanly.
  • Mounting certificate or key material with overly permissive host-side file permissions, undermining the access restriction the mount itself is meant to help provide.

Mounted config practice complements environment-variable-based configuration specifically for structured documents, certificates, and any content too large or complex to reasonably flatten, applying read-only mounting by default, supporting reload without unnecessary restarts where the application allows it, and validating mounted content directly rather than assuming it matches what was actually intended.