Introduction
\n\nRust is a modern systems programming language that combines the high performance of C/C++ with compile-time memory safety. Thanks to the absence of a garbage collector and low resource consumption, Rust applications are ideal for running in containerized environments. Kubernetes (K8s) is the de facto standard for container orchestration. In this guide, we will practically walk through how to build a simple web application in Rust, package it into a Docker image, and deploy it in a Kubernetes cluster.
\n\nThe article is intended for developers who are already familiar with the basics of Rust and have a basic understanding of Docker and Kubernetes. We will not delve into theory, but will focus on a step-by-step guide with real code examples and commands.
\n\n1. Preparing the Rust Application
\n\nAs an example, we will create a minimal HTTP server using the popular actix-web framework. It will respond to GET requests and return a JSON response.
Create a new project:
\n\ncargo new rust-k8s-app\ncd rust-k8s-app\n\nAdd dependencies to Cargo.toml:
[dependencies]\nactix-web = "4"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\n\nNow let's write the server code in src/main.rs:
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};\nuse serde::Serialize;\n\n#[derive(Serialize)]\nstruct HealthResponse {\n status: String,\n message: String,\n}\n\n#[get("/health")]\nasync fn health_check() -> impl Responder {\n HttpResponse::Ok().json(HealthResponse {\n status: "ok".to_string(),\n message: "Service is running".to_string(),\n })\n}\n\n#[get("/")]\nasync fn index() -> impl Responder {\n HttpResponse::Ok().json(serde_json::json!({\n "service": "rust-k8s-app",\n "version": env!("CARGO_PKG_VERSION")\n }))\n}\n\n#[actix_web::main]\nasync fn main() -> std::io::Result<()> {\n let host = std::env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string());\n let port: u16 = std::env::var("PORT")\n .unwrap_or_else(|_| "8080".to_string())\n .parse()\n .expect("PORT must be a number");\n\n println!("Server started on {}:{}", host, port);\n\n HttpServer::new(|| {\n App::new()\n .service(health_check)\n .service(index)\n })\n .bind((host.as_str(), port))?\n .run()\n .await\n}\n\nNote: we have moved the host and port to environment variables. This is a standard practice for containerized applications — configuration should come from outside.
\n\nCheck that the application builds and runs locally:
\n\ncargo build --release\n./target/release/rust-k8s-app\n\nOpen your browser at http://localhost:8080/health — you should see a JSON response.
2. Building the Docker Image
\n\nTo deploy in Kubernetes, we need to package the application into a Docker image. We will use a multi-stage build to minimize the final image size.
\n\nCreate a Dockerfile in the project root:
# Build stage\nFROM rust:1.75-slim-bookworm AS builder\n\nWORKDIR /app\n\n# Copy only Cargo.toml for caching dependencies\nCOPY Cargo.toml Cargo.lock ./\nRUN mkdir src && echo "fn main() {}" > src/main.rs\nRUN cargo build --release 2>/dev/null || true\n\n# Now copy the actual source code\nCOPY src ./src\nRUN cargo build --release\n\n# Final image\nFROM debian:bookworm-slim\n\nRUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*\n\nCOPY --from=builder /app/target/release/rust-k8s-app /usr/local/bin/rust-k8s-app\n\nEXPOSE 8080\n\nCMD ["rust-k8s-app"]\n\nBuild the image:
\n\ndocker build -t rust-k8s-app:latest .\n\nCheck the image size