Prerequisites
- Docker BuildKit enabled (supported by modern Docker versions).
- Docker Compose (v1.27+ or v2) for Compose secrets support.
- A build process that may need private dependencies or a runtime service that reads credentials from the filesystem.
Implementation decision
If the credential is only required during a RUN step, pass it with docker build --secret and consume it with RUN --mount=type=secret (or use --ssh and RUN --mount=type=ssh for SSH keys). This scope keeps the secret available only to that build instruction and reduces the chance it will be recorded in image layers.
If the credential is only required when the container runs, define it as a Compose secret and mount it into the container at /run/secrets/. Give the secret only to the services that need it.
If both build and runtime need the same credential, do not try to reuse one mechanism for both. Use a build mount during image construction and a Compose secret at runtime; treat those as separate items in your CI and deployment pipeline.
Expected result
- The build process can access private resources without baking credentials into the image.
- The runtime service receives a file-backed secret readable at /run/secrets/ and does not have those secrets stored as image ENV or in image history.
Limitation
- These Docker features stop Docker from embedding secrets into image layers or image configuration, but they cannot control what your application does with a secret once it’s inside a running container. You still need to prevent logging, unintended copies, or publishing of secret contents.
(Verified code 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