Skip to main content
  1. Blogs/

Rust: Optimización de Imagen de Docker con GitLab CI

·671 words·4 mins· loading · loading ·
tutorial docker rust gitlab
Table of Contents

Como describí acá, una forma de optimizar la imagen de Docker de tu aplicación Rust, es mediante las construcciones en múltiples etapas. En la primera etapa, construyes la aplicación y obtienes el binario, y en la segunda etapa construyes la imagen final que contiene solo el binario generado previamenete. De esta manera, obtendrás una imagen de Docker más pequeña. El Dockerfile para la construcción de múltiples etapas se muestra a continuación:

FROM rust:latest AS builder
WORKDIR /app

COPY Cargo.toml .
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release

COPY src src
RUN touch src/main.rs
RUN cargo build --release

RUN strip target/release/hello_rocket

FROM gcr.io/distroless/cc-debian12 as release
WORKDIR /app
COPY --from=builder /app/target/release/hello_rocket .

ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=8000
EXPOSE 8000

CMD ["./hello_rocket"]

Otra opción es usar GitLab CI. A través de este artículo, aprenderás como usar GitLab CI para construir una imagen de Docker optimizada de tu aplicación.

GitLab CI
#

Primero, crea un repositorio de GitLab para tu proyecto.

En seguida, crea el ejemplo de Hello, world! con Rocket, en tu entorno local.

Crea un nuevo proyecto:

$ cargo new hello_rocket

Cámbiate al directorio del proyecto:

$ cd hello_rocket

Reemplaza el contenido de src/main.rs con lo siguiente:

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index])
}

Edita el archivo Cargo.toml y agrega la dependencia correspondiente:

[package]
name = "hello_rocket"
version = "0.1.0"
edition = "2021"

[dependencies]
rocket = "=0.5.0-rc.3"

El código anterior mostrará el texto Hello, world! en el navegador. Ahora, sincroniza tu repositorio con el código de tu aplicación

Crea un Dockerfile en tu repositorio, con el siguiente contenido:

FROM gcr.io/distroless/cc-debian12

WORKDIR /app

COPY /target/release/hello_rocket .

ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=8000
EXPOSE 8000

CMD ["./hello_rocket"]

Estoy usando una imagen distroless para evitar obtener algún error al ejecutar el contenedor.

Antes de crear el archivo de configuración de GitLab CI, .gitlab-ci.yml, ve a SettingsCI/CD y agrega las siguientes variables:

  • CI_REGISTRY_USER. Escribe tu usuario de Docker Hub en el campo Value
  • CI_REGISTRY_PASSWORD. En el campo Value, escribe la constraseña de usuario de Docker Hub
  • CI_REGISTRY. Escribe docker.io en el campo Value
  • CI_REGISTRY_IMAGE. En el campo Value, escribe index.docker.io/username/hello-rocket

username es tu usuario de Docker Hub. hello-rocket es el nombre del repositorio de Docker Hub donde la imagen estará disponible.

Y finalmente, crea el archivo .gitlab-ci.yml en tu repositorio, con el siguiente contenido:

stages:
    - build
    - deploy

build-app:
    image: rust:latest
    stage: build
    script:
        - cargo build --release
        - strip target/release/hello_rocket
    artifacts:
        paths:
            - target/

docker-build:
  # Official docker image.
  image: docker:latest
  stage: deploy
  services:
    - docker:dind
  before_script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - docker build --pull -t "$CI_REGISTRY_IMAGE" .
    - docker push "$CI_REGISTRY_IMAGE"
  dependencies:
    - build-app

En el primer trabajo (build-app) de tu pipeline de CI/CD:

  • La aplicación es construida (cargo build --release)
  • Se remueve la información innecesaria del binario, reduciendo su tamaño y haciendo que sea más difícil realizar ingeniería inversa
  • Con artefactos de trabajo, el contenido del directorio target se almacena y se pasa al siguiente trabajo

En el segundo trabajo (docker-build), se construye la imagen de Docker, usando un Dockerfile, y se publica en Docker Hub. Para este ejemplo, publicarás la imagen de Docker que contiene tu aplicación en Docker Hub, y puedes reemplazar las instrucciones si estás publicando directamente en cualquier plataforma en la nube. Para usar los artefactos, debes especificar el primer trabajo como dependencia.

Cuando se inicia el segundo trabajo, se descargan los artefactos del trabajo anterior, y con la siguiente instrucción, se copian a la imagen de Docker que se generará con el Dockerfile:

COPY /target/release/hello_rocket .

Después de que el pipeline de CI/CD termine, podrías usar la imagen de Docker Hub para iniciar un contenedor y ejecutar la aplicación.

$ docker run -p 8000:8000 --name hello-rocket username/hello-rocket

Y puedes ir a localhost:8000 en el navegador.

Conclusión
#

A través de este artículo, aprendiste a usar GitLab CI y artefactos de trabajo para construir una imagen de Docker optimizada de tu aplicación.

Related

Rust: Optimización de Imagen de Docker con Construcciones de Múltiples Etapas
·1034 words·5 mins· loading · loading
tutorial docker rust
Desplegar un Clúster de MongoDB con Docker Compose
·519 words·3 mins· loading · loading
tutorial docker linux mongodb
Docker Swarm con Máquinas Virtuales usando Multipass
·1148 words·6 mins· loading · loading
tutorial docker virtualization
Almacenamiento de Objetos con MinIO en Docker
·637 words·3 mins· loading · loading
tutorial docker linux
Ejecutar Percona Backup for MongoDB con Docker
·969 words·5 mins· loading · loading
tutorial docker linux mongodb