# Docker deploy
`openlatch-provider` ships as a multi-arch image at
`ghcr.io/openlatch/provider:<version>` (and `:latest`). The image is
[distroless](https://github.com/GoogleContainerTools/distroless)
(`gcr.io/distroless/cc-debian12:nonroot`) so the attack surface is
limited to the daemon binary itself.
## Pull and run
```bash
docker run --rm \
-p 127.0.0.1:8443:8443 \
-v ~/.openlatch/provider:/home/nonroot/.openlatch/provider \
-e OPENLATCH_TOKEN=$OPENLATCH_TOKEN \
ghcr.io/openlatch/provider:latest
```
The container's default `ENTRYPOINT` runs `listen --port 8443 --no-tls`.
TLS termination is expected to live in front of the daemon (Caddy /
Nginx / a load balancer); see `caddy-tls-termination.md`.
## Compose
`docker-compose.example.yml` is a copy-friendly starting point. The
volume mount is mandatory — without it the daemon has no manifest,
binding secrets, or audit log path.
## Image size
The release image is < 50 MB on each arch (distroless + stripped
binary). Image labels carry the standard `org.opencontainers.image.*`
metadata so your registry tooling can render the source / license.
## Multi-arch
Both `linux/amd64` and `linux/arm64` are built by the publish workflow
via `docker buildx`. `docker pull` automatically picks the right manifest
for your host arch.
## Auto-update inside containers
The container build sets `OPENLATCH_NO_AUTO_UPDATE=1` by default in the
example compose file: container deployments should rebuild against a
pinned image tag, not auto-update in place. If you do want
auto-update inside the container, drop the env var and ensure the
container has a writable mount point for `~/.openlatch/provider/` so
the sentinel + install-state survive restarts.