Harbor na Prática — Parte 7 Integração com GitLab CI
Nesta parte, vamos integrar o Harbor com o GitLab CI — configurando as variáveis de autenticação, buildando imagens dentro da pipeline e fazendo push automático para o Harbor a cada commit.
O fluxo que vamos construir
Developer faz push no GitLab
│
▼
GitLab CI dispara
│
▼
Build da imagem (Docker ou Kaniko)
│
▼
Login no Harbor (Robot Account)
│
▼
Push para harbor.empresa.com/projeto/app:branch-sha
│
▼
Harbor escaneia com Trivy automaticamente
Pré-requisitos
- Harbor instalado e acessível pelo GitLab Runner
- Robot Account com permissão de push e pull no projeto (veja a Parte 3)
- GitLab Runner configurado (Docker executor ou Kubernetes executor)
Passo 1 — Configurar as variáveis no GitLab
Nunca coloque credenciais diretamente no .gitlab-ci.yml. Use as variáveis de CI/CD do GitLab.
Acesse o projeto no GitLab → Settings → CI/CD → Variables → Add variable:
| Variable | Valor | Masked | Protected |
|---|---|---|---|
HARBOR_REGISTRY | harbor.empresa.com | ❌ | ❌ |
HARBOR_PROJECT | backend | ❌ | ❌ |
HARBOR_USERNAME | robot$backend+gitlab-ci | ❌ | ✅ |
HARBOR_PASSWORD | TOKEN_DO_ROBOT | ✅ | ✅ |
Dica: Marque
HARBOR_PASSWORDcomo Masked para que o valor não apareça nos logs da pipeline.
Passo 2 — Pipeline com Docker executor
Esta é a abordagem mais simples — o GitLab Runner usa Docker-in-Docker (dind) para buildar a imagem.
# .gitlab-ci.yml
stages:
- build
- push
variables:
IMAGE_NAME: $HARBOR_REGISTRY/$HARBOR_PROJECT/$CI_PROJECT_NAME
IMAGE_TAG: $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
build-and-push:
stage: build
image: docker:24
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
# Se o Harbor usa HTTP (sem TLS)
DOCKER_OPTS: "--insecure-registry=harbor.empresa.com"
before_script:
- echo "$HARBOR_PASSWORD" | docker login $HARBOR_REGISTRY
-u "$HARBOR_USERNAME" --password-stdin
script:
- docker build -t $IMAGE_NAME:$IMAGE_TAG .
- docker push $IMAGE_NAME:$IMAGE_TAG
# Tag adicional com o nome do branch
- docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:$CI_COMMIT_REF_SLUG
- docker push $IMAGE_NAME:$CI_COMMIT_REF_SLUG
after_script:
- docker logout $HARBOR_REGISTRY
only:
- main
- develop
- /^feature\/.*$/
Passo 3 — Pipeline com Kaniko (recomendado para Kubernetes executor)
O Kaniko builda imagens sem precisar de Docker daemon — ideal quando o GitLab Runner está no Kubernetes.
# .gitlab-ci.yml
stages:
- build
variables:
IMAGE_NAME: $HARBOR_REGISTRY/$HARBOR_PROJECT/$CI_PROJECT_NAME
IMAGE_TAG: $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
build-kaniko:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.23.0-debug
entrypoint: [""]
script:
# Criar o arquivo de configuração do Docker com as credenciais do Harbor
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$HARBOR_REGISTRY\":{\"auth\":\"$(echo -n $HARBOR_USERNAME:$HARBOR_PASSWORD | base64)\"}}}" > /kaniko/.docker/config.json
# Build e push em um único comando
- /kaniko/executor
--context $CI_PROJECT_DIR
--dockerfile $CI_PROJECT_DIR/Dockerfile
--destination $IMAGE_NAME:$IMAGE_TAG
--destination $IMAGE_NAME:$CI_COMMIT_REF_SLUG
--skip-tls-verify
only:
- main
- develop
- /^feature\/.*$/
O
--skip-tls-verifyé necessário apenas se o Harbor usa HTTP ou certificado autoassinado. Remova em produção com HTTPS válido.
Passo 4 — Pipeline completa com stages separados
Para pipelines mais organizadas, separando build, push e deploy:
# .gitlab-ci.yml
stages:
- build
- scan
- deploy
variables:
IMAGE_NAME: $HARBOR_REGISTRY/$HARBOR_PROJECT/$CI_PROJECT_NAME
IMAGE_TAG: $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
# --- BUILD ---
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.23.0-debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$HARBOR_REGISTRY\":{\"auth\":\"$(echo -n $HARBOR_USERNAME:$HARBOR_PASSWORD | base64)\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor
--context $CI_PROJECT_DIR
--dockerfile $CI_PROJECT_DIR/Dockerfile
--destination $IMAGE_NAME:$IMAGE_TAG
--cache=true
--cache-repo=$HARBOR_REGISTRY/$HARBOR_PROJECT/cache
only:
- main
- develop
- merge_requests
# --- SCAN (aguardar Trivy no Harbor) ---
scan:
stage: scan
image: curlimages/curl:latest
script:
# Aguardar o scan automático do Harbor completar
- sleep 30
# Verificar resultado do scan — falha se houver vulnerabilidade CRITICAL
- |
RESULT=$(curl -s \
"https://$HARBOR_REGISTRY/api/v2.0/projects/$HARBOR_PROJECT/repositories/$CI_PROJECT_NAME/artifacts/$IMAGE_TAG/additions/vulnerabilities" \
-u "$HARBOR_USERNAME:$HARBOR_PASSWORD" | \
jq '.["application/vnd.security.vulnerability.report; version=1.1"].summary.summary.Critical // 0')
if [ "$RESULT" -gt "0" ]; then
echo "❌ Scan encontrou $RESULT vulnerabilidades CRITICAL. Deploy bloqueado."
exit 1
fi
echo "✅ Scan aprovado. Nenhuma vulnerabilidade CRITICAL."
only:
- main
# --- DEPLOY (atualizar manifests no GitLab para ArgoCD) ---
deploy:
stage: deploy
image: alpine/git:latest
script:
- echo "Nova imagem: $IMAGE_NAME:$IMAGE_TAG"
# Aqui você atualizaria os manifests Kubernetes ou o values.yaml do Helm
# para o ArgoCD detectar e fazer o deploy
only:
- main
when: on_success
Trabalhando com Harbor via HTTP (sem TLS)
Se o Harbor não usa HTTPS, é preciso configurar o Docker para aceitar o registry insecuro.
No GitLab Runner com Docker executor, adicione ao /etc/docker/daemon.json do host onde o runner roda:
{
"insecure-registries": ["harbor.empresa.com:32000"]
}
Para o Kaniko, use a flag --skip-tls-verify ou --insecure:
- /kaniko/executor
--context $CI_PROJECT_DIR
--dockerfile $CI_PROJECT_DIR/Dockerfile
--destination $IMAGE_NAME:$IMAGE_TAG
--skip-tls-verify # para HTTPS com cert autoassinado
--insecure # para HTTP puro
Estratégia de tagging recomendada
O GitLab disponibiliza variáveis predefinidas muito úteis para criar tags consistentes:
| Variável GitLab | Exemplo de valor | Uso |
|---|---|---|
$CI_COMMIT_REF_SLUG | main, feature-login | Nome do branch formatado |
$CI_COMMIT_SHORT_SHA | a3f9c12 | Hash curto do commit |
$CI_PIPELINE_ID | 12345 | ID único da pipeline |
$CI_COMMIT_TAG | v1.4.2 | Tag Git (quando existe) |
Estratégia sugerida:
variables:
# Para branches normais: main-a3f9c12
IMAGE_TAG: $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
# Para tags Git (releases), usar a própria tag:
build-release:
script:
- /kaniko/executor
--destination $IMAGE_NAME:$CI_COMMIT_TAG
--destination $IMAGE_NAME:latest
only:
- tags
Verificando o resultado
Após a pipeline executar, verifique no Harbor:
Projects → backend → Repositories → nome-da-app
Você verá as tags criadas com o hash do commit, o scan de vulnerabilidades já executado e os detalhes de cada layer da imagem.
Via API:
curl -s "https://harbor.empresa.com/api/v2.0/projects/backend/repositories/minha-app/artifacts?page_size=5" \
-u "admin:suasenha" | \
jq '.[] | {tag: .tags[0].name, pushed: .push_time, scan: .scan_overview}'
Próximo artigo
Na Parte 8 — o artigo final da série — vamos configurar o Kubernetes para fazer pull de imagens privadas do Harbor usando imagePullSecrets e ServiceAccounts.