Repository navigation
Distroless builds - rust http servers - #452
cosmintanasa47 wants to merge 40 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed functional correctness issues (e.g., a non-compiling Rust server thread spawn and an incorrect rootfs copy path) plus a few packaging/docs mistakes that should be fixed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces multiple Rust-based HTTP server examples packaged as distroless images for Unikraft Cloud deployments, along with end-to-end tests and deployment instructions.
Changes:
- Added new distroless Rust HTTP server examples (plain Rust, Tokio, Actix Web, Rocket, and a Trunk/Leptos static site served via Nginx).
- Added Kraftfile + Dockerfile build definitions and README deployment guides for each example.
- Added end-to-end Python tests that build, deploy, and verify responses from each deployed service.
File summaries
| File | Description |
|---|---|
| httpserver-rust1.91-distroless/test_httpserver-rust1.91-distroless.py | E2E test that deploys the example and asserts “Hello, World!” |
| httpserver-rust1.91-distroless/server.rs | Minimal HTTP server implementation for the example |
| httpserver-rust1.91-distroless/README.md | Deployment/run instructions and expected outputs |
| httpserver-rust1.91-distroless/Kraftfile | Unikraft Cloud build/run spec for the example |
| httpserver-rust1.91-distroless/Dockerfile | Distroless build pipeline for the example binary |
| httpserver-rust1.91-distroless/.gitignore | Ignores build artifacts |
| httpserver-rust1.91-distroless/.dockerignore | Reduces Docker build context for the example |
| httpserver-rust1.88-rocket0.5-distroless/test_httpserver-rust1.88-rocket0.5-distroless.py | E2E test that hits a Rocket route and validates response |
| httpserver-rust1.88-rocket0.5-distroless/src/main.rs | Rocket-based HTTP server implementation |
| httpserver-rust1.88-rocket0.5-distroless/Rocket.toml | Rocket bind address/port config |
| httpserver-rust1.88-rocket0.5-distroless/README.md | Deployment/run instructions for the Rocket example |
| httpserver-rust1.88-rocket0.5-distroless/Kraftfile | Unikraft Cloud build/run spec for Rocket example |
| httpserver-rust1.88-rocket0.5-distroless/Dockerfile | Distroless build pipeline for Rocket binary |
| httpserver-rust1.88-rocket0.5-distroless/Cargo.toml | Rocket example crate manifest |
| httpserver-rust1.88-rocket0.5-distroless/Cargo.lock | Rocket example dependency lockfile |
| httpserver-rust1.88-rocket0.5-distroless/.gitignore | Ignores Cargo build artifacts |
| httpserver-rust1.88-rocket0.5-distroless/.dockerignore | Reduces Docker build context for Rocket example |
| httpserver-rust1.88-actix-web4-distroless/test_httpserver-rust1.88-actix-web4-distroless.py | E2E test for Actix endpoints (/ and /hey) |
| httpserver-rust1.88-actix-web4-distroless/src/main.rs | Actix Web HTTP server implementation |
| httpserver-rust1.88-actix-web4-distroless/README.md | Deployment/run instructions for the Actix example |
| httpserver-rust1.88-actix-web4-distroless/Kraftfile | Unikraft Cloud build/run spec for Actix example |
| httpserver-rust1.88-actix-web4-distroless/Dockerfile | Distroless build pipeline for Actix binary |
| httpserver-rust1.88-actix-web4-distroless/Cargo.toml | Actix example crate manifest |
| httpserver-rust1.88-actix-web4-distroless/Cargo.lock | Actix example dependency lockfile |
| httpserver-rust1.88-actix-web4-distroless/.gitignore | Ignores Cargo build artifacts |
| httpserver-rust1.88-actix-web4-distroless/.dockerignore | Reduces Docker build context for Actix example |
| httpserver-rust1.75-tokio-distroless/test_httpserver-rust1.75-tokio-distroless.py | E2E test for Tokio-based server example |
| httpserver-rust1.75-tokio-distroless/src/main.rs | Tokio-based TCP HTTP response loop |
| httpserver-rust1.75-tokio-distroless/README.md | Deployment/run instructions for Tokio example |
| httpserver-rust1.75-tokio-distroless/Kraftfile | Unikraft Cloud build/run spec for Tokio example |
| httpserver-rust1.75-tokio-distroless/Dockerfile | Distroless build pipeline for Tokio binary |
| httpserver-rust1.75-tokio-distroless/Cargo.toml | Tokio example crate manifest |
| httpserver-rust1.75-tokio-distroless/Cargo.lock | Tokio example dependency lockfile |
| httpserver-rust1.75-tokio-distroless/.dockerignore | Reduces Docker build context for Tokio example |
| httpserver-rust-trunkrs-leptos-distroless/test_httpserver-rust-trunkrs-leptos-distroless.py | E2E test that verifies a 200 response from the deployed service |
| httpserver-rust-trunkrs-leptos-distroless/shared_lib/src/lib.rs | Shared library used by the frontend (with unit tests) |
| httpserver-rust-trunkrs-leptos-distroless/shared_lib/Cargo.toml | Shared library crate manifest |
| httpserver-rust-trunkrs-leptos-distroless/shared_lib/Cargo.lock | Shared library lockfile |
| httpserver-rust-trunkrs-leptos-distroless/rootfs/rootfs/wwwroot/index.html | Static web root content included in the image rootfs |
| httpserver-rust-trunkrs-leptos-distroless/rootfs/rootfs/etc/nginx/nginx.conf | Nginx configuration included in the image rootfs |
| httpserver-rust-trunkrs-leptos-distroless/README.md | Deployment/run instructions for Trunk/Leptos example |
| httpserver-rust-trunkrs-leptos-distroless/Kraftfile | Unikraft Cloud build/run spec for Nginx-based example |
| httpserver-rust-trunkrs-leptos-distroless/frontend/Trunk.toml | Trunk build configuration |
| httpserver-rust-trunkrs-leptos-distroless/frontend/src/main.rs | Leptos CSR frontend code |
| httpserver-rust-trunkrs-leptos-distroless/frontend/nginx.conf | Nginx config used/overlaid for serving the built frontend |
| httpserver-rust-trunkrs-leptos-distroless/frontend/index.html | Trunk entry HTML |
| httpserver-rust-trunkrs-leptos-distroless/frontend/Cargo.toml | Frontend crate manifest |
| httpserver-rust-trunkrs-leptos-distroless/Dockerfile | Builds frontend assets with Trunk and packages into distroless Nginx image |
| httpserver-rust-trunkrs-leptos-distroless/.gitignore | Ignores build artifacts |
Review details
Suppressed comments (3)
httpserver-rust1.91-distroless/server.rs:21
stream.write(response)may perform a partial write, which can result in truncated HTTP responses. Usewrite_all()(and ideally includeContent-Length/Connection: close) to ensure the full response is sent.
httpserver-rust1.91-distroless/server.rs:40- The spawned thread closure needs to capture
streamby value (move) to satisfy the'staticbound, andJoinHandleis#[must_use]so dropping it without binding may trigger warnings. Capture withmoveand explicitly discard the handle.
httpserver-rust1.88-actix-web4-distroless/README.md:103 - Typo in the sample legacy output: service name
loral-water-sndspsy3should match the domain shown above (floral-water-sndspsy3).
- Files reviewed: 45/50 changed files
- Comments generated: 8
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| use std::net::{TcpStream, TcpListener}; | ||
| use std::io::{Read, Write}; | ||
| use std::thread; |
728f5f3 to
40c0013
Compare
|
I have fixed the typos. I do not consider the COPY rootfs "mistake" detected by Copilot as an actual problem. The previous non-distroless dockerfile did the same thing and worked just well. Same for the distroless version. |
The files that should not be sent to docker daemon.
Same Cargo.lock as for the non-distroless version
Same Cargo.toml as for the non-distroless version
Same Kraftfile as for the non-distroless version
Almost same README as for the non-distroless version. Just modified the names and command examples.
Same src as for the non-distroless version
Almost same test file as for the non-distroless version. Just modified the names so it fits the new context.
…erfile First stage compiles/builds the static executable, the second imports a lightweight distroless image for static executables and languages like Rust or Go and gets the executable from the builder stage and runs it. I think that it's worth mentioning that if the user wants to extend the capabilities of the server he/she has to add CA certificates via Dockerfile to the second stage so the server can communicate with other servers or DBs. If the reviewer also considers that this is worth mentioning in the README, tell me so I can modify the README. Considering that it is just an example, some may consider that it should just work and be as light-weight as possible so CA certs are not necessary.
Add multi-stage dockerfile that builds static executable (first stage) and runs it using a distroless image for rust and go executables.
Add list of files to be ignored by docker daemon.
Kept the old .gitignore file.
Slightly modified the old (non-distroless version) README.md.
Slightly modified the non-ditroless test file for rust1.91 http server.
Add the non-distroless Kraftfile as this variant do not require modifications to Kraftfile.
Kept the old non-distroless variant of server.rs.
Add multi-stage dockerfile. First stage builds static executable. Second stage runs it with distroless image of debian13 for rust and go static executables.
Files to be ignored by docker daemon.
Kept the old .gitignore.
Kept the old Cargo.lock
Kept the old version on Cargo.toml
Kept the old file from the non-distroless version.
Kept the old version.
Slightly modified the old version's by adding "-distroless" in some places and some new examples for running and listing unikraft instances.
Kept the old source file.
…file Slightly modified the test file by adding "-distroless" in some places.
… dockerfile Add multi-stage dockerfile to build and run (first and second stage) the rust http server.
Files to be ignored by docker daemon.
Kept the .gitignore from the original version.
Kept the old Cargo.lock file.
Kept the old Cargo.toml file.
Kept old Kraftfile from non-distroless version.
Slightly modified the previous version adding some command examples and "-distroless".
Kept the original source file.
… file Slightly modified test file to fit to the new distroless example.
Slightly modify previous versions's by changing entry-point to fit with new distroless image.
Kept old .gitignore
Slightly modify old README to fit to distroless version.
…ootfs, shared_lib directories The same as in non-distroless variant.
… file Slightly modify to fit to this version.
… Dockerfile First stage builds the executable and the second one runs it. Didn't use a Google distroless image. I used the distrolessdevops/nginx-distroless:1.25.3 image because it was the same as the one used in the second stage of the non-distroless Dockerfile, so it had perfect compatibility with the built executable. I have also used the digest of the image to get the working variant even if it gets modified by the publisher. I have also taken into consideration using the Chainguard variant but I could have only imported the latest version for free (not a fix one, or a previous one), so I couldn't know if the image would still work after being updated.
40c0013 to
afb46c3
Compare
|
Resolved the first observations and modified accordingly. I do not modify source files, I only modified docker related files and READMEs. |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings remain in the Rust servers and frontend test.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
httpserver-rust-trunkrs-leptos-distroless/README.md:117
- The README instructs users to run this from the repository root (the preceding
cddoes that), butTrunk.tomlandindex.htmlare underfrontend/;trunk servefrom the root therefore has no app entrypoint. Run it from that directory instead.
trunk serve
- Files reviewed: 45/50 changed files
- Comments generated: 7
- Review effort level: Lite
Created distroless build for rust http server that uses tokio. Details in commit messages. Needs review.