Introducción: por qué el despliegue avanzado de Rust en VPS es una necesidad
Desarrollar en Rust es solo la mitad del trabajo. La segunda parte, igualmente importante, es un despliegue confiable y seguro. Los métodos básicos, como la compilación manual y la ejecución mediante cargo run, no son adecuados para producción. A nivel avanzado se requiere automatización, aislamiento de procesos, monitoreo y garantía de alta disponibilidad.
En este artículo, analizaremos cómo configurar el despliegue de una aplicación Rust en VPS utilizando Docker, CI/CD (GitHub Actions), systemd para el inicio automático y Nginx como proxy inverso. Todos los ejemplos de código están en Rust y Bash.
1. Preparación del VPS y el entorno
1.1. Configuración básica del servidor
Supongamos que tienes un VPS con Ubuntu 22.04 LTS. Primero, actualizamos los paquetes e instalamos las herramientas necesarias:
sudo apt update && sudo apt upgrade -ysudo apt install -y curl git build-essential pkg-config libssl-devInstalamos Rust mediante rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shsource $HOME/.cargo/envrustc --version # verificación1.2. Instalación de Docker
Docker proporcionará aislamiento y reproducibilidad del entorno:
sudo apt install -y docker.iosudo systemctl enable --now dockersudo usermod -aG docker $USERnewgrp docker1.3. Instalación de Nginx
Nginx actuará como proxy inverso y balanceador de carga:
sudo apt install -y nginxsudo systemctl enable --now nginx2. Contenerización de la aplicación Rust con Docker
2.1. Compilación multi-etapa (multi-stage build)
Para reducir el tamaño de la imagen, utilizamos la compilación multi-etapa. Crea un Dockerfile en la raíz del proyecto:
# Etapa de compilaciónFROM rust:1.75-slim-bookworm AS builderWORKDIR /appCOPY Cargo.toml Cargo.lock ./COPY src ./srcRUN cargo build --release
# Etapa finalFROM debian:bookworm-slimRUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/*WORKDIR /appCOPY --from=builder /app/target/release/my_app .EXPOSE 8080CMD ["./my_app"]Aquí my_app es el nombre de tu archivo binario. Asegúrate de que en Cargo.toml esté especificado name = "my_app".
2.2. Compilación y ejecución del contenedor
docker build -t my_app:latest .docker run -d --name my_app -p 8080:8080 my_app:latestVerifica que la aplicación responda:
curl http://localhost:80803. Configuración del inicio automático y monitoreo (systemd + Docker Compose)
3.1. Docker Compose para la gestión de servicios
Crea un archivo docker-compose.yml:
version: '3.8'services: app: image: my_app:latest restart: always ports: - "127.0.0.1:8080:8080" environment: - RUST_LOG=info healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3Observa que ports está vinculado a 127.0.0.1 para que las solicitudes externas pasen solo a través de Nginx.
3.2. Unidad de systemd para la gestión del servicio
Crea el archivo /etc/systemd/system/my_app.service:
[Unit]Description=My Rust ApplicationAfter=docker.serviceRequires=docker.service
[Service]Type=oneshotRemainAfterExit=yesWorkingDirectory=/opt/my_appExecStart=/usr/bin/docker compose up -dExecStop=/usr/bin/docker compose downUser=deployGroup=deploy
[Install]WantedBy=multi-user.targetHabilítalo e inícialo:
sudo systemctl daemon-reloadsudo systemctl enable my_appsudo systemctl start my_app