Docker e Rust: conteinerização de aplicações para produção

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
```html

Introdução: por que um desenvolvedor Rust precisa do Docker?

Rust é conhecido por seu desempenho e segurança de memória, mas mesmo o binário mais eficiente requer um ambiente adequado para ser executado. O Docker resolve esse problema, empacotando a aplicação junto com todas as suas dependências em um contêiner isolado. Neste artigo, vamos abordar como containerizar aplicações Rust com Docker, usando técnicas modernas, incluindo multi-stage build e minimização do tamanho da imagem.

A containerização de projetos Rust é especialmente vantajosa porque Rust compila para um binário estático — isso permite criar imagens mínimas (alpine ou até scratch), que são executadas mais rapidamente e com mais segurança do que equivalentes em Python ou Node.js.

1. Fundamentos: Dockerfile para uma aplicação Rust simples

Vamos começar com um servidor web simples em Rust usando o framework actix-web. Criaremos um Dockerfile básico.

1.1. Estrutura do projeto

my_rust_app/
├── Cargo.toml
├── Cargo.lock
└── src/
    └── main.rs

1.2. Exemplo de código (main.rs)

use actix_web::{get, App, HttpResponse, HttpServer, Responder};

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Olá do contêiner Rust!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(hello))
        .bind("0.0.0.0:8080")?
        .run()
        .await
}

1.3. Dockerfile simples

FROM rust:1.77 AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release
COPY src/ src/
RUN cargo build --release

FROM debian:bookworm-slim
COPY --from=builder /app/target/release/my_rust_app /usr/local/bin/
EXPOSE 8080
CMD ["my_rust_app"]

Explicação: o primeiro estágio (builder) compila a aplicação, o segundo estágio copia apenas o binário para uma imagem Debian limpa. Isso reduz o tamanho de ~2 GB para ~100 MB.

2. Multi-stage build: otimização do tamanho da imagem

O multi-stage build é uma técnica chave para Rust. Ela permite separar o ambiente de compilação (com compilador, dependências) do ambiente de execução.

2.1. Dockerfile avançado com cache

Para acelerar compilações repetidas, armazenamos as dependências em cache:

FROM rust:1.77 AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release 2>/dev/null || true
COPY src/ src/
RUN cargo build --release && \
    cp target/release/my_rust_app /app/rust_app

FROM gcr.io/distroless/cc-debian12
COPY --from=builder /app/rust_app /app/rust_app
EXPOSE 8080
CMD ["/app/rust_app"]

Por que distroless? A imagem distroless contém apenas glibc e bibliotecas básicas — sem shell, apt, ls. Isso aumenta a segurança e reduz o tamanho para ~30 MB.

2.2. Imagem mínima com scratch

Se sua aplicação não usa libc (por exemplo, escrita com #![no_std]), você pode usar scratch:

FROM rust:1.77 AS builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM scratch
COPY --from=builder /app/target/release/my_rust_app /app
EXPOSE 8080
CMD ["/app"]

Essa imagem pesa menos de 10 MB!

3. Docker Compose: aplicação multicontêiner

Frequentemente, uma aplicação Rust trabalha em conjunto com PostgreSQL, Redis ou Nginx. Usamos docker-compose.yml:

3.1. Exemplo de docker-compose.yml

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mydb
      - RUST_LOG=info
    depends_on:
      - db

  db:
    image: postgres:16-alpine
```                

Blogs

Book Recommendations