Tentando configurar um serviço utilizando Docker em um Raspberry Pi, deparei-me com tempos de build astronómicos (parei de contar após 20 minutos), muitas vezes resultando em erros por incompatibilidade ou indisponibilidade de rede.
Este post apresenta uma solução completa e automatizada para este problema, utilizando o GitHub Actions para automatizar o build das imagens em multiplas plataformas e disponibilizando elas no Docker Hub.
Docker no Raspberry Pi
O Docker é uma excelente ferramenta para criação e gerenciamento de containers, simplificando muito o processo de setup de uma topologia de um projeto e todas suas dependencias (DB, cache, server de arquivos estáticos, etc…).
Em 2016, foi anunciado no Blog do Raspberry Pi de que a nova
versão do raspbian/jessie
contaria com suporte oficial ao Docker, permitindo
então que este fosse instalado com relativa facilidade:
No entanto, devido à capacidade de processamento do Raspberry Pi, especialmente nas versões de hardware mais antigas, o processo de construir as imagens dos containers é extremamente demorado.
Em um dos casos, passei mais de 20 minutos esperando o comando concluir, apenas para ver ele sendo cancelado devido a um problema temporário de conexão com os repositórios do NPM.
Builds Multi Plataforma
A solução que encontrei para este problema foi atravéz do comando
buildx
, que já vem disponível na CLI a partir da versão
19.03
do Docker.
Este commando permite a criação de builders, capazes de construirem imagens
a partir de um Dockerfile
. Este commando, aliado ao QEMU, é capaz de
gerar imagens em multiplas plataformas, incluindo arm/v6
e arm/v7
, que são as arquiteturas suportadas pelo Raspberry Pi.
Testei este método gerando uma imagem e armazenando ela num arquivo .tar
:
Depois de pronta, a imagem pode ser copiada para o Raspberry Pi e carregada através dos comandos:
Build automático através do GitHub Actions
O procedimento apresentado até então já é suficiente para cobrir a utilização básica, no entanto, como ele é manual, fica um pouco chato para um desenvolvimento contínuo de um projeto.
Uma maneira de resolver isto é automatizar e incluir este procedimento nas rotinas de Integração Contínua (CI). O GitHub Actions é perfeito para isto, sendo extremamente fácil de configurar e proporcionando uma excelente integração com o repositório do projeto.
O GitHub Actions nos permite configurar Workflows. Estes representam uma
lista de ações que serão executadas em sequência. Estes são definidos através
de arquivos .yml
, definidos no diretório .github
, na raíz do repositório:
Conteúdo do arquivo:
-
A primeira diretiva
name
atribui um nome ao Workflow. - A diretiva
on
define as condições nas quais o workflow será executado:push
- Define que o workflow será executado toda vez que houver push no branchmain
(Se o repositório for mais antigo, é bem provável que este seja omaster
).workflow_dispatch
- Permite executar o workflow manualmente, através da abaActions
na página principal do projeto.
- Diretiva
jobs
define as tarefas a serem executadas e os seus parâmetros:build
- o nome do job a ser definido.runs-on
- permite escolher qual distribuição será utilizada na máquina virtual (provisionada automaticamente) que executará as ações.- Optei pelo
ubuntu-18.04
pois é uma versão bem madura e estável.
- Optei pelo
steps
- passos a serem executados.name
- Nome do passo.id
- ID do passo. Permite ser referenciado no restante do arquivo de configuração.uses
- Repositório da ação a ser executada.with
- Parâmetros a serem passados à ação.
Descrição das ações:
-
action/checkout
- Faz um checkout do repositório na VM. docker/setup-qemu-action
- Faz o setup do QEMU:platforms
define as plataformas a serem configuradas no QEMU.- No meu caso, optei por
linux/amd64
elinux/arm/v6
. - Para uma lista completa de plataformas suportadas, consulte o repositório da ação no GitHub.
- No meu caso, optei por
-
docker/setup-buildx-action
- Faz o setup dobuildx
. docker/login-action
- Fazer o login no Docker Hub:- Permitirá fazer um push da imagem gerada para o repositório da Docker, definido no próximo passo.
- Como este arquivo estará commitado no nosso repositório, não é uma boa ideia simplesmente colocar credenciais em plain text, mesmo que o repositório seja privado!
- Para fazer isto de maneira segura, é possível adicionar as credenciais
como Segredos (Secrets) no GitHub e referenciá-las
através de variáveis prefixadas em
secrets.
.
build-push-action
- Gera a imagem:- Mais uma vez, as plataformas são específicadas em
platforms
. tags
especifica uma tag a ser aplicada às imagens geradas:- Utilizo apenas a tag
:latest
, que será sempre sobrescrita (Ainda não explorei muito, mas imagino que seja possível utilizar variáveis para aplicar a mesma tag definida no repositório Git).
- Utilizo apenas a tag
- Mais uma vez, as plataformas são específicadas em
- A diretriz
run
serve para executar um comando diretamente no shell da VM. Neste caso, oecho
serve para imprimir o hash da imagem gerada no passo anterior. Serve como exemplo de como se referir a uma etapa anterior (steps.<id_do_passo>
).
Para descobrir outras ações disponíveis, é possível consultar o GitHub Marketplace.