7 antipadrões do Docker que você precisa evitar

O Docker transformou o desenvolvimento de software com seu modelo simples de conteinerização que permite empacotar cargas de trabalho rapidamente em unidades reproduzíveis. Embora o Docker seja fácil de usar, há mais nuances em seu uso do que sempre parece. Isso é especialmente verdadeiro quando você está procurando otimizar o uso do Docker para aumentar a eficiência e o desempenho.
Aqui estão sete dos antipadrões do Docker mais comuns que você deve procurar e evitar. Embora seus contêineres e imagens possam atender às suas necessidades imediatas, a presença de qualquer uma dessas práticas sugere que você está se desviando dos princípios de conteinerização de uma forma que pode ser prejudicial no futuro.
1. Aplicação de atualizações dentro de contêineres
Provavelmente, o antipadrão Docker mais comum é tentar atualizar contêineres usando técnicas herdadas de máquinas virtuais tradicionais. Os sistemas de arquivos do contêiner são efêmeros, portanto, todas as alterações são perdidas quando o contêiner para. Seu estado deve ser reproduzível a partir do Dockerfile usado para construir a imagem.
Isso significa que você não deve executar uma atualização do apt dentro de seus contêineres. Eles seriam diferentes da imagem a partir da qual foram criados. Os recipientes devem ser livremente intercambiáveis; separar seus dados de seu código e dependências permite substituir instâncias de contêiner a qualquer momento.
Os patches devem ser aplicados reconstruindo periodicamente a sua imagem, parando os contêineres existentes e iniciando novos com base na imagem revisada. Os projetos do conjunto de ferramentas da comunidade estão disponíveis para simplificar esse processo e informá-lo sobre as atualizações upstream disponíveis.
2. Execução de vários serviços dentro de um contêiner
Os contêineres devem ser independentes e focados em uma função particular. Embora você possa ter executado seus servidores da Web e de banco de dados anteriormente em uma única máquina física, uma abordagem totalmente desacoplada veria os dois componentes separados em contêineres individuais.
Publicidade
Esta metodologia evita que imagens de contêineres individuais se tornem muito grandes. Você pode inspecionar os registros de cada serviço usando comandos integrados do Docker e atualizá-los independentemente um do outro.
Vários contêineres fornecem escalabilidade aprimorada, pois você pode aumentar prontamente a contagem de réplicas de partes individuais de sua pilha. O banco de dados está lento? Use seu orquestrador de contêiner para adicionar mais algumas instâncias de contêiner MySQL, sem alocar nenhum recurso extra para os componentes que já estão funcionando bem.
3. Imagens construídas com efeitos colaterais
Construções de imagens do Docker devem ser operações idempotentes que sempre produzem o mesmo resultado. Executar o docker build não deve causar nenhum impacto em seu ambiente mais amplo, pois seu único objetivo é produzir uma imagem de contêiner.
No entanto, muitas equipes criam Dockerfiles que manipulam recursos externos. Um Dockerfile pode se transformar em uma forma de script de CI abrangente que publica versões, cria confirmações Git e grava em APIs ou bancos de dados externos.
Essas ações não pertencem a um Dockerfile. A criação de uma imagem Docker é uma operação independente que deve ser seu próprio estágio de pipeline de CI. A preparação da liberação ocorre então como um estágio separado para que você sempre possa encaixar a compilação sem publicar inesperadamente uma nova tag.
4. Complicando demais seu Dockerfile
De maneira semelhante, é possível que os Dockerfiles façam muito. Limitar o Dockerfile ao conjunto mínimo de instruções de que você precisa minimiza o tamanho da imagem e melhora a legibilidade e a manutenção.
Publicidade
Freqüentemente, podem ocorrer problemas ao usar compilações do Docker de vários estágios. Esse recurso facilita o desenvolvimento de sequências de construção complexas que fazem referência a várias imagens de base. Muitos estágios independentes podem ser um indicador de que você está misturando interesses e processos de acoplamento muito estreitos.
Procure por seções lógicas em seu Dockerfile que atendam a propósitos específicos. Tente dividi-los em Dockerfiles individuais, criando imagens de utilitário autocontidas que podem ser executadas independentemente para preencher partes de seu pipeline mais amplo.
Você pode criar um “ construtor ” imagem com as dependências necessárias para compilar seu código-fonte. Use essa imagem como um estágio em seu pipeline de CI e, em seguida, alimente sua saída como artefatos no próximo estágio. Agora você pode copiar os binários compilados em uma imagem final do Docker que você usa na produção.
5. Configuração codificada
Imagens de contêiner que incluem credenciais, segredos ou chaves de configuração codificadas podem causar sérias dores de cabeça, bem como riscos de segurança. Associar as configurações à sua imagem compromete a atração fundamental do Docker, a capacidade de implantar a mesma coisa em vários ambientes.
Use variáveis de ambiente e segredos declarados do Docker para injetar configuração no ponto em que você inicia um contêiner. Isso mantém as imagens como ativos reutilizáveis e limita o acesso a dados confidenciais apenas para o tempo de execução.
Publicidade
Esta regra ainda se aplica a imagens destinadas apenas para uso interno. Codificar segredos implica que eles também estão comprometidos com seu software de controle de versão, potencialmente tornando-os vulneráveis a roubo no caso de uma violação do servidor.
6. Imagens separadas de desenvolvimento e implantação
Você deve construir apenas uma imagem de contêiner para cada alteração em seu aplicativo. Manter várias imagens semelhantes para ambientes individuais sugere que você &’ não está se beneficiando com o Docker &’ s “ executado em qualquer lugar ” mentalidade.
É melhor promover uma única imagem em seus ambientes, desde o teste até a produção. Isso dá a você a confiança de que está executando exatamente o mesmo ambiente lógico em cada uma de suas implantações, de modo que o que funcionou na preparação ainda será executado na produção.
Ter uma “ produção ” a imagem sugere que você pode estar sofrendo de alguns dos outros anti-padrões indicados acima. Você provavelmente tem uma sequência de construção complexa que pode ser dividida ou credenciais específicas de produção codificadas em sua imagem. As imagens devem ser separadas por estágio de ciclo de vida de desenvolvimento, não por ambiente de implementação. Lide com diferenças entre ambientes injetando configuração usando variáveis.
7. Armazenamento de dados dentro de contêineres
A natureza efêmera dos sistemas de arquivos contêiner significa que você não deve gravar dados neles. Os dados persistentes criados pelos usuários do seu aplicativo, como uploads e bancos de dados, devem ser armazenados em volumes do Docker ou serão perdidos quando seus contêineres forem reiniciados.
Outros tipos de dados úteis devem evitar a gravação no sistema de arquivos sempre que possível. Transmita registros para o fluxo de saída do seu contêiner, onde podem ser consumidos por meio do comando docker logs, em vez de despejá-los em um diretório que seria perdido após uma falha do contêiner.
Publicidade
As gravações do sistema de arquivos do contêiner também podem incorrer em uma penalidade de desempenho significativa ao modificar os arquivos existentes. O uso do Docker da “ cópia na gravação ” estratégia de camadas significa que os arquivos que existem nas camadas inferiores do sistema de arquivos são lidos dessa camada, em vez da camada final da imagem. Se uma alteração for feita no arquivo, o Docker deve primeiro copiá-lo para a camada superior e, em seguida, aplicar a alteração. Esse processo pode levar vários segundos para arquivos maiores.
Conclusão
Observar esses antipadrões tornará suas imagens do Docker mais reutilizáveis e fáceis de manter. Eles são a diferença entre apenas usar contêineres do Docker e adotar um fluxo de trabalho em contêiner. Você pode escrever facilmente um Dockerfile funcional, mas um mal planejado restringirá sua capacidade de capitalizar todos os benefícios potenciais.
Os contêineres devem ser unidades efêmeras e autônomas de funcionalidade criadas a partir de um processo de construção reproduzível. Eles mapeiam para estágios em seu processo de desenvolvimento, não ambientes de implantação, mas não facilitam diretamente esse processo eles próprios. As imagens devem ser os artefatos produzidos por um pipeline de CI, não o mecanismo que define esse pipeline.
A adoção de contêineres requer uma mudança de mentalidade. É melhor começar pelos fundamentos, estar ciente dos objetivos gerais e, em seguida, ver como você pode incorporá-los ao seu processo. Usar contêineres sem a devida consideração desses aspectos pode acabar criando uma dor de cabeça a longo prazo, longe da maior flexibilidade e confiabilidade apregoada pelos proponentes da abordagem.
Nenhum comentário