# Rust Dockerfile Generator

URL: /dockerizer/rust

Generate a production Dockerfile for a Rust service with a cached cargo registry and target directory, shipping a single binary.

## Default configuration

- `appName` (App name): rust-app — Used for the image tag, the compose service and the OCI labels.

- `port` (Port): 8080 — The port the app listens on inside the container. Keep it above 1024 so the process can bind it without root.

- `binaryName` (Binary name): app — The [[bin]] name from Cargo.toml — usually the package name.

- `rustVersion` (Rust version): 1.85

- `runtimeBase` (Runtime image): distroless

- `database` (Database service): none — Adds the database to docker-compose.yml with a healthcheck, a named volume and a DATABASE_URL wired into the app.

- `redis` (Redis service): false — Adds Redis to docker-compose.yml and exposes REDIS_URL to the app.

- `cacheMounts` (BuildKit cache mounts): true — Persists the package manager store between builds. Repeat builds skip the download entirely.

- `multiArch` (Multi-architecture build): false — Adds BUILDPLATFORM/TARGETARCH so `docker buildx build --platform linux/amd64,linux/arm64` cross-compiles natively.

- `healthcheck` (Healthcheck): true — Adds a HEALTHCHECK so orchestrators can restart an unresponsive container.

- `ociLabels` (OCI labels): false — Adds org.opencontainers.image.* metadata to the final image.

## Generated files

### Dockerfile

Multi-stage build: dependencies, compilation and the runtime image are separate, so only what the app needs at runtime ships.

```docker
# syntax=docker/dockerfile:1
# Generated by Easypanel Dockerizer — https://easypanel.io/dockerizer

# --- Build --------------------------------------------
FROM rust:1.85-slim-bookworm AS build

# Common transitive build dependencies for TLS-enabled crates
RUN apt-get update \
 && apt-get install -y --no-install-recommends pkg-config libssl-dev \
 && rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY . .

# The target dir is a cache mount, so it must be copied out before the mount is released
RUN --mount=type=cache,id=cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
    --mount=type=cache,id=cargo-target,target=/src/target,sharing=locked \
    cargo build --release --locked && cp target/release/app /bin/app

# --- Runtime ------------------------------------------
FROM gcr.io/distroless/cc-debian12:nonroot AS runtime
COPY --from=build /bin/app /app
USER nonroot
ENV PORT=8080
EXPOSE 8080
STOPSIGNAL SIGTERM

# No healthcheck: distroless has no shell. Probe from the orchestrator instead.
ENTRYPOINT ["/app"]

```

### .dockerignore

Keeps the build context small and stops secrets and local dependencies from reaching an image layer.

```bash
# Version control
.git
.gitignore
.github

# Secrets — never bake these into an image layer
.env
.env.*
!.env.example
*.pem
*.key

# Editor and OS noise
.vscode
.idea
.DS_Store
Thumbs.db

# Docs and local tooling
README.md
LICENSE
docs
.editorconfig
docker-compose*.yml
Dockerfile*
.dockerignore

# Cargo build output — rebuilt inside the image
target
**/*.rs.bk

```

### docker-compose.yml

Runs the image locally with its backing services, wired together and health-gated.

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - "8080:8080"

```

## Frequently asked questions

### Why copy the binary out of target/ in the same RUN?

Because target/ is a cache mount — it exists only for the duration of that instruction. Anything left there is gone by the time the next layer runs.

### Can I get a truly static Rust binary?

Yes, build for x86_64-unknown-linux-musl. Then the runtime image can be scratch. It is a slower build and some crates need extra work, which is why glibc plus distroless/cc is the default here.

## Related generators

- [Go](/dockerizer/golang)

- [Node.js](/dockerizer/nodejs)

- [FastAPI](/dockerizer/fastapi)

- [.NET](/dockerizer/dotnet)