Agora é possível construir imagens Docker no werf também usando um Dockerfile comum

Antes tarde do que nunca. Ou como quase cometemos um grande erro por não termos suporte a Dockerfiles padrão para construir imagens de aplicativo.

Agora é possível construir imagens Docker no werf também usando um Dockerfile comum

Vamos falar sobre werf — uma ferramenta GitOps que se integra a qualquer sistema de CI/CD e garante o gerenciamento de todo o ciclo de vida do aplicativo, permitindo que:

  • criem e publiquem imagens,
  • implantem aplicativos no Kubernetes,
  • e removam imagens não utilizadas por meio de políticas específicas.


A filosofia do projeto é reunir ferramentas de baixo nível em um único sistema unificado, dando aos engenheiros DevOps controle sobre os aplicativos. Sempre que possível, as ferramentas existentes (como Helm e Docker) devem ser utilizadas. Se uma solução para um problema específico não existir, podemos criar e manter tudo o que for necessário.

Histórico: nosso construtor de imagens

Foi assim que surgiu o construtor de imagens no werf: não tínhamos o Dockerfile usual. Ao olhar brevemente para a história do projeto, esse problema já se manifestou nas primeiras versões do werf (então ainda conhecido como dapp).

). Ao criar uma ferramenta para empacotar aplicativos em imagens Docker, percebemos rapidamente que o Dockerfile não era adequado para algumas tarefas bastante específicas:

  1. A necessidade de compilar tipos típicos de aplicativos web pequenos de acordo com o seguinte esquema padrão:
    • instalar as dependências do sistema do aplicativo,
    • instalar o bundle de bibliotecas das dependências do aplicativo,
    • compilar os assets,
    • e o mais importante — atualizar o código na imagem de forma rápida e eficiente.
  2. Ao fazer alterações nos arquivos do projeto, o construtor deve criar rapidamente uma nova camada aplicando um patch nos arquivos alterados.
  3. Se certos arquivos forem modificados, a fase correspondente dependente deve ser recompilada.

Hoje em dia, nosso construtor tem muitas outras funcionalidades, mas os desejos e anseios iniciais eram esses.

No geral, sem pensar muito, escolhemos a linguagem de programação utilizada (veja abaixo) e partimos para implementar nossa própria DSL! Atingindo os objetivos estabelecidos, ela foi projetada para descrever o processo de construção em fases e determinar as dependências dessas fases em relação aos arquivos. E complementava isso com nosso próprio construtor, que transformava a DSL no objetivo final — a imagem construída. Inicialmente, a DSL era em Ruby, mas à medida que fazemos a transição para o Golang , a configuração do nosso construtor começou a ser descrita em um arquivo YAML.

Agora é possível construir imagens Docker no werf também usando um Dockerfile comum
Configuração antiga para dapp em Ruby

Agora é possível construir imagens Docker no werf também usando um Dockerfile comum
Configuração atual para werf em YAML

O mecanismo de trabalho do construtor também mudou ao longo do tempo. No início, nós apenas gerávamos um Dockerfile temporário a partir da nossa configuração, e depois começamos a executar instruções de construção em contêineres temporários e fazer commit.

NB: Atualmente, nosso construtor, que trabalha com sua própria configuração (em YAML) e é chamado de construtor Stapel, já se desenvolveu em uma ferramenta bastante poderosa. Sua descrição detalhada merece artigos separados, e os principais detalhes podem ser encontrados em documentação.

Compreensão do problema

Mas percebemos, embora não imediatamente, que cometemos um erro: não adicionamos a possibilidade de construir imagens através de um Dockerfile padrão e integrá-las na mesma infraestrutura de gerenciamento complexo de aplicativo (ou seja, construir imagens, implantar e limpar). Como poderíamos ter feito uma ferramenta para implantação no Kubernetes e não implementar suporte ao Dockerfile, ou seja, o método padrão para descrever imagens para a maioria dos projetos?..

Em vez de responder a tal pergunta, oferecemos sua solução. O que fazer se você já tiver um Dockerfile (ou um conjunto de Dockerfiles) e quiser usar o werf?

NB: A propósito, por que você gostaria de usar o werf? Os principais recursos são:

  • ciclo completo de gerenciamento de aplicativo, incluindo limpeza de imagens;
  • capacidade de gerenciar a construção de várias imagens a partir de uma única configuração;
  • processo de implantação aprimorado de charts compatíveis com Helm.

Para uma lista mais completa, você pode consultar página do projeto.

Então, se antes teríamos sugerido reescrever o Dockerfile na nossa configuração, agora diremos com prazer: “Deixe o werf construir seus Dockerfiles!”

Como usar?

A implementação completa dessa funcionalidade surgiu na versão werf v1.0.3-beta.1. O princípio geral é simples: o usuário especifica o caminho para o Dockerfile existente na configuração do werf, após o que Executa o comando werf build… e pronto — o werf construirá a imagem. Vamos considerar um exemplo abstrato.

Declararemos o seguinte Dockerfile na raiz do projeto:

FROM ubuntu:18.04
RUN echo Construindo ...

E declararemos werf.yaml, que usa este Dockerfile:

configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: .\/Dockerfile

Isso é tudo! Agora só falta executar werf build:

