DEV Community

Cover image for Deploy de uma api em rust em cloudrun através de pipeline com gitlab
Rodrigo Burgos
Rodrigo Burgos

Posted on

Deploy de uma api em rust em cloudrun através de pipeline com gitlab

Post genuíno, em português e escrito por mim (gpt revisou hehehe). Tentarei ser o máximo objetivo possível mas sinta-se convidado a discutir abordagens ou tirar dúvidas por dm ou nos comentários.

  1. API

A abordagem que utilizei para esta api é a de DDD (domain drive design). Não vou me demorar muito no desenvolvimento da api em sí, vou focar no m̀ain.rs e na árvore de arquivos.

use test_api::infra::handler::health::get_health_handler;
use tokio;
use warp::Filter;

#[tokio::main]
async fn main() {
    // Define the route
    let get_health_route = warp::path("health")
        .and(warp::get())
        .and_then(get_health_handler);

    // Start the warp server
    warp::serve(get_health_route)
        .run(([0, 0, 0, 0], 8080))
        .await;
}

Enter fullscreen mode Exit fullscreen mode
├── Cargo.toml
├── Dockerfile
├── REAME.md
├── src
│   ├── domain
│   │   ├── entities
│   │   └── use_case
│   ├── infra
│   │   └── handler
│   ├── lib.rs
│   ├── main.rs
│   └── use_case
│       └── get_health
└── target
    ├── CACHEDIR.TAG
    └── debug
        ├── build
        ├── deps
        ├── examples
        └── incremental

15 directories, 6 files

Enter fullscreen mode Exit fullscreen mode

Pontos importantes para focar são os paramêtros do run do warp/serve:

.run(([0, 0, 0, 0], 8080))

Para que o container seja acessado externamente.

  1. Dockerfile
# Etapa 1: Builder com Rust + OpenSSL
FROM rust:latest AS builder

RUN apt-get update && apt-get install -y pkg-config libssl-dev

WORKDIR /usr/src/test_api

# Copia arquivos do crate
COPY Cargo.toml ./
COPY src ./src

# Gera lockfile e baixa dependências
RUN cargo generate-lockfile
RUN cargo build --release

# Etapa 2: Imagem final com compatibilidade glibc
FROM debian:bookworm-slim

# Instala OpenSSL e dependências mínimas de runtime
RUN apt-get update && apt-get install -y libssl3 ca-certificates && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY --from=builder /usr/src/test_api/target/release/test_api .

ENV PORT=8080
EXPOSE 8080

CMD ["./test_api"]
Enter fullscreen mode Exit fullscreen mode
  1. Gitlab
stages:
    - deploy_cloud_run

deploy_cloud_run:
    stage: deploy_cloud_run
    tags: [temp]
    environment:
        name: dev
    rules:
        - if: '$CI_COMMIT_BRANCH == "dev" && $CI_PIPELINE_SOURCE == "push"'
          changes:
              - **/*
          when: always
        - when: never
    before_script:
        - mkdir -p "$CI_PROJECT_DIR/.tmp/google-cloud-sdk"
        - curl -sSL "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-438.0.0-linux-x86_64.tar.gz" | tar -xz -C "$CI_PROJECT_DIR/.tmp/google-cloud-sdk" --strip-components=1
        - export PATH="$CI_PROJECT_DIR/.tmp/google-cloud-sdk/bin:$PATH"
        - echo "$SERVICE_ACCOUNT_JSON" | base64 -d > gcloud-key.json
        - gcloud auth activate-service-account --key-file=gcloud-key.json
        - export GCP_PROJECT_ID="seu-projeto"
        - gcloud config set project "$GCP_PROJECT_ID"
        - gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
    script:
        - |
            IMAGE_TAG="$(git rev-parse --short HEAD)"
            IMAGE_URI="us-central1-docker.pkg.dev/seu-repo/api/test-api:${IMAGE_TAG}"

            docker build \
              -t "$IMAGE_URI" \
              -f test_api/Dockerfile \
              test_api

            docker push "$IMAGE_URI"

            gcloud run deploy api-dev \
              --image "$IMAGE_URI" \
              --platform managed \
              --region us-central1 \
              --allow-unauthenticated \
              --project "$GCP_PROJECT_ID" \
              --set-env-vars "ENVIRONMENT=staging"
    after_script:
        - rm -f gcloud-key.json
Enter fullscreen mode Exit fullscreen mode

Permissões qua service account necessita para rodar esse job:

gcloud projects add-iam-policy-binding seu-projeto \ --member="serviceAccount:service-account@project.iam.gserviceaccount.com" \ --role="roles/run.admin"

gcloud projects add-iam-policy-binding seu-projeto \ --member="serviceAccount:service-account@project.iam.gserviceaccount.com" \ --role="roles/viewer"

gcloud projects add-iam-policy-binding seu-projeto \ --member="serviceAccount:service-account@project.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountUser"
Enter fullscreen mode Exit fullscreen mode

O json da SA deve ser armazenado como segredo do Gitlab.

Dentro da sua gitlab dashboard, na sessão de jobs, deve existir um output como esse:

Service [api-dev] revision [sua-api-00000-pez] has been deployed and is serving 100 percent of traffic.
Service URL: https://sua-api-hash-uc.a.run.app
Enter fullscreen mode Exit fullscreen mode

Se tudo deu certo, utilizando curl para interagir com o endpoint health:

curl https://sua-api-hash-uc.a.run.app/health
{"health_status":{"status":"healthy","message":"API is working fine"}}%
Enter fullscreen mode Exit fullscreen mode

Repositório da api aqui.

Espero que, na eventualidade de você se encontrar travado com um procedimento como esse, ou parecido, essa postagem te ajuda a desimpedir (:

Top comments (0)