Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk5 min

Docker /run/secrets with a Local Fallback: A Safe Pattern for Compose and Deployment

Compose mounts file-backed secrets at /run/secrets, but the local fallback is your app's job. Here is a safe, explicit pattern and the limits to know.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Docker Compose can mount a file-backed secret into a service at /run/secrets/<secret_name>, once you declare the secret at the top level and grant it to that service. Your application then reads the file. The local fallback is not a Docker feature. It is a few lines of application code or configuration, and it needs explicit rules so it never hides a missing production secret.

The pattern in one picture

  1. Declare the secret in the Compose file and grant it to the services that need it.
  2. Docker mounts it read-only at /run/secrets/<name>.
  3. The app reads a configured path first. Only in an explicit development mode does it try a local-only file.
  4. If nothing is found, the app fails loudly.

Docker documents steps 1 and 2. Steps 3 and 4 are an implementation recommendation built on that documented behavior. Docker does not define a fallback path or precedence rules.

Step 1: Declare and grant the secret in Compose

services:
  app:
    image: my-app:dev
    secrets:
      - db_password
    environment:
      APP_ENV: development
      DB_PASSWORD_FILE: /run/secrets/db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

Two details matter here:

  • A top-level secrets entry on its own grants nothing. A service gets the secret only if its own secrets list names it.
  • The short syntax mounts the file at /run/secrets/<secret_name>. Long syntax lets you choose a different target name or an absolute target path.

The source can be a host file, as above, or, in Docker Compose, an environment variable. With a file source, Compose uses the file’s contents and bind-mounts the file into the container.

Keep the local file out of version control:

# .gitignore
secrets/

Step 2: Read the secret with explicit precedence

This Python example is illustrative. The same logic ports to any language.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import os
from pathlib import Path

def read_secret(name: str) -> str:
    primary = os.environ.get(f"{name.upper()}_FILE", f"/run/secrets/{name}")
    candidates = [primary]

    # The local file is considered only when development mode is explicit.
    if os.environ.get("APP_ENV") == "development":
        candidates.append(f"./secrets/{name}.txt")

    for path in candidates:
        p = Path(path)
        if p.is_file():
            return p.read_text().strip()

    raise RuntimeError(
        f"Secret '{name}' not found. Tried: {', '.join(candidates)}"
    )

Design choices worth keeping, whatever your language:

  • Mounted path wins. If a runtime secret is present, it takes precedence over any local file.
  • The fallback is opt-in. It is enabled by an explicit development setting, not by the mere absence of a file. A production container that lost its secret should crash, not quietly use a stale developer credential.
  • Unreadable or missing means failure. The error names the paths tried but never prints secret contents.
  • Document it. Write down which source wins and how failures behave, and test both branches.

Does your image already support _FILE?

Some images accept variables such as MYSQL_ROOT_PASSWORD_FILE, which point at a file instead of holding the value. Docker describes this as a convention supported by certain images, including Docker Official Images such as MySQL and Postgres. It is not a universal rule. Check the image’s documentation. If the image does not support it, your application must read the file itself, as in the example above.

Docker also advises against passing sensitive values as plain environment variables, since they can be visible to processes and show up in logs. Passing a file path in an environment variable is the safe variant of this idea.

Limitations of local Compose secrets

  • Linux containers only. Docker states that Compose supports secrets only for Linux containers. Windows containers support bind-mounting directories only.
  • Permission settings are ignored. A file-backed secret is a bind mount, and the uid, gid and mode settings are silently ignored for file sources. Do not rely on them to tighten permissions. Protect the host file itself.
  • It is not encrypted storage. Docker documents the file source as a bind mount. The encryption guarantees Docker describes for Swarm do not carry over to local Compose.

Trust the Compose project you run

Docker’s trust-model guidance warns that a Compose file can control how containers interact with the host. File-reference fields, including file-backed secrets, can read host files available to the user running Compose, including through symlinks. Their contents may be read during configuration loading, before any container starts. Only run Compose configuration you trust, and review file references, included files and related options in third-party projects first.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Compose, Swarm and BuildKit secrets are different things

All three use /run/secrets as a default location, which is why they get confused.

Aspect Compose file-backed secret Swarm service secret BuildKit build secret
Purpose Runtime file for a service Runtime file for a Swarm service Credential for a build step only
Source Host file (or environment variable in Docker Compose) Swarm-managed secret File or environment variable
Delivery Read-only bind mount, granted per service In-memory filesystem mount for the running task Mount in the build container, default /run/secrets/<id>, custom targets allowed
Encryption claims None documented; it is a bind mount Mutual TLS in transit, encrypted in the Raft log Not a runtime mechanism
Availability Linux containers Swarm services only, not standalone containers Image builds

Swarm specifics that don’t apply locally

  • On Linux the default mount is /run/secrets/<name>. Windows uses a different default path.
  • When the task stops, Docker says the decrypted mount is removed and flushed from node memory.
  • A disconnected node’s running task keeps access, but it cannot receive updates until it reconnects.
  • Docker documents a 500 KB maximum per secret.
  • A secret cannot be removed while a running service uses it. Docker points to versioned secret names and a rotation procedure.

Because your app only reads a file path, the same code works under Compose and Swarm. The security properties behind that path differ.

Build-time credentials

If a build step needs a credential, use a BuildKit secret mount. Do not put credentials in Dockerfile ARG or ENV. Docker’s build checks explain that these can persist in the final image or its metadata. A build mount is not what a running service reads later.

Checklist

  • Secret declared at top level and granted only to services that need it.
  • Local secret file git-ignored and readable only by you on the host.
  • App reads the mounted path first; local fallback is enabled only by an explicit development setting.
  • Missing or unreadable secrets fail startup with a clear, non-leaking error.
  • Image _FILE support verified, not assumed.
  • Third-party Compose files reviewed before running.
  • Build-time credentials use BuildKit secret mounts, never ARG or ENV.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.