Práticas recomendadas para criar contêineres

Neste artigo, descrevemos um conjunto de práticas recomendadas para criar contêineres. Elas abrangem uma ampla variedade de metas, incluindo o encurtamento do tempo de criação e a elaboração de imagens menores e mais resilientes. O objetivo é facilitar a criação de contêineres (por exemplo, com o Cloud Build) e a execução deles no Google Kubernetes Engine (GKE).

Essas práticas têm importâncias diferentes. Por exemplo, execute com sucesso uma carga de trabalho de produção sem algumas delas, mas outras são fundamentais. Em especial, a importância das práticas recomendadas em relação à segurança é subjetiva. A implementação delas depende do ambiente e das restrições.

Para aproveitar ao máximo este artigo, você precisa ter conhecimento sobre o Docker e o Kubernetes. Algumas práticas recomendadas discutidas aqui também se aplicam a contêineres do Windows. Porém, na maioria presume-se que você esteja trabalhando com contêineres do Linux. Você encontra dicas sobre como executar e operar contêineres em Práticas recomendadas para a operação de contêineres.

Empacotar um único aplicativo por contêiner

Importância: ALTA

No início, é um erro comum tratar contêineres como máquinas virtuais que podem executar muitos elementos diferentes ao mesmo tempo. Um contêiner pode funcionar dessa maneira, mas isso reduz a maioria das vantagens do modelo de contêiner. Por exemplo, pegue uma pilha clássica do Apache/MySQL/PHP: talvez você fique tentado a executar todos os componentes em um único contêiner. No entanto, a prática recomendada é usar dois ou três contêineres diferentes: um para o Apache, um para o MySQL e, possivelmente, um para o PHP se você estiver executando o PHP-FPM.

Como o contêiner é projetado para ter o mesmo ciclo de vida do aplicativo que ele hospeda, cada um dos contêineres precisa incluir apenas um aplicativo. Quando um contêiner for iniciado, o mesmo ocorrerá no aplicativo, e quando o aplicativo parar, o mesmo acontecerá com o contêiner. O diagrama a seguir mostra essa prática recomendada.

Um diagrama do processo de inicialização sem uma imagem personalizada.

Figura 1. O contêiner à esquerda segue a prática recomendada. O contêiner à direita não.

Se você tiver diversos aplicativos em um contêiner, eles poderão ter ciclos de vida diferentes ou estar em estados distintos. Por exemplo, você pode acabar com um contêiner em execução, mas com um dos principais componentes dele com falha ou sem resposta. Sem uma verificação de integridade adicional, o sistema geral de gerenciamento de contêiner (Docker ou Kubernetes) não pode informar se o contêiner está íntegro. No caso do Kubernetes, significa que o contêiner não será reiniciado por padrão, se necessário.

Você verá as ações a seguir em imagens públicas, mas não siga o exemplo delas:

Lidar adequadamente com PID 1, manipulação de sinal e processos zumbi

Importância: ALTA

Os sinais do Linux são a principal maneira de controlar o ciclo de vida dos processos dentro de um contêiner. De acordo com a prática recomendada anterior, para vincular o ciclo de vida do aplicativo ao contêiner em que ele está, certifique-se de que ele processe corretamente os sinais do Linux. O sinal mais importante é o SIGTERM, porque encerra um processo. O aplicativo também pode receber um sinal SIGKILL, que é usado para encerrar o processo de modo não otimizado, ou um sinal SIGINT, que é enviado quando você digita Ctrl+C e é geralmente tratado como SIGTERM.

Identificadores de processo (PIDs, na sigla em inglês) são exclusivos e fornecidos pelo kernel do Linux a cada processo. Os PIDs usam namespace, o que significa que um contêiner tem o próprio conjunto de PIDs que são mapeados para PIDs no sistema de hospedagem. O primeiro processo executado ao iniciar um kernel do Linux tem o PID 1. Em um sistema operacional normal, esse processo é o sistema init, por exemplo, systemd ou SysV. Da mesma forma, o primeiro processo executado em um contêiner recebe o PID 1. O Docker e o Kubernetes usam sinais para se comunicar com os processos dentro de contêineres, principalmente para encerrá-los. O Docker e o Kubernetes só podem enviar sinais para o processo que tenha o PID 1 dentro de um contêiner.

No contexto de contêineres, os sinais PIDs e Linux criam dois problemas a serem considerados.

Problema 1: como o kernel do Linux manipula sinais

