# Container / OCI deployment RustProxy ships a baseline multi-stage `Dockerfile`. It compiles the locked Rust release and runs it as the unprivileged `rustproxy` user (UID 10001). The core image does not mount the Docker socket. Docker discovery uses the separate `docker-agent/` process on each Docker host, so the proxy container never needs Docker-socket access. See [Docker discovery](DOCKER_DISCOVERY.md). Build locally with a normal OCI builder: ```bash docker build -t rustproxy:0.27.1 . ``` Persist `/var/lib/rustproxy`; it contains the SQLite database, certificates and the optional cold-cache tier. The default container proxy listener is `0.0.0.0:8080`. Administration remains `127.0.0.1:9090` inside the container and is intentionally not remotely reachable by merely publishing port 9090. ```bash docker volume create rustproxy-data docker run --rm -d --name rustproxy \ -p 8080:8080 \ -v rustproxy-data:/var/lib/rustproxy \ rustproxy:0.27.1 docker exec rustproxy rust-proxy admin setup-token ``` To expose administration, first enable administration HTTPS in the persisted RustProxy configuration and choose a certificate, then bind the administration listener to a non-loopback address. Publish the admin port only after HTTPS is active. Plain remote HTTP keeps the legacy explicit risk gate. The runtime image includes Python, venv/pip, OpenSSL and distribution Certbot packages for Cloudflare, OVH and RFC2136 fallback. RustProxy prefers its own pinned Certbot environment under `/var/lib/rustproxy/acme-python`; because `/var/lib/rustproxy` is the persisted volume, that environment survives container replacement. If pip setup is not possible, the image can fall back to the distribution Certbot binaries already in `PATH`. For access-log files, prefer a writable path under `/var/lib/rustproxy` or mount a separate writable log volume. The built-in JSON file sink is disabled by default. Low ports such as 80/443 require an explicit container capability or host port mapping; the image itself does not run as root.