Skip to main content

Docker Security Best Practices

Tiaki supports multiple security enhancements to protect your Docker infrastructure when running the Docker agent.

Docker Socket Proxy

By default, the Tiaki agent requires direct access to the Docker socket (/var/run/docker.sock). While mounted as read-only, this still grants significant privileges.

For enhanced security, use a socket proxy to limit the agent's Docker API access to only the required endpoints.

Setup

  1. Uncomment the socket-proxy service in docker-compose.yml:
socket-proxy:
image: tecnativa/docker-socket-proxy:latest
restart: unless-stopped
profiles:
- agent
- socket-proxy
privileged: true
environment:
- CONTAINERS=1
- IMAGES=1
- INFO=1
- NETWORKS=1
- VOLUMES=1
- POST=1 # Required for pulling images
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- tiaki-internal
  1. Update the agent configuration:
agent:
volumes:
# Comment out direct socket access
# - /var/run/docker.sock:/var/run/docker.sock:ro
environment:
DOCKER_HOST: tcp://socket-proxy:2375
depends_on:
- socket-proxy
  1. Start with both profiles:
docker compose --profile agent --profile socket-proxy up -d

Benefits

  • Principle of least privilege: Agent only gets access to required Docker API endpoints
  • Attack surface reduction: Limits potential damage if agent is compromised
  • Audit trail: Socket proxy can log all Docker API requests

Limitations

The socket proxy itself runs with privileged: true and has full Docker socket access. Ensure it runs in a trusted environment.

Docker Secrets for Registry Credentials

Instead of storing registry credentials in environment variables or .env files, use Docker secrets for enhanced security.

❌ Insecure Method (Environment Variables)

agent:
environment:
REGISTRY_USERNAME: myuser
REGISTRY_PASSWORD: mypassword # Visible in docker inspect!

✅ Secure Method (Docker Secrets)

  1. Create the secrets directory and auth file:
mkdir -p secrets
cp secrets/registry_auth.json.example secrets/registry_auth.json
  1. Edit secrets/registry_auth.json with your credentials:
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "dXNlcm5hbWU6cGFzc3dvcmQ="
},
"ghcr.io": {
"username": "github-username",
"password": "ghp_your_token"
}
}
}
Encoding credentials

For the auth field, use base64-encoded username:password:

echo -n "username:password" | base64
  1. Set file permissions:
chmod 600 secrets/registry_auth.json
  1. Uncomment the secrets section in docker-compose.yml:
secrets:
registry_auth:
file: ./secrets/registry_auth.json

agent:
secrets:
- registry_auth
environment:
REGISTRY_AUTH_FILE: /run/secrets/registry_auth
  1. Restart the agent:
docker compose --profile agent up -d agent

Benefits

  • Not visible in environment: Credentials don't appear in docker inspect or process lists
  • File-based security: Secrets are mounted as read-only files in /run/secrets/
  • Better for production: Industry standard for credential management
  • Git-safe: Secrets directory is excluded from version control

Multiple Registries

You can configure multiple registries in a single registry_auth.json:

{
"auths": {
"https://index.docker.io/v1/": {
"auth": "base64-encoded-dockerhub-creds"
},
"ghcr.io": {
"username": "github-user",
"password": "ghp_token"
},
"registry.example.com": {
"username": "user",
"password": "pass"
}
}
}

Combined Setup (Maximum Security)

For production deployments, combine both features:

services:
socket-proxy:
image: tecnativa/docker-socket-proxy:latest
restart: unless-stopped
profiles: [agent, socket-proxy]
privileged: true
environment:
- CONTAINERS=1
- IMAGES=1
- INFO=1
- NETWORKS=1
- VOLUMES=1
- POST=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- tiaki-internal

agent:
image: tiakidev/tiaki-agent-docker:latest
restart: unless-stopped
profiles: [agent]
environment:
CONTROL_URL: http://server:3001
AGENT_API_KEY: ${AGENT_API_KEY}
DOCKER_HOST: tcp://socket-proxy:2375
REGISTRY_AUTH_FILE: /run/secrets/registry_auth
TRIVY_ENABLED: ${TRIVY_ENABLED:-true}
secrets:
- registry_auth
networks:
- tiaki-internal
depends_on:
- server
- socket-proxy

secrets:
registry_auth:
file: ./secrets/registry_auth.json

Start with:

docker compose --profile agent --profile socket-proxy up -d

Additional Security Recommendations

  1. Network isolation: Use Docker networks to isolate services (already configured)
  2. Read-only mounts: All socket mounts use :ro flag
  3. Minimal permissions: Socket proxy limits API access to required endpoints
  4. Credential rotation: Regularly rotate registry credentials and API keys
  5. Audit logging: Enable and monitor logs for suspicious activity
  6. Updates: Keep Tiaki and all images up to date
  7. Secrets management: Never commit secrets to version control

Kubernetes Alternative

For Kubernetes deployments, use native Kubernetes secrets instead:

apiVersion: v1
kind: Secret
metadata:
name: registry-credentials
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-auth-json>

See Kubernetes Agent Configuration for details.