Ultimamente, tenho recebido muitas perguntas sobre a contêinerização de ambientes para testes automatizados ao usar sistemas de Integração Contínua. Se você não entendeu a maioria dessa frase, não se preocupe porque vamos mergulhar fundo em contêineres, Docker e como aproveitá-los no seu ambiente embarcado e nos testes de hardware in the loop.
Existem muitos textos excelentes sobre contêineres, incluindo este da Docker (um dos motores de execução de contêineres mais populares que existem). Contêineres em ambientes de construção (ou seja, sistemas embarcados) e ambientes de teste (ou seja, testes de hardware in the loop) nos dão a capacidade de abstrair toda a configuração complicada toda vez que queremos iniciar uma nova máquina. Isso não está relacionado apenas a novas máquinas de teste, mas também a escalar nossa operação na nuvem também para a construção de firmware embarcado.
Não importa o tamanho da operação que você está executando atualmente, muitas empresas aproveitam a nuvem para evitar manter servidores físicos. Nos princípios de DevOps, sempre queremos garantir que qualquer software que escrevemos possa ser construído e executado em qualquer lugar, a qualquer hora, em qualquer lugar. Iniciar constantemente novas máquinas na nuvem e instalar software de compilação, bibliotecas e outros pacotes de software não escala bem. É precisamente por isso que a contêinerização se tornou tão popular. Podemos pegar nosso ambiente de construção (ou de execução), empacotá-lo em uma máquina virtual muito leve e entregá-lo a qualquer máquina para executar, seja na nuvem ou em nosso próprio computador pessoal.
Vamos explorar como realmente criar e usar esses contêineres em seus projetos. Quando começamos a criar uma imagem de contêiner, temos que começar com uma “imagem base” existente. Na maioria dos casos, alguma variante de um sistema operacional Linux, como Debian, Ubuntu ou Alpine, será suficiente. Uma vez que você cria seu Dockerfile, você se refere à imagem assim:
FROM ubuntu:latest
Isso indica que o sistema operacional base estará executando a imagem Docker Ubuntu mais recente. Depois disso, precisaremos instalar quaisquer bibliotecas necessárias para nosso ambiente de construção ou teste. Em um repositório de exemplo, instalei a IDE do Arduino usando o gerenciador de pacotes Debian (Apt) e depois adicionei mais camadas instalando os drivers da placa Arduino Sam também. Executando este contêiner em modo privilegiado (ou passando o ponto de montagem do volume para o dispositivo), posso compilar e fazer upload de um esboço do Arduino via linha de comando em uma máquina novinha em folha que contém apenas o Docker (ou seja, sem IDE ou drivers).
Podemos fazer o mesmo com máquinas que estão conectadas aos nossos dispositivos em teste. Neste container Docker que montei, instalo todas as dependências e softwares necessários para rodar um dispositivo Analog Discovery 2. Em teoria, posso iniciar o container Docker em uma máquina completamente nova (que contém apenas o Docker) e começar a comunicar com o Analog Discovery 2 sem complicações. Com o Analog Discovery 2, posso escrever testes para validar meus ADCs, DACs, ou enviar comandos I2C/SPI para diferentes chips na minha placa (junto com uma miríade de outras capacidades).
Agora, vamos discutir como os containers podem aprimorar sistemas de Integração Contínua para aumentar a eficiência e escalabilidade. A verdadeira mágica acontece quando começamos a usar containers em conjunto com sistemas de Integração Contínua (CI). Podemos ter dezenas, se não centenas de máquinas de teste físicas ou acesso a milhares de máquinas na nuvem para nossos servidores de teste e construção. Para escalar de forma prática, como mencionado acima, não podemos configurar cada máquina individualmente à medida que elas são disponibilizadas. Entregar um container a cada execução de CI nos dá não apenas uma maneira sistemática e repetível de realizar builds e testes, mas também nos liberta de ter que reconfigurar uma máquina toda vez que a iniciamos (o que, na nuvem, acontece em quase todas as execuções de CI). Ao aproveitar os containers para builds embutidos e testes de hardware físico, proporcionamos a nós mesmos e às nossas empresas um certo nível de escala que as gerações anteriores só poderiam sonhar.
Neste artigo, destacamos o papel crucial dos containers no desenvolvimento de sistemas embutidos, especialmente para ambientes de build e teste consistentes em diferentes tipos de infraestrutura. Sua integração com sistemas de integração contínua não apenas agiliza o desenvolvimento, mas também aumenta a escalabilidade e a confiabilidade do produto. À medida que a tecnologia de containers avança, sua adoção se tornará cada vez mais importante para os desenvolvedores. Aprofunde-se e experimente diferentes configurações visitando alguns repositórios de exemplo em https://gitlab.com/docker-embedded.