# Dockerfile# Multi-stage build for Rust applications# Build stageFROMrust:1.75-slimasbuilder# Set working directoryWORKDIR/app# Install system dependenciesRUNapt-getupdate&&apt-getinstall-y\pkg-config\libssl-dev\&&rm-rf/var/lib/apt/lists/*
# Copy Cargo filesCOPYCargo.tomlCargo.lock./
# Create a dummy main.rs to cache dependenciesRUNmkdirsrc&&echo"fn main() {}">src/main.rs
# Build dependencies (this layer will be cached)RUNcargobuild--release
# Copy source codeCOPYsrc./src
# Build the actual applicationRUNcargobuild--release
# Runtime stageFROMdebian:bookworm-slim# Install runtime dependenciesRUNapt-getupdate&&apt-getinstall-y\ca-certificates\&&rm-rf/var/lib/apt/lists/*
# Create non-root userRUNgroupadd-rappuser&&useradd-r-gappuserappuser
# Copy binary from builder stageCOPY--from=builder/app/target/release/myapp/usr/local/bin/myapp
# Set ownershipRUNchownappuser:appuser/usr/local/bin/myapp
# Switch to non-root userUSERappuser# Expose portEXPOSE8080# Health checkHEALTHCHECK--interval=30s--timeout=3s--start-period=5s--retries=3\CMDcurl-fhttp://localhost:8080/health||exit1# Run the applicationCMD["myapp"]
# Dockerfile.optimized# Optimized Dockerfile for Rust applications# Use distroless base image for minimal attack surfaceFROMgcr.io/distroless/cc-debian12# Copy the binaryCOPY--from=builder/app/target/release/myapp/usr/local/bin/myapp
# Set the entrypointENTRYPOINT["/usr/local/bin/myapp"]
// rust/01-container-security.rs/*Container security patterns and best practices*/usestd::env;usestd::process;usestd::fs;usestd::path::Path;/// Container security configuration.pubstructContainerSecurity{user_id:Option<u32>,group_id:Option<u32>,read_only_root:bool,no_new_privileges:bool,seccomp_profile:Option<String>,apparmor_profile:Option<String>,}implContainerSecurity{pubfnnew()->Self{Self{user_id:None,group_id:None,read_only_root:false,no_new_privileges:false,seccomp_profile:None,apparmor_profile:None,}}/// Set user and group IDs for security.pubfnset_user_group(&mutself,user_id:u32,group_id:u32){self.user_id=Some(user_id);self.group_id=Some(group_id);}/// Enable read-only root filesystem.pubfnenable_read_only_root(&mutself){self.read_only_root=true;}/// Enable no new privileges.pubfnenable_no_new_privileges(&mutself){self.no_new_privileges=true;}/// Set seccomp profile.pubfnset_seccomp_profile(&mutself,profile:String){self.seccomp_profile=Some(profile);}/// Set AppArmor profile.pubfnset_apparmor_profile(&mutself,profile:String){self.apparmor_profile=Some(profile);}/// Apply security configuration.pubfnapply(&self)->Result<(),String>{// Set user and group IDsifletSome(uid)=self.user_id{ifletSome(gid)=self.group_id{self.set_user_group_ids(uid,gid)?;}}// Enable read-only root if requestedifself.read_only_root{self.enable_read_only_root_fs()?;}// Enable no new privileges if requestedifself.no_new_privileges{self.enable_no_new_privileges()?;}Ok(())}/// Set user and group IDs.fnset_user_group_ids(&self,uid:u32,gid:u32)->Result<(),String>{// In a real implementation, you would use libc functions// to set the user and group IDsprintln!("Setting user ID to {} and group ID to {}",uid,gid);Ok(())}/// Enable read-only root filesystem.fnenable_read_only_root_fs(&self)->Result<(),String>{// In a real implementation, you would remount the root filesystem// as read-onlyprintln!("Enabling read-only root filesystem");Ok(())}/// Enable no new privileges.fnenable_no_new_privileges(&self)->Result<(),String>{// In a real implementation, you would use prctl to set// PR_SET_NO_NEW_PRIVSprintln!("Enabling no new privileges");Ok(())}}/// Container health checker.pubstructContainerHealthChecker{health_endpoint:String,timeout:std::time::Duration,interval:std::time::Duration,}implContainerHealthChecker{pubfnnew(health_endpoint:String)->Self{Self{health_endpoint,timeout:std::time::Duration::from_secs(5),interval:std::time::Duration::from_secs(30),}}/// Check container health.pubasyncfncheck_health(&self)->Result<bool,String>{// In a real implementation, you would make an HTTP request// to the health endpointprintln!("Checking health at {}",self.health_endpoint);// Simulate health checkOk(true)}/// Start health checking loop.pubasyncfnstart_health_checking(&self)->Result<(),String>{letmutinterval_timer=tokio::time::interval(self.interval);loop{interval_timer.tick().await;matchself.check_health().await{Ok(true)=>{println!("Health check passed");}Ok(false)=>{println!("Health check failed");process::exit(1);}Err(e)=>{println!("Health check error: {}",e);process::exit(1);}}}}}/// Container resource limits.pubstructContainerResourceLimits{memory_limit:Option<u64>,cpu_limit:Option<f64>,file_descriptor_limit:Option<u64>,}implContainerResourceLimits{pubfnnew()->Self{Self{memory_limit:None,cpu_limit:None,file_descriptor_limit:None,}}/// Set memory limit in bytes.pubfnset_memory_limit(&mutself,limit:u64){self.memory_limit=Some(limit);}/// Set CPU limit as a fraction (e.g., 0.5 for 50%).pubfnset_cpu_limit(&mutself,limit:f64){self.cpu_limit=Some(limit);}/// Set file descriptor limit.pubfnset_file_descriptor_limit(&mutself,limit:u64){self.file_descriptor_limit=Some(limit);}/// Apply resource limits.pubfnapply(&self)->Result<(),String>{ifletSome(memory_limit)=self.memory_limit{self.set_memory_limit(memory_limit)?;}ifletSome(cpu_limit)=self.cpu_limit{self.set_cpu_limit(cpu_limit)?;}ifletSome(fd_limit)=self.file_descriptor_limit{self.set_file_descriptor_limit(fd_limit)?;}Ok(())}/// Set memory limit.fnset_memory_limit(&self,limit:u64)->Result<(),String>{// In a real implementation, you would use cgroups or similar// to set memory limitsprintln!("Setting memory limit to {} bytes",limit);Ok(())}/// Set CPU limit.fnset_cpu_limit(&self,limit:f64)->Result<(),String>{// In a real implementation, you would use cgroups or similar// to set CPU limitsprintln!("Setting CPU limit to {}",limit);Ok(())}/// Set file descriptor limit.fnset_file_descriptor_limit(&self,limit:u64)->Result<(),String>{// In a real implementation, you would use setrlimit// to set file descriptor limitsprintln!("Setting file descriptor limit to {}",limit);Ok(())}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_container_security(){letmutsecurity=ContainerSecurity::new();security.set_user_group(1000,1000);security.enable_read_only_root();security.enable_no_new_privileges();assert!(security.apply().is_ok());}#[test]fntest_container_health_checker(){letchecker=ContainerHealthChecker::new("/health".to_string());assert_eq!(checker.health_endpoint,"/health");}#[test]fntest_container_resource_limits(){letmutlimits=ContainerResourceLimits::new();limits.set_memory_limit(1024*1024*1024);// 1GBlimits.set_cpu_limit(0.5);// 50%limits.set_file_descriptor_limit(1024);assert!(limits.apply().is_ok());}}
// rust/03-container-testing.rs/*Container testing patterns and best practices*/usestd::process::{Command,Stdio};usestd::time::Duration;usetokio::time::timeout;/// Container test runner.pubstructContainerTestRunner{image_name:String,container_name:String,test_timeout:Duration,}implContainerTestRunner{pubfnnew(image_name:String,container_name:String)->Self{Self{image_name,container_name,test_timeout:Duration::from_secs(30),}}/// Set test timeout.pubfnset_test_timeout(&mutself,timeout:Duration){self.test_timeout=timeout;}/// Run container tests.pubasyncfnrun_tests(&self)->Result<TestResults,String>{letmutresults=TestResults::new();// Test 1: Container starts successfullyifletErr(e)=self.test_container_start().await{results.add_failure("Container start test".to_string(),e);}else{results.add_success("Container start test".to_string());}// Test 2: Health check passesifletErr(e)=self.test_health_check().await{results.add_failure("Health check test".to_string(),e);}else{results.add_success("Health check test".to_string());}// Test 3: Application respondsifletErr(e)=self.test_application_response().await{results.add_failure("Application response test".to_string(),e);}else{results.add_success("Application response test".to_string());}// Test 4: Resource usage is within limitsifletErr(e)=self.test_resource_usage().await{results.add_failure("Resource usage test".to_string(),e);}else{results.add_success("Resource usage test".to_string());}// Test 5: Security scan passesifletErr(e)=self.test_security_scan().await{results.add_failure("Security scan test".to_string(),e);}else{results.add_success("Security scan test".to_string());}Ok(results)}/// Test container start.asyncfntest_container_start(&self)->Result<(),String>{letoutput=Command::new("docker").args(&["run","--rm","-d","--name",&self.container_name,&self.image_name]).output().map_err(|e|format!("Failed to start container: {}",e))?;if!output.status.success(){returnErr("Container failed to start".to_string());}// Wait for container to be readytokio::time::sleep(Duration::from_secs(5)).await;Ok(())}/// Test health check.asyncfntest_health_check(&self)->Result<(),String>{letoutput=Command::new("docker").args(&["exec",&self.container_name,"curl","-f","http://localhost:8080/health"]).output().map_err(|e|format!("Failed to run health check: {}",e))?;if!output.status.success(){returnErr("Health check failed".to_string());}Ok(())}/// Test application response.asyncfntest_application_response(&self)->Result<(),String>{letoutput=Command::new("docker").args(&["exec",&self.container_name,"curl","-f","http://localhost:8080/"]).output().map_err(|e|format!("Failed to test application response: {}",e))?;if!output.status.success(){returnErr("Application response test failed".to_string());}Ok(())}/// Test resource usage.asyncfntest_resource_usage(&self)->Result<(),String>{letoutput=Command::new("docker").args(&["stats","--no-stream","--format","table {{.MemUsage}}",&self.container_name]).output().map_err(|e|format!("Failed to check resource usage: {}",e))?;if!output.status.success(){returnErr("Resource usage check failed".to_string());}// Parse memory usage and check if it's within limitsletoutput_str=String::from_utf8_lossy(&output.stdout);ifoutput_str.contains("GiB"){returnErr("Memory usage too high".to_string());}Ok(())}/// Test security scan.asyncfntest_security_scan(&self)->Result<(),String>{letoutput=Command::new("docker").args(&["run","--rm","-v","/var/run/docker.sock:/var/run/docker.sock","aquasec/trivy","image",&self.image_name]).output().map_err(|e|format!("Failed to run security scan: {}",e))?;if!output.status.success(){returnErr("Security scan failed".to_string());}// Check for high severity vulnerabilitiesletoutput_str=String::from_utf8_lossy(&output.stdout);ifoutput_str.contains("HIGH")||output_str.contains("CRITICAL"){returnErr("High severity vulnerabilities found".to_string());}Ok(())}/// Clean up test container.pubasyncfncleanup(&self)->Result<(),String>{let_=Command::new("docker").args(&["stop",&self.container_name]).output();let_=Command::new("docker").args(&["rm",&self.container_name]).output();Ok(())}}/// Test results container.pubstructTestResults{successes:Vec<String>,failures:Vec<(String,String)>,}implTestResults{pubfnnew()->Self{Self{successes:Vec::new(),failures:Vec::new(),}}/// Add a successful test.pubfnadd_success(&mutself,test_name:String){self.successes.push(test_name);}/// Add a failed test.pubfnadd_failure(&mutself,test_name:String,error:String){self.failures.push((test_name,error));}/// Get test summary.pubfnget_summary(&self)->String{lettotal_tests=self.successes.len()+self.failures.len();letpassed_tests=self.successes.len();letfailed_tests=self.failures.len();format!("Tests: {} total, {} passed, {} failed",total_tests,passed_tests,failed_tests)}/// Get detailed results.pubfnget_details(&self)->String{letmutdetails=String::new();details.push_str("=== Test Results ===\n");details.push_str(&self.get_summary());details.push_str("\n\n");if!self.successes.is_empty(){details.push_str("Passed tests:\n");forsuccessin&self.successes{details.push_str(&format!(" ✓ {}\n",success));}details.push_str("\n");}if!self.failures.is_empty(){details.push_str("Failed tests:\n");for(test_name,error)in&self.failures{details.push_str(&format!(" ✗ {}: {}\n",test_name,error));}}details}/// Check if all tests passed.pubfnall_passed(&self)->bool{self.failures.is_empty()}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_test_results(){letmutresults=TestResults::new();results.add_success("Test 1".to_string());results.add_failure("Test 2".to_string(),"Error".to_string());assert!(!results.all_passed());assert_eq!(results.successes.len(),1);assert_eq!(results.failures.len(),1);}#[test]fntest_container_test_runner(){letrunner=ContainerTestRunner::new("test-image".to_string(),"test-container".to_string(),);assert_eq!(runner.image_name,"test-image");assert_eq!(runner.container_name,"test-container");}}