O kernel do Linux manipula os sinais de maneira diferente para o processo que tem PID 1 do que para outros processos. Os manipuladores de sinais não são registrados automaticamente para este processo, o que significa que, por padrão, sinais como SIGTERM ou SIGINT não terão efeito. Por padrão, é necessário eliminar processos usando o SIGKILL, impedindo qualquer desligamento otimizado. Dependendo do aplicativo, o uso do SIGKILL pode resultar em erros do usuário, gravações interrompidas (no armazenamento de dados) ou alertas indesejados no sistema de monitoramento.

Problema 2: como os sistemas init clássicos gerenciam processos órfãos

Os sistemas init clássicos, como o systemd, também são usados para remover (colher) processos zumbis órfãos. Processos órfãos (com pais encerrados) são anexados novamente ao processo que tem o PID 1, que os colherá quando morrerem. Um sistema init normal faz isso. Mas em um contêiner, essa responsabilidade recai sobre qualquer processo que tenha PID 1. Se esse processo não manipular adequadamente a coleta, você correrá o risco de ficar sem memória ou sem alguns outros recursos.

Esses problemas têm várias soluções comuns, descritas nas seções a seguir.

Solução 1: execute como PID 1 e registre manipuladores de sinal

Esta solução resolve apenas o primeiro problema. Ela é válida se o aplicativo gera processos filho com controle (o que geralmente é o caso), evitando o segundo problema.

A maneira mais fácil de implementar essa solução é iniciar o processo com as instruções CMD e/ou ENTRYPOINT no Dockerfile. Por exemplo, no Dockerfile a seguir, o nginx é o primeiro e único processo a ser iniciado.

FROM debian:9

RUN apt-get update && \
    apt-get install -y nginx

EXPOSE 80

CMD [ "nginx", "-g", "daemon off;" ]

Às vezes, talvez você precise preparar o ambiente no contêiner para que o processo seja executado corretamente. Nesse caso, a prática recomendada é fazer com que o contêiner execute um script de shell ao iniciar. Esse script de shell é encarregado de preparar o ambiente e iniciar o processo principal. No entanto, se você usar essa abordagem, o script de shell terá PID 1, não seu processo, e é por isso que você precisará usar o comando exec integrado para iniciar o processo do script de shell. O comando exec substitui o script pelo programa que você quiser. Seu processo então herda o PID 1.

Solução 2: use um sistema init especializado

Como você faria em um ambiente Linux mais clássico, também é possível usar um sistema init para lidar com esses problemas. No entanto, sistemas init normais, como o systemd ou o SysV, são muito complexos e grandes para esse propósito, e é por isso que recomendamos o uso de um sistema init, como o tini, criado especialmente para contêineres.

Se você usa um sistema init especializado, o processo init tem o PID 1 e executa estas ações:

  • Registra os gerenciadores de sinal corretos.
  • Garante que os sinais funcionem no aplicativo.
  • Coleta qualquer processo zumbi que venha a aparecer.

Use essa solução no próprio Docker com a opção --init do comando docker run. Para usar essa solução no Kubernetes, você precisa instalar o sistema init na imagem do contêiner e usá-la como ponto de entrada para o contêiner.

Otimizar o cache de criação do Docker

Importância: ALTA

O cache de criação do Docker pode acelerar bastante a criação de imagens de contêiner. As imagens são criadas camada por camada e, em um Dockerfile, cada instrução cria uma camada na imagem resultante. Durante uma criação, quando possível, o Docker reutiliza uma camada de uma criação anterior e ignora uma etapa custosa em potencial. O Docker pode usar o cache de criação somente se todas as etapas de criação anteriores o utilizarem. Esse comportamento geralmente é positivo e faz com que as criações sejam mais rápidas, mas é necessário considerar alguns casos.

Por exemplo, para aproveitar ao máximo o cache de criação do Docker, você precisa posicionar as etapas de criação que são alteradas com frequência na parte inferior do Dockerfile. Se você colocá-las na parte superior, o Docker não poderá usar o cache de criação para as outras etapas que estão sendo alteradas com menos frequência. Como uma nova imagem do Docker é geralmente criada para cada nova versão do código-fonte, adicione esse código à imagem o mais tarde possível no Dockerfile. No diagrama a seguir, veja que, se estiver alterando a STEP 1, o Docker poderá reutilizar somente as camadas da etapa FROM debian:9. No entanto, se você alterar a STEP 3, o Docker poderá reutilizar as camadas de STEP 1 e STEP 2.

