Pipeline CI/CD no GitLab para Blog Jekyll com Docker
Introdução
O Jekyll é uma ferramenta poderosa para criar sites estáticos a partir de arquivos Markdown, ideal para blogs e documentações. Combinando Jekyll com uma pipeline CI/CD no GitLab, Docker para contêineres e Nginx como proxy reverso, garantimos:
- Automatização do processo de publicação.
- Manutenção de um ambiente leve e portátil.
- Alto desempenho, com suporte a HTTPS.
Neste tutorial, você aprenderá a:
- Configurar um repositório no GitLab.
- Construir e publicar imagens Docker.
- Configurar um pipeline CI/CD para deploy automático.
- Implementar um proxy reverso com Nginx e SSL.
Arquitetura do Projeto
Fluxo do Pipeline CI/CD
- Commit: O desenvolvedor realiza alterações e faz push no GitLab.
- Pipeline: Jobs automatizados constroem a imagem Docker, verificam erros e publicam no Docker Hub.
- Deploy: A imagem é usada para rodar um contêiner na VPS.
- Nginx: Atua como proxy reverso para servir o site com HTTPS.
Componentes
- GitLab CI/CD: Automatiza build e deploy.
- Docker: Empacota o site estático gerado pelo Jekyll.
- Nginx: Gerencia solicitações HTTP/HTTPS.
- Certbot: Configura SSL gratuito.
1. Configurando o Projeto no GitLab
Nesta etapa, configuraremos o repositório no GitLab e prepararemos o tema Chirpy-Starter para começar a construção do blog.
1.1 Criar o Repositório no GitLab
- Faça login no GitLab.
- Navegue para Menu > Projects > New Project.
- Clique em Create Blank Project.
- Preencha os campos:
- Project name:
jekyll-blog
. - Visibility Level: Escolha
Private
(somente você) ouPublic
(visível a todos).
- Project name:
- Clique em Create Project.
1.2 Configurar o Tema Chirpy-Starter
O Chirpy-Starter oferece um design responsivo e funcionalidades integradas como SEO e tabelas de conteúdo automáticas.
- Clone o repositório oficial:
1 2 3 4 5
mkdir jekyll-blog cd jekyll-blog/ git clone https://github.com/cotes2020/chirpy-starter.git chirpy-temp cp -r chirpy-temp/* . rm -rf chirpy-temp
- Configure o repositório para o seu GitLab:
1 2 3 4 5
git init --initial-branch=main git remote add origin https://gitlab.com/seu-usuario/jekyll-blog.git git add . git commit -m "Initial commit" git push -u origin main
1.3 Verificar os Arquivos no Repositório
- Acesse o repositório no GitLab.
- Confirme se todos os arquivos foram carregados corretamente.
1.4 Criar Token de Acesso no Docker Hub
Acessar o Docker Hub
- Acesse sua conta no Docker Hub.
- Faça login com seu nome de usuário e senha.
Navegar para as Configurações de Token
- Clique no seu avatar ou nome de usuário no canto superior direito.
- Vá para Account Settings > Security > New Access Token.
Criar o Token
- Na página de tokens, clique em Create Access Token.
- Insira um nome descritivo para o token, como
gitlab-ci-token
. - Selecione Read/Write nas permissões.
- Clique em Generate.
Salvar o Token
- Copie o token gerado.
- Guarde o token em um local seguro, pois você não poderá visualizá-lo novamente.
1.5 Criar Variáveis de Acesso do Docker Hub no Projeto do GitLab
Acessar Configurações de CI/CD no GitLab
- Acesse o repositório no GitLab.
- No menu lateral, clique em Settings > CI/CD.
Adicionar Variáveis do Docker Hub
- Role a página até a seção Variables e clique em Expand.
- Clique em Add Variable para criar cada variável necessária:
DOCKER_USERNAME
:- Valor: seu nome de usuário no Docker Hub.
- Tipo:
Variable
. - Protegida: Marque se só será usada em branches protegidas.
DOCKER_PASSWORD
:- Valor: o token gerado no Docker Hub.
- Tipo:
Variable
. - Protegida: Marque se só será usada em branches protegidas.
Salvar e Testar
- Após adicionar as variáveis, clique em Save Variables.
- Verifique se as variáveis foram salvas corretamente.
2. Criando o Dockerfile e Preparando o Ambiente de Build
O Dockerfile define como a imagem do contêiner será construída, encapsulando o Jekyll e suas dependências em um ambiente isolado. Usaremos um multi-stage build para criar uma imagem otimizada.
2.1 Criar o Dockerfile
- No diretório raiz do projeto, crie um arquivo chamado
Dockerfile
:1
touch Dockerfile
- Edite o
Dockerfile
com o seguinte conteúdo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Etapa 1: Construir os arquivos estáticos com Jekyll
FROM ruby:3.2-bullseye AS builder
# Instalar dependências
RUN apt-get update && apt-get install -y \
build-essential \
ruby-dev \
gcc \
g++ \
make \
libffi-dev \
libyaml-dev \
zlib1g-dev \
git \
curl \
nodejs \
npm \
&& rm -rf /var/lib/apt/lists/*
# Definir diretório de trabalho
WORKDIR /app
# Copiar e instalar dependências Ruby
COPY Gemfile ./
RUN bundle install
# Copiar o restante do projeto
COPY . .
# Gerar os arquivos estáticos do site
RUN bundle exec jekyll build --destination /app/_site
# Etapa 2: Servir os arquivos estáticos com Nginx
FROM nginx:1.27-alpine
# Copiar os arquivos estáticos gerados
COPY --from=builder /app/_site /usr/share/nginx/html
# Expor a porta padrão do Nginx
EXPOSE 80
# Rodar o Nginx
CMD ["nginx", "-g", "daemon off;"]
2.2 Explicando o Dockerfile
- Fase de Construção (
builder
):- Usa a imagem leve
ruby:3.3-alpine
para instalar o Jekyll. - Instala todas as dependências necessárias e compila o site para a pasta
_site
.
- Usa a imagem leve
- Fase de Produção:
- Usa
nginx:1.27-alpine
para servir o site estático gerado. - Apenas os arquivos necessários são copiados, reduzindo o tamanho final da imagem.
- Usa
2.3 Testar o Dockerfile Localmente
- Construa a imagem Docker:
1
docker build -t jekyll-blog .
- Execute o contêiner para testar:
1
docker run -d --name jekyll-container -p 8080:80 jekyll-blog
-
Acesse o site em: http://localhost:8080
- Verifique os logs do contêiner (se necessário):
1
docker logs jekyll-container
2.4 Otimizações e Boas Práticas
- Cache de Dependências: Use cache para acelerar builds futuros:
1
RUN bundle config set path 'vendor/bundle' && bundle install
- Verificação de Vulnerabilidades: Use o Trivy para escanear a imagem:
1
trivy image jekyll-blog
- Reduza o Tamanho da Imagem: Certifique-se de que apenas os arquivos essenciais são copiados para a fase de produção.
3. Configurando o Pipeline CI/CD no GitLab
Agora, vamos configurar o pipeline CI/CD no GitLab para automatizar a construção, teste e deploy do blog Jekyll. O pipeline será definido no arquivo .gitlab-ci.yml
.
3.1 Criar o Arquivo .gitlab-ci.yml
- No diretório raiz do projeto, crie o arquivo
.gitlab-ci.yml
:1
touch .gitlab-ci.yml
- Adicione o seguinte conteúdo básico ao arquivo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
stages:
- build
- deploy
variables:
IMAGE_NAME: $DOCKER_USERNAME/chirpy-starter # Nome da imagem no Docker Hub
# Job para construir e enviar a imagem para o Docker Hub
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- echo "=== Logando no Docker Hub ==="
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- echo "=== Construindo a imagem Docker ==="
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest
- echo "=== Enviando a imagem para o Docker Hub ==="
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- docker push $IMAGE_NAME:latest
- echo "=== Obtendo o digest da imagem ==="
# Extraindo o digest da imagem enviada para uso no deploy
- IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE_NAME:$CI_COMMIT_SHA)
- echo $IMAGE_DIGEST > image_digest.txt
artifacts:
paths:
- image_digest.txt # Salva o digest da imagem para o job de deploy
only:
- main
# Job para deploy na VPS
deploy:
stage: deploy
image: docker:latest
tags:
- chirpy-starter
before_script:
- echo "=== Logando no Docker Host ==="
- docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD"
script:
- |
IMAGE_DIGEST=$(cat image_digest.txt)
if [ -z "$IMAGE_DIGEST" ]; then
echo "Erro: IMAGE_DIGEST está vazio ou não definido."
exit 1
fi
echo "Imagem a ser usada: ${IMAGE_DIGEST}"
- echo "=== Removendo imagens locais antigas ==="
- docker rmi $IMAGE_NAME:latest || echo "Imagem local 'latest' não encontrada"
- docker rmi $IMAGE_NAME:$CI_COMMIT_SHA || echo "Imagem local específica não encontrada"
- echo "=== Baixando a imagem mais recente ==="
- docker pull $IMAGE_DIGEST
- echo "=== Parando e removendo contêiner antigo ==="
- docker stop chirpy-starter || echo "Nenhum contêiner em execução para parar"
- docker rm chirpy-starter || echo "Nenhum contêiner antigo para remover"
- echo "=== Iniciando novo contêiner ==="
- docker run -d --name chirpy-starter -p 8092:80 $IMAGE_DIGEST
- echo "=== Novo contêiner iniciado com sucesso ==="
dependencies:
- build
only:
- main
3.2 Explicação do Pipeline
- Stages:
- Build: Constrói a imagem Docker e a publica no Docker Hub.
- Test: Valida o site gerado, verificando links e integridade.
- Deploy: Faz deploy da imagem Docker em uma VPS.
- Jobs:
- Build: Usa
docker:dind
para criar e enviar imagens Docker. - Test Links: Verifica links quebrados usando
HTMLProofer
. - Deploy: Substitui o contêiner em execução na VPS pelo novo.
- Build: Usa
- Triggers:
- O pipeline é executado automaticamente em push para a branch
main
.
- O pipeline é executado automaticamente em push para a branch
3.3 Agendar Builds Automáticos
- Acesse CI/CD > Schedules no GitLab.
- Configure a execução automática da pipeline semanalmente ou em intervalos definidos.
- Escolha a branch (
main
) e salve o agendamento.
3.4 Testar o Pipeline
- Faça um commit para a branch
main
:1 2 3
git add .gitlab-ci.yml git commit -m "Adiciona pipeline CI/CD ao projeto" git push
- Verifique a execução do pipeline:
- Acesse CI/CD > Pipelines no repositório.
- Veja o progresso e logs de cada job.
4. Configurando o GitLab Runner na VPS
O GitLab Runner será configurado em uma VPS para executar o job de deploy. Essa configuração permite que o pipeline faça o deploy diretamente no ambiente de produção.
4.1 Preparar a VPS
- Instalar Docker na VPS:
- Faça login na VPS via SSH.
- Instale o Docker:
1 2
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
- Adicione seu usuário ao grupo Docker para evitar usar
sudo
em todos os comandos:1
sudo usermod -aG docker $USER
- Reinicie a sessão para aplicar as permissões:
1 2
exit ssh usuario@seu-ip
- Verifique a instalação do Docker:
1
docker --version
4.2 Configurar o GitLab Runner
- Executar o GitLab Runner como contêiner Docker:
- Baixe e inicie o GitLab Runner:
1 2 3 4 5
docker run -d --name gitlab-runner \ --restart always \ -v /srv/gitlab-runner/config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest
- Baixe e inicie o GitLab Runner:
- Verificar se o contêiner está rodando:
1
docker ps
Você verá uma saída com o contêiner
gitlab-runner
listado.
4.3 Registrar o GitLab Runner
- Obter o Token de Registro no GitLab:
- Acesse o repositório no GitLab.
- Navegue até Settings > CI/CD > Runners.
- Clique em Expand na seção Available Runners e copie o token de registro.
- Registrar o Runner:
- No terminal da VPS, execute:
1
docker exec -it gitlab-runner gitlab-runner register
- Siga as instruções interativas:
- URL do GitLab:
https://gitlab.com
- Token do Runner: Cole o token copiado.
- Descrição:
runner-jekyll
- Tags:
runner-jekyll
(use as mesmas tags no.gitlab-ci.yml
). - Executor: Escolha
docker
.
- URL do GitLab:
- No terminal da VPS, execute:
- Configurar o Executor Docker:
- Durante o registro, configure o executor para usar a imagem Docker padrão:
1 2
Please enter the Docker image (eg. ruby:2.6): [docker:latest]
- Durante o registro, configure o executor para usar a imagem Docker padrão:
4.4 Verificar a Configuração
- Após o registro, verifique o arquivo
config.toml
do GitLab Runner:1
sudo cat /srv/gitlab-runner/config/config.toml
- Certifique-se de que as tags, URL e executor estão configurados corretamente:
1 2 3 4 5 6 7 8 9
[[runners]] name = "runner-jekyll" url = "https://gitlab.com" token = "seu-token" executor = "docker" [runners.docker] image = "docker:latest" privileged = true volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
- Reinicie o Runner para aplicar as alterações:
1
docker restart gitlab-runner
4.5 Testar o GitLab Runner
- Faça um commit na branch
main
para disparar o pipeline:1 2
git commit --allow-empty -m "Testando o GitLab Runner" git push
- No GitLab, acesse CI/CD > Pipelines e verifique se o job de deploy é executado com o Runner configurado.
5. Configurando o Proxy Reverso com Nginx
Agora, vamos configurar o Nginx na VPS para servir o site gerado pelo contêiner do Jekyll. O Nginx atuará como proxy reverso, redirecionando as solicitações para o contêiner e fornecendo suporte a HTTPS usando o Certbot.
5.1 Instalar e Configurar o Nginx
- Instalar o Nginx:
- Conecte-se à VPS via SSH.
- Instale o Nginx:
1 2
sudo apt update sudo apt install nginx
- Verificar se o Nginx está ativo:
1
sudo systemctl status nginx
O status deve indicar active (running).
- Criar a Configuração do Site:
- Crie um arquivo de configuração para o proxy:
1
sudo vim /etc/nginx/sites-available/jekyll
- Adicione o seguinte conteúdo ao arquivo:
1 2 3 4 5 6 7 8 9 10 11
server { server_name geanmartins.com.br www.geanmartins.com.br; location / { proxy_pass http://localhost:8092; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
- Crie um arquivo de configuração para o proxy:
- Ativar o Site:
- Crie um link simbólico para habilitar a configuração:
1
sudo ln -s /etc/nginx/sites-available/jekyll /etc/nginx/sites-enabled/
- Teste a configuração do Nginx:
1
sudo nginx -t
- Reinicie o Nginx para aplicar as alterações:
1
sudo systemctl restart nginx
- Crie um link simbólico para habilitar a configuração:
5.2 Configurar HTTPS com Certbot
- Instalar o Certbot:
- Instale o Certbot e o plugin para Nginx:
1
sudo apt install certbot python3-certbot-nginx
- Instale o Certbot e o plugin para Nginx:
- Obter o Certificado SSL:
- Execute o Certbot para configurar o HTTPS:
1
sudo certbot --nginx -d geanmartins.com.br -d www.geanmartins.com.br
- Execute o Certbot para configurar o HTTPS:
- Verificar a Instalação do SSL:
- Certifique-se de que o Certbot atualizou o arquivo de configuração do Nginx.
- Acesse o site em https://geanmartins.com.br.
- Configurar Renovação Automática:
- Verifique a renovação automática:
1
sudo certbot renew --dry-run
- Adicione um cron job para executar a renovação regularmente:
1
crontab -e
Adicione a linha:
1
0 3 * * * certbot renew --quiet
- Verifique a renovação automática:
5.3 Testar a Configuração
- Verificar o Acesso ao Site:
- Acesse o site usando HTTP e HTTPS para confirmar que o redirecionamento está funcionando.
- Validar Logs do Nginx:
- Inspecione os logs para identificar possíveis problemas:
1
sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log
- Inspecione os logs para identificar possíveis problemas:
6. Resumo e Validação Final
Agora que o blog Jekyll foi configurado e publicado, vamos validar todo o fluxo para garantir que o sistema funcione conforme esperado.
6.1 Validação de Componentes
Pipeline CI/CD
- Objetivo: Automatizar build, teste e deploy.
- Verificação:
- Faça um commit na branch
main
. - No GitLab, acesse CI/CD > Pipelines e confirme que os jobs:
- Build: Constrói e publica a imagem Docker.
- Test: Valida links e o site gerado.
- Deploy: Substitui o contêiner na VPS.
- Todos os jobs devem ser marcados como Passed.
- Faça um commit na branch
Contêiner Docker
- Objetivo: Rodar o site gerado pelo Jekyll.
- Verificação:
- Acesse a VPS e liste os contêineres:
1
docker ps
- Verifique se o contêiner
jekyll-blog
está ativo e escutando na porta8092
.
- Acesse a VPS e liste os contêineres:
Nginx e Proxy Reverso
- Objetivo: Redirecionar o tráfego para o contêiner.
- Verificação:
- Abra o navegador e acesse:
- Confirme que o HTTPS está funcionando.
Certificado SSL
- Objetivo: Garantir a segurança do tráfego.
- Verificação:
- Use uma ferramenta online como SSL Labs para verificar o certificado.
- Certifique-se de que o Certbot está configurado para renovação automática.
6.2 Dicas de Manutenção
- Atualizações do Pipeline:
- Monitore a integridade das imagens Docker e dependências.
- Use
Trivy
ouSnyk
para verificar vulnerabilidades periodicamente.
- Logs e Monitoramento:
- Inspecione os logs regularmente:
1 2
sudo tail -f /var/log/nginx/access.log docker logs jekyll-blog
- Inspecione os logs regularmente:
- Renovação de Certificados:
- Garanta que o cron job do Certbot está ativo e funcionando.