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

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

Introdução: Por que Docker e Rust são a dupla perfeita

Rust é uma linguagem de programação de sistemas moderna, conhecida por seu desempenho e segurança de memória. No entanto, para entregar uma aplicação Rust ao usuário final ou à nuvem, é necessário resolver o problema do ambiente. É aqui que o Docker entra em ação. A conteinerização permite empacotar uma aplicação Rust junto com todas as suas dependências em um contêiner leve e isolado. Neste artigo, vamos explorar como criar uma imagem Docker eficiente e mínima para um projeto Rust, usando as melhores práticas.



1. Fundamentos do Docker para desenvolvedores Rust

Docker é uma plataforma para desenvolvimento, entrega e execução de aplicações em contêineres. O contêiner inclui a própria aplicação e tudo o que é necessário para seu funcionamento: bibliotecas, utilitários do sistema e configurações. Para Rust, isso é especialmente relevante, pois o binário compilado não depende de um runtime (ao contrário de Python ou Node.js), permitindo criar imagens muito pequenas.

Os principais componentes que você precisará:

  • Dockerfile — arquivo de texto com instruções para construir a imagem.
  • .dockerignore — arquivo que exclui arquivos desnecessários do contexto de build.
  • Docker Compose (opcional) — para orquestrar múltiplos contêineres.

Antes de começar, certifique-se de ter instalado o Docker Desktop ou o Docker Engine.



2. Criando um Dockerfile para uma aplicação Rust

Vamos considerar um exemplo simples de servidor web em Rust usando o framework actix-web. Nosso arquivo principal main.rs é assim:

use actix_web::{web, App, HttpServer, Responder};

async fn index() -> impl Responder { "Hello, Docker and Rust!"}

#[actix_web::main]async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().route("/", web::get().to(index)) }) .bind("0.0.0.0:8080")? .run() .await}

Agora vamos criar o Dockerfile. A técnica mais importante aqui é o multi-stage build. Ela permite primeiro compilar a aplicação em um ambiente com o conjunto completo de ferramentas Rust e, em seguida, copiar o binário pronto para uma imagem final mínima.

// ---- Primeiro estágio: build ----FROM rust:1.75 as builder

WORKDIR /app

// Copiamos os manifestos para cachear as dependênciasCOPY Cargo.toml Cargo.lock ./

// Criamos um main.rs vazio para compilar as dependênciasRUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || true

// Agora copiamos o código fonte realCOPY src ./src

// Compilamos o binário final (o cache das dependências já existe)RUN cargo build --release

// ---- Segundo estágio: imagem final ----FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app

// Copiamos o binário do primeiro estágioCOPY --from=builder /app/target/release/my_rust_app .

EXPOSE 8080

CMD ["./my_rust_app"]

Observe o truque com o main.rs vazio. Isso permite que o Docker armazene em cache as dependências compiladas (crates) e não as recompile toda vez que você alterar apenas o código fonte. Isso acelera significativamente as compilações subsequentes.



2.1. Otimizando o tamanho da imagem

A imagem final baseada em debian:bookworm-slim pesa cerca de 80-100 MB. No entanto, se você quiser uma imagem realmente mínima, pode usar scratch (imagem vazia) ou alpine. Para aplicações Rust compiladas estaticamente, esta é a opção ideal. Para isso, é necessário alterar o target de compilação:

// No primeiro estágio (builder):RUN rustup target add x86_64-                

Blogs

Book Recommendations