Repository: firezone/firezone
Pull request #8688: chore(rust): remove `dev` stage in Dockerfile
Author: login: thomaseizinger
Created: 2025-04-08T00:17:11Z | Merged: 2025-04-10T04:24:28Z

We don't ever use the `dev` stage within our Rust Dockerfile that actually builds the binaries within the container. In CI, we build the binaries on the host and then copy them in. During local development, I always do the same because it is much faster to iterate that way.

Long story short: We don't need this stage within our Dockerfile and it causes confusion when people try to use `docker compose build`. If somebody really wanted to do that, they need to follow the instructions in the Dockerfile and build the binary first.

Related: #8687


Diff:
diff --git a/docker-compose.yml b/docker-compose.yml
index 01379da1e68..ff10d0a2a62 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -327,7 +327,7 @@ services:
       FIREZONE_API_URL: ws://api:8081
     init: true
     build:
-      target: dev
+      target: debug
       context: rust
       dockerfile: Dockerfile
       cache_from:
@@ -359,7 +359,7 @@ services:
       FIREZONE_ID: 4694E56C-7643-4A15-9DF3-638E5B05F570
     init: true
     build:
-      target: dev
+      target: debug
       context: rust
       dockerfile: Dockerfile
       cache_from:
@@ -446,7 +446,7 @@ services:
       FIREZONE_API_URL: ws://api:8081
       OTLP_GRPC_ENDPOINT: otel:4317
     build:
-      target: dev
+      target: debug
       context: rust
       dockerfile: Dockerfile
       cache_from:
@@ -487,7 +487,7 @@ services:
       FIREZONE_API_URL: ws://api:8081
       OTLP_GRPC_ENDPOINT: otel:4317
     build:
-      target: dev
+      target: debug
       context: rust
       dockerfile: Dockerfile
       cache_from:
diff --git a/rust/Dockerfile b/rust/Dockerfile
index e8cbb738954..ee6d4627685 100644
--- a/rust/Dockerfile
+++ b/rust/Dockerfile
@@ -1,49 +1,7 @@
-# Keep synced with `rust-toolchain.toml`
-ARG RUST_VERSION="1.86.0"
 ARG ALPINE_VERSION="3.20"
-ARG CARGO_CHEF_VERSION="0.1.67"
 
 ARG PACKAGE
 
-# This image is used to prepare Cargo Chef which is used to cache dependencies
-# Keep the Rust version synced with `rust-toolchain.toml`
-FROM rust:${RUST_VERSION}-alpine${ALPINE_VERSION} AS chef
-
-ARG CARGO_CHEF_VERSION
-RUN set -xe \
-    && apk add --no-cache musl-dev \
-    && cargo install cargo-chef --locked --version=${CARGO_CHEF_VERSION} \
-    && rm -rf $CARGO_HOME/registry/
-
-## See https://github.com/LukeMathWalker/cargo-chef/issues/231.
-COPY rust-toolchain.toml rust-toolchain.toml
-
-RUN rustup show
-
-WORKDIR /build
-
-# Create a cache recipe for dependencies, which allows
-# to leverage Docker layer caching in a later build stage
-FROM chef AS planner
-
-COPY . .
-
-RUN cargo chef prepare --recipe-path recipe.json
-
-# Build dependencies and application application
-FROM chef AS builder
-
-COPY --from=planner /build/recipe.json .
-
-ARG PACKAGE
-RUN set -xe \
-    && cargo chef cook --recipe-path recipe.json --bin ${PACKAGE}
-
-COPY . .
-
-ARG TARGET
-RUN cargo build -p ${PACKAGE} $([ -n "${TARGET}" ] && "--target ${TARGET}")
-
 # Base image which is used to run the application binary
 FROM alpine:${ALPINE_VERSION} AS runtime_base
 
@@ -85,27 +43,18 @@ ENV PACKAGE=${PACKAGE}
 
 CMD ${PACKAGE}
 
-# used as a base for dev and test
-FROM runtime AS test
+# Build an image for GitHub Actions which includes debug asserts and more test utilities
+FROM runtime AS debug
 
 RUN apk add --no-cache iperf3 bind-tools iproute2 jq procps
 
-# used for local development
-FROM test AS dev
-ARG TARGET
-ARG PACKAGE
-COPY --from=builder /build/target/${TARGET}/debug/${PACKAGE} .
-
-# Build an image for GitHub Actions which includes debug asserts and more test utilities
-FROM test AS debug
-
-## Build first with `cross build --target ${TARGET} -p ${PACKAGE} && mv /target/${TARGET}/release/${PACKAGE} .`
+## Build first with `cargo build --target ${TARGET} -p ${PACKAGE} && mv /target/${TARGET}/debug/${PACKAGE} .`
 ARG PACKAGE
 COPY ${PACKAGE} .
 
 # Build a production image from including a binary compiled on the host
 FROM runtime AS release
 
-## Build first with `cross build --target ${TARGET} -p ${PACKAGE} --release && mv /target/${TARGET}/release/${PACKAGE} .`
+## Build first with `cargo build --target ${TARGET} -p ${PACKAGE} --release && mv /target/${TARGET}/release/${PACKAGE} .`
 ARG PACKAGE
 COPY ${PACKAGE} .
