docker/compose · error
unsupported external secret
Error message
unsupported external secret %s
What it means
Secrets counterpart of the external-config check: when a service mounts a secret declared 'external: true', compose v2 cannot resolve it (no Swarm secret store lookup) and fails with the secret's resolved name. It needs the secret defined in the project via file or environment.
Solutions
- Drop 'external: true' and provide the secret with file: or environment:
- If the secret lives outside the project, copy/bind-mount it as a file and reference that path
- Use 'docker stack deploy' if Swarm-managed secrets are required
Example fix
# before
secrets:
db_password:
external: true
# after
secrets:
db_password:
file: ./secrets/db_password.txt Defensive patterns
Strategy: validation
Validate before calling
for name, sec := range project.Secrets {
if sec.External {
return fmt.Errorf("secret %s is external; provide file: or environment:", name)
}
} Try / catch
if err != compose.Up(...); err != nil && strings.Contains(err.Error(), "unsupported external secret") { /* inline the secret as a file and retry */ } Prevention
- Run docker compose config as a CI gate
- Convert Swarm secrets to file-backed secrets when migrating
- Never commit secret material; mount via file: from a secret manager checkout
When it happens
Trigger: Top-level secrets: entry with external: true (or {external: true, name: X}) referenced from a service's secrets: list during container creation.
Common situations: Swarm stack files reused with compose; secrets created with 'docker secret create' expected to be picked up; multi-environment YAML sharing.
Related errors
- Docker Compose does not support secrets.*.driver
- Docker Compose does not support secrets.*.template_driver
- unsupported external config
- cannot create in read-only service : `file` is the sole…
- cannot publish compose file with local includes
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/d4306d8acd3b373e.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/compose/create.go:1219
}
return values, nil
}
func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
mounts := map[string]mount.Mount{}
secretsDir := "/run/secrets/"
for _, secret := range s.Secrets {
target := secret.Target
if secret.Target == "" {
target = secretsDir + secret.Source
} else if !isAbsTarget(secret.Target) {
target = secretsDir + secret.Target
}
definedSecret := p.Secrets[secret.Source]
if definedSecret.External {
return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
}
if definedSecret.Driver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.driver") //nolint:staticcheck
}
if definedSecret.TemplateDriver != "" {
return nil, errors.New("Docker Compose does not support secrets.*.template_driver") //nolint:staticcheck
}
if definedSecret.Environment != "" {
continue
}
if secret.UID != "" || secret.GID != "" || secret.Mode != nil {
logrus.Warn("secrets `uid`, `gid` and `mode` are not supported, they will be ignored")
}
if _, err := os.Stat(definedSecret.File); os.IsNotExist(err) {View on GitHub (pinned to ddc4b044b6)