[Prova de conceito] CI com um script Python, Github Actions e Docker HUB

Este script Python é um exemplo de um script que poderia ser utilizado em um processo de CI. Nosso objetivo é explorar como escrever um software e automatizar uma solução pra um processo de CI otimizando a esteira de desenvolvimento e implantação.

Nosso objetivo é ter um único ponto de fácil acesso via Docker HUB pra implantar em diversos ambientes com uma fácil configuração e atualização/obtenção do mesmo.

Sumário

Links úteis

Pré-requisitos

Configurações

Primeiro, além dos acessos ao github actions nós precisamos criar arquivos e configurações para nosso processo. Nosso objetivo é simples: automatizar o processo de buildar e mandar nossa imagem docker ao Docker HUB (o que inclui o overview lá no Docker HUB) e manter este sempre atualizado a cada push que dermos a nossa branch main.

Docker Hub

Você irá precisar de uma conta no Docker Hub, e dito isso, crie um repositório nele. Inclusive, já deixe o nome dele anotado, iremos logo menos.

Crie seu token de acesso, e com ele e seu username vamos a parte mais interessante!

Git hub Actions

Pra isso, precisaremos de um arquivo .yml criado dentro da pasta .github/workflows que vamos chamar de ci.yml.

name: ci-python-script

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Docker Hub Description
        uses: peter-evans/dockerhub-description@v4
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          repository: ${{ secrets.IMAGE_NAME }}
          short-description: A Python script example for Docker Hub with github actions
          readme-filepath: ./OVERVIEW_DOCKER_HUB.md

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push Docker image
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          push: true
          tags: ${{ secrets.IMAGE_NAME }}:latest

Vamos destacar algumas coisas desse processo:

  • lá no "on" colocamos quando esse processo deve ser acionado, e evidentemente, as configurações seguintes como "push" e "branches" especificam nosso objetivo para sempre ser acionado ao dar push na main
  • já adicionar "workflow_dispatch" permite que caso desejarmos acionemos nosso processo manualmente link da documentação
  • o próprio github disponibiliza n's actions dentro de seu marketplace pra diversos fins, aqui vamos usar os principais pra docker presentes nesse cara: Build and Push Docker Images
  • E por fim um cara muito especial neste repositório que proporciona automatizar a overview que irá pro Docker Hub por meio de uma action! Note que inclusive fizemos um arquivo somente pra overview(OVERVIEW_DOCKER_HUB.md) diferente do readme.

Dado isso, vamos configurar nossas variáveis no Github, onde no seu repositório basta ir em Settings > Security > Secrets and variables > Actions e configure as variáveis

  • DOCKERHUB_TOKEN
  • DOCKERHUB_USERNAME
  • IMAGE_NAME

Imagem das variáveis de ambiente para Github actions

Com isso, no nosso processo push na branch main nossa action deve conseguir buildar e adicionar nossa imagem ao repositório no docker hub.

O que fizemos até aqui

Após todo nosso processo até então visto, devemos ter algo semelhante a isso lá no nosso repositório informado na variável IMAGE_NAME:

Imagem do docker hub pós publicação da imagem

E dado isso, poderíamos usar nossa imagem da seguinte forma:

docker run --rm --name ci_python_example_2 --env-file=.env mugarate12/ci_python_script:latest

Onde eu uso "run" pra rodar nossa image, "--rm" pra excluir o container depois do finalizar o processo realizado, "--name" adicionando um nome ao container gerado, "--env-file" pra indicar o .env que irei usar(você também pode passar as variáveis de ambiente com -e [NOME DA VARIÁVEL]:[CONTEÚDO DA VARIÁVEL]), e por fim o repositório do docker hub (que é o mesmo que informamos no IMAGE_NAME lá nas actions). Você deverá ter um resultado como esse:

Exemplo de execução da imagem via docker hub

O que com isso abstrai toda a configuração de ambiente e utilitários para o funcionamento da solução.

Conclusão

O que vimos aqui tende a ser um facilitador para implantações de soluções pequenas ou mesmo grandes, onde conseguimos usar as automações das actions do Github e o Docker + Docker Hub pra fazer um processo contínuo de integração sem a necessidade de ocupar tempo das equipes em verificar e atualizar as versões. Claro, com um bom processo de CD (Continuous Delivery) poderíamos ainda disponibilizar essa nova versão ao cliente de forma mais rápida e automatizada.

Ainda há várias incrementos que poderíamos fazer, como fazer testes automatizados via actions e somente permitir um commit ou um merge/pull request na main (pensando que estaríamos usando gitflow) caso os testes passem.

As possibilidades são muitas e tudo isso só gera mais valor e segurança pro produto que estivermos atuando.

Ótimo post Matheus, como posso executar testes antes de subir a aplicação?

Claro que pode, não nesta proposta, todavia é possível. Inclusive, é possível somente aprovar um pull request pra branch main (ou seja, produção) se os testes passarem em casos mais arrojados.
Sim, vi sobre pode configurar uma dependência no docker compose. Executar estes testes usando docker compose é comum, ou tem alguma outra maneira melhor? Até implementei isso no meu sistema ao fazer um pull, mas os testes são executados sobre a imagem anterior ocasionando um erro em testes de novas features. Acredito que não configurei corretamente. Tem algum material de referência para mim? artigo/video/etc