Dev.to Security 🔐 Cybersecurity 👁 0 📖 2 min read

Pick secrets by lifetime: Docker build mounts for builds, Compose files for runtime

Problem summarized Docker offers multiple ways to supply credentials during CI, image build, and runtime. The labels overlap — "secrets", "args", "env" — but the correct choice depends on the lifetime you intend for the

Problem summarized

Docker offers multiple ways to supply credentials during CI, image build, and runtime. The labels overlap — "secrets", "args", "env" — but the correct choice depends on the lifetime you intend for the credential, not convenience.

Implementation overview

1) Build-time needs: Use docker build --secret (RUN --mount=type=secret) for temporary credentials and --ssh (RUN --mount=type=ssh) for SSH agent/socket access. These mounts are scoped to the instruction that uses them and are not meant to persist in resulting image layers or configuration.

2) Runtime needs: Use Docker Compose secrets. Define the secret at the Compose file top level, grant it only to the service that needs it, and read the file from /run/secrets/ inside the container. This keeps the secret out of image content and out of broad environment-variable exposure.

3) Don’t use ARG or ENV for secrets you expect to keep out of images. Build args and ENV become part of image history or config and are the usual cause of accidental leakage.

Expected behavior

  • A build using --secret or --ssh should complete without leaving the secret string in image history or image configuration when the Dockerfile and builder follow the documented pattern.
  • A Compose service that declares a secret should receive the secret as a mounted file at /run/secrets/. Services that don’t list the secret will not receive it.

Verification and limits

  • Always inspect the resulting image with docker history and docker image inspect to ensure the secret text is not present in command history or environment values.
  • These Docker mechanisms ensure Docker itself does not bake secrets into images, but they do not prevent your application from leaking values at runtime (logging, copying files, exposing via debug endpoints). Application-level handling remains your responsibility.

Why this choice matters

The decision is small but strict: choose the mechanism that matches the credential lifetime. Splitting responsibilities when a credential is needed both at build and at runtime avoids forcing one API to do both jobs and reduces accidental persistence.

(Verified implementation example inserted by the server.)

Working example

export function chooseDockerSecretMechanism({ needsDuringBuild, needsDuringRuntime, credentialType = 'file' } = {}) {
  if (needsDuringBuild && needsDuringRuntime) {
    return {
      recommendation: 'split',
      reason: 'Use a build secret or SSH mount during image construction, and a Compose secret at runtime.',
    };
  }

  if (needsDuringBuild) {
    if (credentialType === 'ssh') {
      return {
        recommendation: 'build-ssh-mount',
        reason: 'SSH credentials used during a build should use --ssh and RUN --mount=type=ssh.',
      };
    }

    return {
      recommendation: 'build-secret',
      reason: 'Temporary build-time credentials should use --secret and RUN --mount=type=secret.',
    };
  }

  if (needsDuringRuntime) {
    return {
      recommendation: 'compose-secret',
      reason: 'A running container should read a file-backed secret mounted by Docker Compose at /run/secrets/<name>.',
    };
  }

  return {
    recommendation: 'plain-config',
    reason: 'If the value is not sensitive and is not needed for build or runtime secret access, use ordinary configuration instead.',
  };
}

export function classifyDockerfileLine(line) {
  const text = String(line).trim();

  if (/\bRUN\b.*--mount=type=secret\b/.test(text)) {
    return 'build-secret-mount';
  }
  if (/\bRUN\b.*--mount=type=ssh\b/.test(text)) {
    return 'build-ssh-mount';
  }
  if (/^\s*(ENV|ARG)\b/i.test(text) && /(TOKEN|PASSWORD|SECRET|KEY)/i.test(text)) {
    return 'persistent-secret-risk';
  }
  return 'other';
}

Read the full article: https://chriseugenerodriguez.com/blog/docker-build-vs-compose-secrets

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.