Self-Signed SSL Certificates in Docker
Mount certs, build them into images, or trust them inside a container — all the patterns for self-signed certs in Docker.
Running a self-signed cert in a container is the same as on bare metal — you just need the files where the process can read them. A few patterns cover 99% of use cases.
Pattern 1: Mount certs as a volume (recommended)
Keeps certs out of the image. Rotate them without rebuilding.
# docker-compose.yml
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./certs:/etc/nginx/ssl:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
Then in nginx.conf:
ssl_certificate /etc/nginx/ssl/certificate.pem;
ssl_certificate_key /etc/nginx/ssl/private-key.pem;
Pattern 2: Docker secrets
For Docker Swarm, put certs in secrets. They're mounted at /run/secrets/ read-only inside the container.
# docker-compose.yml
secrets:
cert:
file: ./certificate.pem
key:
file: ./private-key.pem
services:
nginx:
image: nginx:alpine
secrets: [cert, key]
# reference as /run/secrets/cert and /run/secrets/key
Pattern 3: Build certs into the image (dev only)
FROM nginx:alpine
COPY certificate.pem /etc/nginx/ssl/
COPY private-key.pem /etc/nginx/ssl/
COPY nginx.conf /etc/nginx/nginx.conf
Never ship a container image to a registry with the private key baked in. Anyone who pulls the image can extract the key. Use mount or secrets for anything that leaves your laptop.
Trust a self-signed cert inside the container
If your app runs in a container and needs to call an HTTPS service with a self-signed cert:
# Dockerfile — Debian/Ubuntu-based
COPY ca.pem /usr/local/share/ca-certificates/my-ca.crt
RUN update-ca-certificates
Alpine:
COPY ca.pem /usr/local/share/ca-certificates/my-ca.crt
RUN apk add --no-cache ca-certificates && update-ca-certificates
Pattern 4: Caddy (auto-HTTPS in a container)
For pure local dev, Caddy will generate a self-signed cert on the fly:
# Caddyfile
localhost {
reverse_proxy app:3000
tls internal
}
tls internal tells Caddy to mint a cert from its internal CA. Trust Caddy's CA in your OS once, and everything it serves is trusted for the duration of the cert.
Troubleshooting
"SSL_CTX_use_PrivateKey_file failed"
The container can't read the key file. Check volume mount permissions, and make sure the file isn't empty (a common silent failure when a volume path is wrong — it creates an empty directory instead of mounting the file).
Client inside container can't verify a self-signed server
You need to trust the cert inside the container — see the update-ca-certificates pattern above. For Node.js containers, mount the cert and set NODE_EXTRA_CA_CERTS.