This project is inspired by the original vishnudxb/docker-mkcert image, but reworked to support multi-architecture builds and a cleaner workflow. The behavior is intended to remain compatible, with small improvements for readability and usage.
Image: https://hub.docker.com/r/fullfrontend/mkcert
Instead of installing mkcert locally, you can run mkcert as a container and share the generated certificates with your dev services.
Create a shared volume:
docker volume create --name mkcert-data
Run mkcert for a single domain:
docker run -d -e domain=dev.localhost.com --name mkcert -v mkcert-data:/root/.local/share/mkcert fullfrontend/mkcert
Comma-separated list with domain:
docker run -d -e domain=api.staging.com,dev.localhost.com,stg.localhost.com --name mkcert -v mkcert-data:/root/.local/share/mkcert fullfrontend/mkcert
Newline-separated list with domains:
docker run -d -e "domains=api.staging.com
dev.localhost.com
stg.localhost.com" --name mkcert -v mkcert-data:/root/.local/share/mkcert fullfrontend/mkcert
More readable domains list:
mkcert:
image: fullfrontend/mkcert
environment:
domains: |
fullfrontend.test
penpot.test
n8n.test
volumes:
- ./certs/:/root/.local/share/mkcert
labels:
- "traefik.enable=false"
networks:
- web
Minimal Traefik setup that mounts the same certs volume and loads them via a file provider.
services:
reverse-proxy:
image: traefik:v3.6.7
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs:/etc/certs:ro
- ./traefik-dev.yml:/etc/traefik/traefik.yml:ro
- ./traefik-dynamic.yml:/etc/traefik/dynamic.yml:ro
networks:
- web
mkcert:
image: fullfrontend/mkcert
environment:
domains: |
app.localhost
api.localhost
volumes:
- ./certs:/root/.local/share/mkcert
labels:
- "traefik.enable=false"
networks:
- web
networks:
web:
external: true
Example traefik-dev.yml:
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
http:
tls: {}
providers:
docker:
exposedByDefault: false
network: "web"
file:
filename: "/etc/traefik/dynamic.yml"
Example traefik-dynamic.yml:
tls:
certificates:
- certFile: "/etc/certs/app.localhost.pem"
keyFile: "/etc/certs/app.localhost-key.pem"
- certFile: "/etc/certs/api.localhost.pem"
keyFile: "/etc/certs/api.localhost-key.pem"
Once mkcert is running, mount the same volume in your app container at the path where your app expects TLS files.
Example (simple Go HTTPS server):
docker build -f Dockerfile.dev -t=mkcert-dev .
docker run -d -p 443:443 --name mkcert-dev -v mkcert-data:/tmp -it mkcert-dev
You must trust mkcert's root CA on your host for browsers to accept the certs.
macOS example:
mkdir ~/Documents/root-ca
docker cp mkcert:/root/.local/share/mkcert ~/Documents/root-ca
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/Documents/root-ca/mkcert/rootCA.pem
If everything goes well, you should see the certs trusted in your browser.