Exemplos de como usar o cache de criação do Docker

Figura 2. Exemplos de como usar o cache de criação do Docker. Em verde, as camadas que você pode reutilizar. Em vermelho, as que precisam ser recriadas.

A reutilização de camadas tem outra consequência: se uma etapa de criação depender de qualquer tipo de cache armazenado no sistema de arquivos local, esse cache precisará ser gerado na mesma etapa. Se esse cache não estiver sendo gerado, sua etapa de criação poderá ser executada com um cache desatualizado proveniente de uma criação anterior. Você vê esse comportamento mais comumente com gerenciadores de pacotes como o apt ou o yum: é necessário atualizar seus repositórios no mesmo comando RUN que a instalação do pacote.

Se você alterar a segunda etapa RUN no Dockerfile a seguir, o comando apt-get update não será executado novamente, deixando-o com um cache do apt desatualizado.

FROM debian:9

RUN apt-get update
RUN apt-get install -y nginx

Em vez disso, mescle os dois comandos em uma única etapa RUN:

FROM debian:9

RUN apt-get update && \
    apt-get install -y nginx

Remover ferramentas desnecessárias

Importância: MÉDIA

Para proteger os aplicativos contra invasores, reduza a superfície de ataque deles removendo todas as ferramentas desnecessárias. Por exemplo, remova utilitários como o netcat, que você usa para criar um shell reverso no sistema. Se o netcat não estiver presente no contêiner, o invasor terá que encontrar outro caminho.

Essa prática recomendada e válida para qualquer carga de trabalho, mesmo que não seja em contêiner. A diferença é que é muito mais simples implementar com contêineres do que com máquinas virtuais clássicas ou servidores bare metal.

Algumas dessas ferramentas podem ser úteis para depuração. Por exemplo, se você aplicar essa prática a fundo, sistemas inteiros de registro, rastreamento, criação de perfis e Gerenciamento de desempenho de aplicativos tornam-se quase obrigatórios. Na verdade, não é mais possível depender de ferramentas de depuração locais porque elas geralmente têm alto privilégio.

Conteúdo do sistema de arquivos

Na primeira parte desta prática recomendada, falaremos sobre o conteúdo da imagem do contêiner. Mantenha a imagem com o mínimo de elementos possível. Se for possível compilar o aplicativo em um único binário vinculado estaticamente, adicione-o à imagem de rascunho para gerar uma imagem final que contenha apenas o aplicativo. Ao reduzir o número de ferramentas empacotadas na imagem, você diminui a ação de um invasor em potencial no contêiner. Para mais informações, consulte Criar a menor imagem possível.

Segurança do sistema de arquivos

Não ter ferramentas na sua imagem não é suficiente: é necessário evitar que invasores em potencial instalem as próprias ferramentas. É possível combinar dois métodos aqui:

  • Evite executar como root dentro do container: este método oferece uma primeira camada de segurança e pode impedir, por exemplo, que invasores modifiquem arquivos de propriedade do root usando um gerenciador de pacotes incorporado em sua imagem (como apt-get ou apk). Para que este método seja útil, você precisa desativar ou desinstalar o comando sudo. Este tópico é abordado mais amplamente em Evite executar como root.

  • Inicie o contêiner no modo somente leitura. Basta usar a sinalização --read-only no comando docker run ou a opção readOnlyRootFilesystem no Kubernetes. É possível aplicar isso no Kubernetes usando PodSecurityPolicy.

Criar a menor imagem possível

Importância: MÉDIA

Criar uma imagem menor oferece vantagens como tempos de upload e download mais rápidos, o que é importante principalmente na hora de inicialização a frio de um pod no Kubernetes: quanto menor a imagem, mais rápido o node poderá fazer o download dela. No entanto, criar uma imagem pequena pode ser difícil, já que é fácil incluir inadvertidamente dependências de criação ou camadas não otimizadas na imagem final.

Usar a menor imagem base possível

A imagem base é aquela referenciada na instrução FROM no Dockerfile. Todas as outras instruções no Dockerfile fazem criações sobre esta imagem. Quanto menor a imagem base, menor a imagem resultante e mais rápido o tempo de download dela. Por exemplo, a imagem alpine:3.7 é 71 MB menor que a centos:7.

É possível até usar a imagem base de rascunho, que é uma imagem vazia em que você cria o próprio ambiente de execução. Se o aplicativo for um binário vinculado estaticamente, será fácil usar a imagem base de rascunho:

FROM scratch
COPY mybinary /mybinary
CMD [ "/mybinary" ]

O projeto distroless fornece as imagens base mínimas em várias linguagens diferentes. As imagens contêm somente as dependências do ambiente de execução para a linguagem, mas não incluem muitas ferramentas que você esperaria encontrar em uma distribuição do Linux (shells, gerenciadores de pacotes e assim por diante).

Reduzir a quantidade de desordem na imagem

Para reduzir o tamanho da imagem, instale apenas o que é estritamente necessário dentro dela. Pode ser tentador instalar pacotes extras e, em seguida, removê-los em uma etapa posterior. No entanto, essa abordagem não é suficiente. Como cada instrução do Dockerfile cria uma camada, a remoção de dados da imagem em uma etapa posterior àquela que a criou não reduz o tamanho da imagem geral. Os dados ainda estão lá, só que ocultos em uma camada mais profunda. Veja este exemplo:

Dockerfile ruim Dockerfile bom

FROM debian:9
RUN apt-get update && \ apt-get install -y \ [buildpackage] RUN [build my app] RUN apt-get autoremove --purge \ -y [buildpackage] && \ apt-get -y clean && \ rm -rf /var/lib/apt/lists/*

FROM debian:9
RUN apt-get update && \ apt-get install -y \ [buildpackage] && \ [build my app] && \ apt-get autoremove --purge \ -y [buildpackage] && \ apt-get -y clean && \ rm -rf /var/lib/apt/lists/*

Na versão ruim do Dockerfile, o [buildpackage] e os arquivos em /var/lib/apt/lists/* ainda existem na camada correspondente à primeira RUN. Essa camada faz parte da imagem, e é preciso fazer o upload e download dela com o restante, mesmo que os dados nela contidos não estejam acessíveis na imagem resultante.

Na versão boa do Dockerfile, tudo é feito em uma única camada que contém apenas o aplicativo criado. O [buildpackage] e os arquivos em /var/lib/apt/lists/* não existem em nenhum lugar na imagem resultante nem mesmo ocultos em uma camada mais profunda.

Para mais informações sobre camadas de imagem, consulte Otimizar o cache de criação do Docker.

Outra ótima maneira de reduzir a quantidade de desordem na imagem é usar criações em vários estágios (implantadas no Docker 17.05). Com elas, você desenvolve o aplicativo em um primeiro contêiner "de criação" e usa o resultado em outro, com o mesmo Dockerfile.

Processo de criação multi-estágio do Docker

Figura 3. O processo de criação de vários estágios do Docker.

No Dockerfile a seguir, o binário hello é criado em um primeiro contêiner e injetado em um segundo. Como o segundo contêiner é baseado em uma imagem vazia, a imagem resultante contém apenas o binário hello, e não o arquivo de origem e os de objetos necessários durante a criação. O binário precisa estar vinculado estaticamente para funcionar sem a necessidade de qualquer biblioteca externa na imagem de rascunho.

FROM golang:1.10 as builder

WORKDIR /tmp/go
COPY hello.go ./
RUN CGO_ENABLED=0 go build -a -ldflags '-s' -o hello

FROM scratch
CMD [ "/hello" ]
COPY --from=builder /tmp/go/hello /hello

Tentar criar imagens com camadas comuns

Se você precisar fazer download de uma imagem do Docker, ele primeiro verificará se você já tem algumas das camadas que estão nela. Se você tiver essas camadas, o download não será feito. Essa situação pode ocorrer se você fez download anteriormente de outra imagem que tem a mesma base da imagem que você está fazendo download no momento. O resultado é que a quantidade de dados de download é muito menor para a segunda imagem.

Em nível organizacional, você aproveita essa redução fornecendo aos desenvolvedores um conjunto de imagens base comuns e padrão. Seus sistemas precisam fazer download de cada imagem base somente uma vez. Após o download inicial, apenas as camadas que tornam cada imagem única são necessárias. Na verdade, quanto mais suas imagens tiverem em comum, mais rápido será o download delas.

Tente criar imagens com camadas comuns

Figura 4. Como criar imagens com camadas comuns.

Usar a varredura de vulnerabilidade no Container Registry

Importância: MÉDIA

Vulnerabilidades de software são um problema bem conhecido no mundo dos servidores bare-metal e máquinas virtuais. Uma maneira comum de lidar com essas vulnerabilidades é usar um sistema de inventário centralizado que lista os pacotes instalados em cada servidor. Assine os feeds de vulnerabilidades dos sistemas operacionais de upstream para ser informado quando uma vulnerabilidade afetar seus servidores e corrigi-los de acordo.

No entanto, como os contêineres precisam ser imutáveis (consulte Contêineres imutáveis e sem estado para mais detalhes), não os corrija no local em caso de vulnerabilidade. A prática recomendada é recriar a imagem, incluindo os patches, e reimplantá-la. Os contêineres têm um ciclo de vida muito mais curto e uma identidade menos definida do que os servidores. Portanto, usar um sistema de inventário centralizado semelhante é uma maneira ruim de detectar vulnerabilidades em contêineres.

Para ajudar a solucionar esse problema, o Container Registry tem um recurso de verificação de vulnerabilidade. Quando ativado, esse recurso identifica as vulnerabilidades do pacote em suas imagens de contêiner. As imagens são verificadas quando são carregadas no Container Registry e sempre que houver uma atualização no banco de dados de vulnerabilidades. É possível agir de acordo com as informações relatadas por esse recurso de várias maneiras:

  • Crie um job do tipo cron que liste vulnerabilidades e acione o processo para corrigi-las, onde existir uma correção.
  • Assim que uma vulnerabilidade for detectada, use a integração do Cloud Pub/Sub para acionar o processo de correção que sua empresa usa.

Recomendamos automatizar o processo de correção e contar com o canal de integração contínua atual, inicialmente usado para criar a imagem. Se estiver confiante em seu canal de implantação contínua, talvez também queira implantar automaticamente a imagem fixa quando estiver pronta. No entanto, a maioria das pessoas prefere uma etapa de verificação manual antes da implantação. O processo a seguir efetua isso:

  1. Armazene suas imagens no Container Registry e ative a varredura de vulnerabilidade.
  2. Configure um job que busque regularmente novas vulnerabilidades do Container Registry e acione uma recriação das imagens, se necessário.
  3. Quando as imagens novas forem criadas, faça com que o sistema de implantação contínua as implante em um ambiente de preparação.
  4. Verifique manualmente os problemas no ambiente de preparação.
  5. Se nenhum problema for encontrado, acione manualmente a implantação para produção.

Atribuir as tags corretas às imagens

Importância: MÉDIA

As imagens do Docker geralmente são identificadas por dois componentes: o nome e a tag. Por exemplo, para a imagem google/cloud-sdk:193.0.0, "google/cloud-sdk" é o nome e "193.0.0" é a tag. A tag "mais recente" será usada por padrão se você não fornecer uma nos seus comandos do Docker. O par nome/tag é exclusivo a qualquer momento. No entanto, você reatribui uma tag a uma imagem diferente, conforme necessário.

Quando você cria uma imagem, cabe a você atribuir a tag a ela corretamente. Siga uma política coerente e consistente de atribuição de tags. Documente sua política de atribuição de tags para que os usuários da imagem possam entendê-la facilmente.

As imagens de contêiner são uma forma de empacotar e lançar um software. Atribuir uma tag à imagem permite que os usuários identifiquem uma versão específica do seu software para fazer download dela. Por esse motivo, vincule o sistema de tags nas imagens do contêiner à política de lançamento do seu software.

Atribuir tags usando controle de versão semântico

Uma maneira comum de lançar softwares é "atribuir tag" (como no comando git tag) a uma versão específica do código-fonte com um número de versão. A Especificação de controle de versão semântico fornece uma maneira limpa de lidar com números de versão. Neste sistema, seu software tem um número de versão de três partes: "X.Y.Z", em que:

  • X é a versão principal, incrementada apenas para alterações de API incompatíveis;
  • Y é a versão secundária, incrementada para novos recursos;
  • Z é a versão do patch, incrementada para correções de bugs.

Cada incremento no número de versão secundária ou de patch precisa ser para uma alteração compatível com versões anteriores.

Se você usa este sistema, ou um similar, atribua uma tag às suas imagens de acordo com a política a seguir:

  • A tag "mais recente" sempre se refere à imagem mais recente (possivelmente estável). Essa tag é movida assim que uma imagem nova é criada.
  • A tag "X.Y.Z" se refere a uma versão específica do seu software. Não a mova para outra imagem.
  • A tag "X.Y" se refere à última versão de patch do branch secundário "X.Y" do seu software. Ela é movida quando uma nova versão de patch é lançada.
  • A tag "X" se refere à versão mais recente do último lançamento secundário do branch principal "X". Ela é movida quando uma nova versão de patch ou uma nova versão secundária é lançada.

O uso dessa política oferece aos usuários a flexibilidade de escolher qual versão do seu software eles querem usar. Eles podem escolher uma versão "X.Y.Z" específica e ter a garantia de que a imagem nunca será alterada ou podem receber atualizações automaticamente, escolhendo uma tag menos específica.

Atribuir tags usando o hash de commit do Git

Se você tem um sistema avançado de entrega contínua e lança seu software com frequência, provavelmente não usa números de versão, conforme descrito na Especificação de controle de versão semântica. Nesse caso, uma maneira comum de manipular números de versão é usar o hash de commit SHA-1 do Git (ou uma versão curta dele) como o número da versão. Por definição, o hash de commit do Git é imutável e faz referência a uma versão específica do seu software.

Use esse hash de commit como um número de versão para seu software, mas também como uma tag para a imagem do Docker criada dessa versão específica do software. Isso faz com que as imagens do Docker sejam rastreáveis: como nesse caso a tag da imagem é imutável, você sabe instantaneamente qual versão específica do seu software está sendo executada dentro de um determinado contêiner. Em seu canal de Entrega Contínua, automatize a atualização do número da versão usada para suas implantações.

Refletir cuidadosamente sobre quando usar uma imagem pública

Importância: N/D

Uma das grandes vantagens do Docker é o grande número de imagens disponíveis publicamente, para todos os tipos de software. Essas imagens permitem que você dê os primeiros passos rapidamente. No entanto, quando você estiver criando uma estratégia de contêiner para sua empresa, provavelmente terá restrições que as imagens fornecidas publicamente não poderão atender. Aqui estão alguns exemplos de restrições que podem impossibilitar o uso de imagens públicas:

  • Você quer controlar exatamente o que está dentro de suas imagens.
  • Você não quer depender de um repositório externo.
  • Você quer controlar estritamente as vulnerabilidades em seu ambiente de produção.
  • Você quer o mesmo sistema operacional de base em todas as imagens.

A resposta a todas essas restrições é a mesma e, infelizmente, é cara: você precisa criar suas próprias imagens. Isso é bom para um número limitado de imagens, mas esse número tem uma tendência a crescer rapidamente. Para ter alguma chance de gerenciar tal sistema em escala, pense nestas possibilidades:

  • Uma maneira automatizada e confiável de criar imagens, mesmo para aquelas criadas raramente. Os acionadores de criação no Cloud Build são uma boa maneira de realizar isso.
  • Uma imagem de base padronizada. O Google fornece algumas imagens de base que podem ser usadas.
  • Uma maneira automatizada de propagar atualizações para a imagem de base para imagens "filhas".
  • Uma maneira de direcionar vulnerabilidades em suas imagens. Para ver mais informações, consulte Usar análise de vulnerabilidade no Container Registry.
  • Uma maneira de aplicar seus padrões internos em imagens criadas pelas diferentes equipes em sua empresa.

Várias ferramentas estão disponíveis para ajudá-lo a aplicar políticas nas imagens que você cria e implanta:

  • O container-diff pode analisar o conteúdo das imagens e até comparar duas imagens.
  • O container-structure-test pode testar se o conteúdo de uma imagem está em conformidade com um conjunto de regras que você define.
  • O Grafeas é uma API de metadados de artefatos, em que você armazena metadados das suas imagens para verificar posteriormente se elas estão em conformidade com suas políticas.
  • O Kubernetes tem controladores de admissão que podem ser usados para verificar vários pré-requisitos antes da implantação de uma carga de trabalho.
  • O Kubernetes também tem políticas de segurança de pod, que pode ser usadas para aplicar o uso de opções de segurança no cluster.

Também pode ser útil adotar um sistema híbrido: usando uma imagem pública como Debian ou Alpine como a imagem base e criando tudo sobre essa imagem. Ou usar imagens públicas para algumas de suas imagens não críticas e criar suas próprias imagens em outros casos. Essas perguntas não têm respostas certas ou erradas, mas você precisa abordá-las.

Uma observação sobre licenças

Antes de incluir bibliotecas e pacotes de terceiros na imagem do Docker, verifique se as respectivas licenças permitem isso. Licenças de terceiros também podem impor restrições à redistribuição, que se aplicam quando você publica uma imagem do Docker em um registro público.

Próximas etapas

Teste outros recursos do Google Cloud Platform. Consulte nossos tutoriais.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…