diff --git a/rust/docker-compose-dev.yml b/rust/docker-compose-dev.yml
deleted file mode 100644
index c46bce5b5c0..00000000000
--- a/rust/docker-compose-dev.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-# Meant to be used with docker-compose.yml
-services:
-  client:
-    build:
-      target: test
-    volumes:
-      - ./rust/target/x86_64-unknown-linux-musl/debug/firezone-headless-client:/bin/firezone-headless-client
-
-  download.httpbin:
-    build:
-      target: test
-    volumes:
-      - ./rust/target/x86_64-unknown-linux-musl/debug/http-test-server:/bin/http-test-server
-
-  gateway:
-    build:
-      target: test
-    volumes:
-      - ./rust/target/x86_64-unknown-linux-musl/debug/firezone-gateway:/bin/firezone-gateway
-
-  relay-1:
-    build:
-      target: test
-    volumes:
-      - ./rust/target/x86_64-unknown-linux-musl/debug/firezone-relay:/bin/firezone-relay
-
-  relay-2:
-    build:
-      target: test
-    volumes:
-      - ./rust/target/x86_64-unknown-linux-musl/debug/firezone-relay:/bin/firezone-relay
diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml
index 7c097685eb4..8009387dc8f 100644
--- a/rust/rust-toolchain.toml
+++ b/rust/rust-toolchain.toml
@@ -1,5 +1,4 @@
 [toolchain]
-# Keep synced with `Dockerfile`
 channel = "1.86.0"
 components = ["rust-src", "rust-analyzer", "clippy"]
 targets = ["x86_64-unknown-linux-musl"]


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

<details>
<summary>Files not reviewed (2)</summary>

* **rust/Dockerfile**: Language not supported
* **rust/docker-compose-dev.yml**: Language not supported
</details>



state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T00:17:36Z
user: login: jamilbk
body: Will this break the dev setup for the main docker-compose.yml? We use that whenever we need an entire cluster for local dev like testing the relays_presence stuff.

Building outside and copying in doesn't work so well for Mac users.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-08T12:25:23Z
user: login: jamilbk
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-08T19:51:51Z

Review comments:
diff_hunk: @@ -327,7 +327,7 @@ services:
       FIREZONE_API_URL: ws://api:8081
     init: true
     build:
-      target: dev
+      target: debug
path: docker-compose.yml
user: login: Copilot
body: Verify that a 'debug' build stage exists in the Dockerfile to support this change, as the removal of the 'dev' stage requires an alternative target.
created_at: 2025-04-08T00:17:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,27 +43,18 @@ ENV PACKAGE=${PACKAGE}
 
 CMD ${PACKAGE}
 
-# used as a base for dev and test
-FROM runtime AS test
+# Build an image for GitHub Actions which includes debug asserts and more test utilities
+FROM runtime AS debug
 
 RUN apk add --no-cache iperf3 bind-tools iproute2 jq procps
 
-# used for local development
-FROM test AS dev
-ARG TARGET
-ARG PACKAGE
-COPY --from=builder /build/target/${TARGET}/debug/${PACKAGE} .
-
-# Build an image for GitHub Actions which includes debug asserts and more test utilities
-FROM test AS debug
-
-## Build first with `cross build --target ${TARGET} -p ${PACKAGE} && mv /target/${TARGET}/release/${PACKAGE} .`
+## Build first with `cargo build --target ${TARGET} -p ${PACKAGE} && mv /target/${TARGET}/release/${PACKAGE} .`
path: rust/Dockerfile
user: login: jamilbk
body: ```suggestion
## Build first with `cargo build --target ${TARGET} -p ${PACKAGE} && mv /target/${TARGET}/debug/${PACKAGE} .`
```
created_at: 2025-04-08T19:51:09Z
author_association: MEMBER

PR comments:
user: login: vercel[bot]
created_at: 2025-04-08T00:17:16Z
body: [vc]: #Ej5CSEnwIy52/9W6j6RUDAmTJHkyL4QA+U6fcrxuo9A=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJmaXJlem9uZSIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9maXJlem9uZS9maXJlem9uZS9CUkI2UGs3RXFUWmJaRWJ0dGtadTV1VlVSTjFqIiwicHJldmlld1VybCI6ImZpcmV6b25lLWdpdC1jaG9yZS1zaW1wbGlmeS1ydXN0LWRvY2tlci1maXJlem9uZS52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImZpcmV6b25lLWdpdC1jaG9yZS1zaW1wbGlmeS1ydXN0LWRvY2tlci1maXJlem9uZS52ZXJjZWwuYXBwIn0sInJvb3REaXJlY3RvcnkiOiJ3ZWJzaXRlIn1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **firezone** | ✅ Ready ([Inspect](https://vercel.com/firezone/firezone/BRB6Pk7EqTZbZEbttkZu5uVURN1j)) | [Visit Preview](https://firezone-git-chore-simplify-rust-docker-firezone.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/firezone-git-chore-simplify-rust-docker-firezone.vercel.app?via=pr-comment-feedback-link) | Apr 10, 2025 3:45am |


author_association: NONE
user: login: thomaseizinger
created_at: 2025-04-08T12:35:26Z
body: > Will this break the dev setup for the main docker-compose.yml? We use that whenever we need an entire cluster for local dev like testing the relays_presence stuff.
> 
> Building outside and copying in doesn't work so well for Mac users.

If we need it then we should test it in CI, otherwise it will keep breaking.
author_association: MEMBER
user: login: thomaseizinger
created_at: 2025-04-08T12:37:38Z
body: > Building outside and copying in doesn't work so well for Mac users.

Do you need to modify Rust code and recompile? Could always use `cross` I guess?
author_association: MEMBER
user: login: jamilbk
created_at: 2025-04-10T04:03:34Z
body: Would it make sense to update the contributing guide here too
author_association: MEMBER