Skip to content

Deployment

Deployment

Docker

Multi-stage Build

# Dockerfile
FROM rust:1.79 AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src ./src
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/my-api /usr/local/bin/my-api
EXPOSE 3000
CMD ["my-api"]

Docker Compose

docker-compose.yml
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/myapp
- RUST_LOG=info
- APM_SERVICE_NAME=my-api
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:

Environment Configuration

Use config crate with environment-specific files:

src/config.rs
use config::{Config, File, Environment};
use serde::Deserialize;
#[derive(Deserialize)]
pub struct Settings {
pub server: ServerConfig,
pub database: DatabaseConfig,
pub apm: ApmConfig,
pub logger: LoggerConfig,
}
#[derive(Deserialize)]
pub struct ServerConfig {
pub host: String,
pub port: u16,
}
#[derive(Deserialize)]
pub struct DatabaseConfig {
pub url: String,
pub max_connections: u32,
}
#[derive(Deserialize)]
pub struct ApmConfig {
pub service_name: String,
pub log_path: String,
}
#[derive(Deserialize)]
pub struct LoggerConfig {
pub min_level: String,
pub classifications: Vec<ClassificationConfig>,
}
impl Settings {
pub fn new() -> Result<Self, config::ConfigError> {
let env = std::env::var("APP_ENV").unwrap_or_else(|_| "development".into());
Config::builder()
.add_source(File::with_name("config/default"))
.add_source(File::with_name(&format!("config/{}", env)).required(false))
.add_source(Environment::with_prefix("APP").separator("__"))
.build()?
.try_deserialize()
}
}
config/
├── default.toml
├── development.toml
├── production.toml
└── test.toml
config/default.toml
[server]
host = "0.0.0.0"
port = 3000
[database]
max_connections = 10
[apm]
service_name = "my-api"
log_path = "apm.ndjson"
[logger]
min_level = "info"
classifications = [
{ name = "PUBLIC", path = "public.ndjson" },
{ name = "CONFIDENTIAL", path = "confidential.ndjson" }
]
config/production.toml
[server]
host = "0.0.0.0"
port = 8080
[database]
url = "postgres://user:pass@host:5432/db"
max_connections = 50
[logger]
min_level = "warn"

Production Checklist