Docker Secrets

Deploy OpenLDAP with passwords loaded from Docker secrets instead of plaintext environment variables. Passwords never appear in docker inspect, process lists, or container metadata.

Project Files

openldap-secrets
Explorer
docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
services:
  openldap:
    image: ${LDAP_IMAGE:-openldap:local}
    container_name: openldap-secrets
    hostname: openldap-secrets
    environment:
      # Use _FILE variants to read passwords from Docker secrets
      - LDAP_DOMAIN=example.com
      - LDAP_ADMIN_PASSWORD_FILE=/run/secrets/ldap_admin_password
      - LDAP_CONFIG_PASSWORD_FILE=/run/secrets/ldap_config_password
      - LDAP_ORGANIZATION=Example Organization (Docker Secrets)
      
      # Optional features
      - ENABLE_MONITORING=true
      - ENABLE_MEMBEROF=false
    ports:
      - "389:389"
      - "636:636"
    volumes:
      - ldap-data:/var/lib/ldap
      - ldap-config:/etc/openldap/slapd.d
      - ./logs:/logs
    
    # Security: Drop all capabilities and add only required ones
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
      - SETUID
      - SETGID
      - CHOWN
      - DAC_READ_SEARCH
      - DAC_OVERRIDE
    
    # Grace period for clean shutdown
    stop_grace_period: 30s
    
    # Docker secrets - passwords are mounted as files, not env vars
    secrets:
      - ldap_admin_password
      - ldap_config_password
    
    restart: unless-stopped
    
    # Resource limits
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '1.0'
        reservations:
          memory: 128M
    
    # Log rotation
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  ldap-data:
  ldap-config:

# Docker secrets definition
# Secrets are read from files on the host at startup
secrets:
  ldap_admin_password:
    file: ./secrets/admin_password.txt
  ldap_config_password:
    file: ./secrets/config_password.txt
YAMLUTF-8
Ln 741 files

Set image

export LDAP_IMAGE=ghcr.io/vibhuvioio/openldap:latest

Create Secret Files

mkdir -p secrets
echo "YourSecureAdminPassword" > secrets/admin_password.txt
echo "YourSecureConfigPassword" > secrets/config_password.txt
Important: Add secrets/.txt to your .gitignore to avoid committing passwords.

Start

docker compose up -d

Verify Secrets Are Used

# Passwords should NOT appear in environment variables
docker exec openldap-secrets env | grep -i password
# Expected: LDAP_ADMIN_PASSWORD_FILE=/run/secrets/ldap_admin_password
# (not the actual password)

# Verify the secret file is mounted
docker exec openldap-secrets cat /run/secrets/ldap_admin_password

Test Authentication

ADMIN_PASS=$(cat secrets/admin_password.txt)

ldapsearch -x -H ldap://localhost:389 \
  -D "cn=Manager,dc=example,dc=com" \
  -w "$ADMIN_PASS" \
  -b "dc=example,dc=com" -s base

How It Works

The Docker Compose file uses the secrets directive:

services:
  openldap:
    environment:
      - LDAP_ADMIN_PASSWORD_FILE=/run/secrets/ldap_admin_password
      - LDAP_CONFIG_PASSWORD_FILE=/run/secrets/ldap_config_password
    secrets:
      - ldap_admin_password
      - ldap_config_password

secrets:
  ldap_admin_password:
    file: ./secrets/admin_password.txt
  ldap_config_password:
    file: ./secrets/config_password.txt

The startup.sh script detects _FILE variants and reads the password from the file at runtime:

if [ -n "$LDAP_ADMIN_PASSWORD_FILE" ] && [ -f "$LDAP_ADMIN_PASSWORD_FILE" ]; then
    LDAP_ADMIN_PASSWORD=$(cat "$LDAP_ADMIN_PASSWORD_FILE")
fi

Security Comparison

Plaintext Env VarDocker Secrets
Visible in docker inspectHidden from container metadata
In process list (ps e)Only in file readable by container
May be loggedNot logged by default
Risk of git commitCan be gitignored

Connection Details

SettingValue
Hostlocalhost
LDAP Port389
LDAPS Port636
Bind DNcn=Manager,dc=example,dc=com
Base DNdc=example,dc=com
PasswordContents of secrets/admin_password.txt

Production Recommendations

  1. 1 Never commit secrets to git — add secrets/.txt to .gitignore
  2. 2 Use proper secret managers — Docker Swarm (docker secret create), Kubernetes Sealed Secrets, or HashiCorp Vault
  3. 3 Rotate secrets regularly — update the file and restart the container
  4. 4 Set strict permissionschmod 600 secrets/*.txt

Cleanup

docker compose down -v