Agora é possível construir imagens Docker no werf também usando um Dockerfile comum

Além disso, você pode declarar o seguinte werf.yaml para construir várias imagens a partir de diferentes Dockerfiles:

configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: .\/dockerfiles\/Dockerfile-backend
---
image: frontend
dockerfile: .\/dockerfiles\/Dockerfile-frontend

Finalmente, o suporte à transmissão de parâmetros adicionais de construção foi adicionado — como --build-arg e --add-host — através da configuração do werf. Uma descrição completa da configuração da imagem Dockerfile está disponível na página da documentação.

Como funciona?

Durante o processo de construção, o cache padrão dos camadas locais do Docker é utilizado. No entanto, o que é importante, o werf também integra a configuração do Dockerfile em sua infraestrutura. O que isso significa?

  1. Cada imagem criada a partir do Dockerfile consiste em um único estágio chamado dockerfile (mais informações sobre o que são estágios no werf podem ser lidas aqui).
  2. Para o estágio dockerfile o werf calcula uma assinatura que depende do conteúdo da configuração do Dockerfile. Quando a configuração do Dockerfile é alterada, a assinatura do estágio é mudada dockerfile e o werf inicia a reconstrução desse estágio com a nova configuração do Dockerfile. Se a assinatura não mudar, o werf pega a imagem do cache (informações sobre o uso de assinaturas no werf foram apresentadas na nesta apresentação).
  3. Os comentários construídos podem ser publicados com o comando werf publish (ou werf build-and-publish) e utilizados para implantação no Kubernetes. As imagens publicadas no Docker Registry serão limpas utilizando os meios padrão de limpeza do werf, ou seja, ocorrerá a limpeza automática de imagens antigas (mais de N dias), imagens associadas a ramificações do Git inexistentes e de acordo com outras políticas.

Mais informações sobre os aspectos mencionados aqui podem ser encontradas na documentação:

Notas e precauções

1. URL externo no ADD não é suportado

No momento, o uso de URL externo na diretiva ADD. O werf não iniciará a reconstrução ao mudar o recurso pelo URL especificado. Em breve, está previsto que essa funcionalidade será adicionada.

2. Não é permitido adicionar .git na imagem

De modo geral, adicionar o diretório .git na imagem é uma prática ruim e aqui está o porquê:

  1. Se .git permanece na imagem final, isso viola os princípios 12 factor app: como a imagem final deve estar vinculada a um único commit, não deve haver possibilidade de fazer git checkout um commit arbitrário.
  2. .git aumenta o tamanho da imagem (o repositório pode ser grande devido a arquivos grandes que foram adicionados e depois removidos). O tamanho da árvore de trabalho, vinculado apenas a um commit específico, não dependerá do histórico de operações no Git. Além disso, adicionar e posteriormente remover .git da imagem final não funcionará: a imagem ainda adquirirá uma camada extra — assim funciona o Docker.
  3. O Docker pode iniciar uma recompilação desnecessária, mesmo que esteja construindo o mesmo commit, mas de diferentes work-trees. Por exemplo, o GitLab cria diretórios clonados separados em /home/gitlab-runner/builds/HASH/[0-N]/yourproject com a compilação paralela ativada. A recompilação desnecessária estará relacionada ao fato de que o diretório .git é diferente nas várias versões clonadas do mesmo repositório, mesmo que esteja sendo compilado o mesmo commit.

O último ponto tem uma consequência ao usar o werf. O werf requer que o cache compilado esteja presente ao executar alguns comandos (por exemplo, werf deploy). Durante a execução de tais comandos, o werf calcula as assinaturas das fases para as imagens especificadas em werf.yaml, e elas devem estar no cache de compilação — caso contrário, o comando não conseguirá continuar a execução. Se a assinatura das fases depender do conteúdo .git, obtemos um cache instável a mudanças em arquivos irrelevantes, e o werf não poderá perdoar tal descuido (veja mais em documentação).

No geral adicionar apenas os arquivos necessários por meio da instrução ADD de qualquer forma aumenta a eficiência e a confiabilidade do que foi escrito Dockerfile, além de melhorar a resistência do cache gerado por este Dockerfile, a mudanças irrelevantes no Git.

Resultado

O nosso caminho inicial de escrever nosso próprio construtor para necessidades específicas foi pesado, honesto e direto: em vez de usar gambiarras em cima do Dockerfile padrão, nós escrevemos nossa própria solução com uma sintaxe personalizada. E isso trouxe suas vantagens: o construtor Stapel lida muito bem com sua tarefa.

No entanto, durante o processo de escrever nosso próprio construtor, deixamos de lado o suporte aos Dockerfiles já existentes. Agora, essa deficiência foi corrigida, e no futuro planejamos desenvolver o suporte ao Dockerfile junto com nosso construtor personalizado Stapel para compilação distribuída e para compilação usando Kubernetes (ou seja, compilações em runners dentro do Kubernetes, como feito no kaniko).

Portanto, se você tiver alguns Dockerfiles de sobra... tente werf!

P.S. Lista de documentação sobre o assunto

Leia também em nosso blog: "werf — nossa ferramenta para CI/CD no Kubernetes (visão geral e vídeo da apresentação)».

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster