How to fix secret "mysecret" is not defined in Docker

DockerINTERMEDIATEMEDIUMUpdated Dec 6, 2025ยท 179 views

The 'secret is not defined' error in Docker Compose occurs when a service references a secret that hasn't been declared in the top-level secrets section of your compose file. Fix it by defining the secret at the top level with either a file source or external reference.

Quick fix

Fixes secret "mysecret" is not defined

services:
  myapp:
    image: myapp:latest
    secrets:
      - my_secret          # Service-level: which secrets to use

secrets:                    # Top-level: where secrets come from
  my_secret:
    file: ./my_secret.txt   # Path to file containing the secret
  1. Add the top-level secrets definition
  2. Check for secret name mismatches
  3. Use file-based secrets for local development
  4. Use environment variables as secret source
docker โ€” error
services:
myapp:
image: myapp:latest
secrets:
- my_secret # Service-level: which secrets to use
secrets: # Top-level: where secrets come from
my_secret:
file: ./my_secret.txt # Path to file containing the secret
secret "mysecret" is not defined

What this error means

The "secret is not defined" error indicates that Docker Compose found a reference to a secret in a service definition, but that secret hasn't been declared in the top-level `secrets:` section of your compose file. Docker Compose secrets work in two parts: 1. **Top-level declaration**: You must define all secrets at the root level of your compose file, specifying where the secret value comes from (a file, environment variable, or external source) 2. **Service-level reference**: Services then reference which secrets they need access to When you reference a secret in a service (like `secrets: [my_secret]`) without first declaring it at the top level, Docker Compose cannot resolve where that secret value should come from, resulting in this error. This error commonly occurs when: - Copying service definitions without their corresponding secret declarations - Migrating from Docker Swarm where secrets were created externally - Forgetting to add the top-level secrets block after adding secrets to a service - Typos in secret names between the top-level declaration and service reference

Typical symptoms

  • Running `docker-compose up` fails with 'secret "mysecret" is not defined'
  • Docker Compose config validation fails before any containers start
  • Error appears immediately when parsing the compose file
  • The error message shows the exact secret name that's missing
  • `docker-compose config` fails with the same secret not defined error
  • Build and up commands both fail at the configuration stage
  • CI/CD pipelines fail at the docker-compose validation step

Common causes

  1. Missing top-level secrets: block in docker-compose.yml (most common)
  2. Secret name mismatch between service reference and top-level declaration
  3. Typo in secret name (underscores vs hyphens, case sensitivity)
  4. Copied service configuration without copying the secrets definition
  5. Using external: true but secret doesn't exist in Docker Swarm
  6. Incomplete migration from another deployment configuration
  7. Secret file path is defined but the file doesn't exist

How to fix "secret "mysecret" is not defined"

1Add the top-level secrets definition

The most common fix is adding the missing top-level secrets: block. Docker Compose requires secrets to be defined at both the service level AND the top level:

yaml
services:
  myapp:
    image: myapp:latest
    secrets:
      - my_secret          # Service-level: which secrets to use

secrets:                    # Top-level: where secrets come from
  my_secret:
    file: ./my_secret.txt   # Path to file containing the secret

The secret file should contain the raw secret value (no quotes needed):

bash
# Create the secret file
echo "my-super-secret-value" > ./my_secret.txt

# Verify Docker Compose config is valid
docker-compose config

Inside your container, the secret will be available at /run/secrets/my_secret.

2Check for secret name mismatches

Ensure the secret name matches exactly between the service reference and top-level declaration:

Incorrect (names don't match):

yaml
services:
  web:
    secrets:
      - db_password        # Using underscores

secrets:
  db-password:             # Using hyphens - MISMATCH!
    file: ./db_password.txt

Correct:

yaml
services:
  web:
    secrets:
      - db_password        # Matches exactly

secrets:
  db_password:             # Same name
    file: ./db_password.txt

Common naming issues:
- db_password vs db-password (underscore vs hyphen)
- mySecret vs mysecret (case sensitivity)
- db_pass vs db_password (abbreviation differences)

3Use file-based secrets for local development

For local development with Docker Compose, file-based secrets are the simplest approach:

yaml
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
      - db_user

  app:
    image: myapp
    secrets:
      - db_password
      - api_key
    depends_on:
      - db

secrets:
  db_password:
    file: ./secrets/db_password.txt
  db_user:
    file: ./secrets/db_user.txt
  api_key:
    file: ./secrets/api_key.txt

Create the secrets directory and files:

bash
mkdir -p ./secrets
echo "postgres-password-123" > ./secrets/db_password.txt
echo "postgres" > ./secrets/db_user.txt
echo "api-key-abc123" > ./secrets/api_key.txt

# Don't commit secrets to git
echo "secrets/" >> .gitignore
4Use environment variables as secret source

Docker Compose can also read secrets from environment variables (available in Compose V2):

yaml
services:
  app:
    image: myapp
    secrets:
      - db_password

secrets:
  db_password:
    environment: DB_PASSWORD    # Read from host environment variable

Then set the environment variable before running:

bash
export DB_PASSWORD="my-secret-password"
docker-compose up

Or in a .env file:

bash
# .env
DB_PASSWORD=my-secret-password

This approach is useful for:
- CI/CD pipelines where secrets are injected as environment variables
- Avoiding secret files on disk
- Dynamic secret values

5Configure external secrets for Docker Swarm

If you're using Docker Swarm, secrets can be created externally and referenced in your compose file:

bash
# First, create the secret in Docker Swarm
docker swarm init  # If not already in swarm mode
echo "my-secret-value" | docker secret create my_secret -

Then reference it as external in your compose file:

yaml
services:
  app:
    image: myapp
    secrets:
      - my_secret

secrets:
  my_secret:
    external: true    # Secret must already exist in Swarm

Important: External secrets ONLY work in Docker Swarm mode. If you see this error with external: true:
- Ensure you've initialized Swarm: docker swarm init
- Verify the secret exists: docker secret ls
- For local development, use file-based secrets instead

6Handle build-time secrets separately

Build-time secrets (used during docker-compose build) require a different setup than runtime secrets:

For runtime secrets (used when container runs):

yaml
services:
  app:
    image: myapp
    secrets:
      - api_key

secrets:
  api_key:
    file: ./api_key.txt

For build-time secrets (used during image build):

yaml
services:
  app:
    build:
      context: .
      secrets:
        - npm_token    # Build-time secret

secrets:
  npm_token:
    file: ./npm_token.txt

In your Dockerfile, mount the build secret:

dockerfile
# syntax=docker/dockerfile:1
FROM node:18

# Mount and use the secret during build
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm install

COPY . .

Build with BuildKit enabled:

bash
DOCKER_BUILDKIT=1 docker-compose build
7Verify your configuration with docker-compose config

Use docker-compose config to validate your compose file and see the resolved configuration:

bash
# Validate the compose file
docker-compose config

# If you see the error, the config is invalid
# ERROR: secret "mysecret" is not defined

# After fixing, you should see the full resolved config
docker-compose config

The output should show your secrets properly defined:

yaml
services:
  app:
    image: myapp
    secrets:
      - source: my_secret
        target: /run/secrets/my_secret
secrets:
  my_secret:
    file: /full/path/to/my_secret.txt

This command helps catch configuration errors before attempting to start containers.

Advanced notes

### Understanding Docker Secrets Architecture

Docker secrets are designed to securely pass sensitive data to containers. Here's how they work:

File-based secrets (Compose standalone)
- Secret content is stored in a file on your host
- Docker mounts the file into the container at /run/secrets/<secret_name>
- The mount is read-only with restrictive permissions
- Works without Docker Swarm

External secrets (Swarm mode)
- Secrets are stored encrypted in the Swarm raft log
- Distributed automatically to nodes that need them
- More secure for production multi-node deployments
- Requires docker swarm init

### Secret Syntax Variations

Docker Compose supports both short and long syntax for secrets:

Short syntax:

yaml
services:
  app:
    secrets:
      - my_secret

Long syntax (more control):

yaml
services:
  app:
    secrets:
      - source: my_secret
        target: /custom/path/secret    # Custom path in container
        uid: '103'                      # Owner UID
        gid: '103'                      # Owner GID
        mode: 0440                      # File permissions

### Reading Secrets in Applications

Applications need to read from /run/secrets/<name> instead of environment variables:

Node.js:

javascript
const fs = require('fs');
const dbPassword = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();

Python:

python
with open('/run/secrets/db_password') as f:
    db_password = f.read().strip()

Bash:

bash
DB_PASSWORD=$(cat /run/secrets/db_password)

### Many Images Support *_FILE Environment Variables

Official images like PostgreSQL, MySQL, and MariaDB support a *_FILE convention:

yaml
services:
  db:
    image: postgres:15
    environment:
      # Instead of POSTGRES_PASSWORD directly
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

This pattern is more secure than passing secrets as environment variables.

### Secrets vs Environment Variables

| Aspect | Secrets | Environment Variables |
|--------|---------|----------------------|
| Storage | File at /run/secrets | Process memory |
| Visibility | Not in docker inspect | Visible in docker inspect |
| Logging | Not logged | May appear in logs |
| Best for | Passwords, API keys | Non-sensitive config |

### Troubleshooting Common Issues

1. Secret file not found:

bash
# Check file exists and path is correct
ls -la ./secrets/

# Use absolute path if relative doesn't work
secrets:
  my_secret:
    file: /home/user/project/secrets/my_secret.txt

2. Secret empty in container:

bash
# Check file isn't empty
cat ./secrets/my_secret.txt

# Ensure no trailing newlines if app is sensitive to them
echo -n "secret-value" > ./secrets/my_secret.txt

3. Permission denied reading secret:

bash
# Check container user can read /run/secrets
docker-compose exec app ls -la /run/secrets/

# Use long syntax to set permissions
secrets:
  - source: my_secret
    mode: 0444    # World-readable

### Security Best Practices

1. Never commit secrets to git - Add to .gitignore
2. Use .env.example - Document required secrets without values
3. Rotate secrets regularly - Recreate secret files periodically
4. Limit access - Only mount secrets to services that need them
5. Use external secrets in production - Swarm secrets or HashiCorp Vault

Frequently asked questions

What does "secret "mysecret" is not defined" mean?
The "secret is not defined" error indicates that Docker Compose found a reference to a secret in a service definition, but that secret hasn't been declared in the top-level secrets: section of your compose file. Docker Compose secrets work in two parts: 1. Top-level declaration: You must define all secrets at the root level of your compose file, specifying where the secret value comes from (a file, environment variable, or external source) 2.
How do I fix "secret "mysecret" is not defined"?
The 'secret is not defined' error in Docker Compose occurs when a service references a secret that hasn't been declared in the top-level secrets section of your compose file. Fix it by defining the secret at the top level with either a file source or external reference.
What causes "secret "mysecret" is not defined"?
Missing top-level secrets: block in docker-compose.yml (most common) Secret name mismatch between service reference and top-level declaration Typo in secret name (underscores vs hyphens, case sensitivity)
Is the "secret "mysecret" is not defined" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading