One place for hosting & domains

      Imagens

      Como Otimizar Imagens Docker para Produção


      O autor escolheu a Code.org para receber uma doação como parte do programa Write for DOnations.

      Introdução

      Em um ambiente de produção, o Docker facilita a criação, o deployment e a execução de aplicações dentro de containers. Os containers permitem que os desenvolvedores reúnam aplicações e todas as suas principais necessidades e dependências em um único pacote que você pode transformar em uma imagem Docker e replicar. As imagens Docker são construídas a partir de Dockerfiles. O Dockerfile é um arquivo onde você define como será a imagem, qual sistema operacional básico ela terá e quais comandos serão executados dentro dela.

      Imagens Docker muito grandes podem aumentar o tempo necessário para criar e enviar imagens entre clusters e provedores de nuvem. Se, por exemplo, você tem uma imagem do tamanho de um gigabyte para enviar toda vez que um de seus desenvolvedores aciona uma compilação, a taxa de transferência que você cria em sua rede aumentará durante o processo de CI/CD, tornando sua aplicação lenta e, consequentemente, custando seus recursos. Por causa disso, as imagens Docker adequadas para produção devem ter apenas as necessidades básicas instaladas.

      Existem várias maneiras de diminuir o tamanho das imagens Docker para otimizá-las para a produção. Em primeiro lugar, essas imagens geralmente não precisam de ferramentas de compilação para executar suas aplicações e, portanto, não há necessidade de adicioná-las. Através do uso de um processo de construção multi-stage, você pode usar imagens intermediárias para compilar e construir o código, instalar dependências e empacotar tudo no menor tamanho possível, depois copiar a versão final da sua aplicação para uma imagem vazia sem ferramentas de compilação. Além disso, você pode usar uma imagem com uma base pequena, como o Alpine Linux. O Alpine é uma distribuição Linux adequada para produção, pois possui apenas as necessidades básicas que sua aplicação precisa para executar.

      Neste tutorial, você otimizará as imagens Docker em algumas etapas simples, tornando-as menores, mais rápidas e mais adequadas à produção. Você construirá imagens para um exemplo de API em Go em vários containers Docker diferentes, começando com o Ubuntu e imagens específicas de linguagens, e então passando para a distribuição Alpine. Você também usará compilações multi-stage para otimizar suas imagens para produção. O objetivo final deste tutorial é mostrar a diferença de tamanho entre usar imagens padrão do Ubuntu e as equivalentes otimizadas, e mostrar a vantagem das compilações em vários estágios (multi-stage). Depois de ler este tutorial, você poderá aplicar essas técnicas aos seus próprios projetos e pipelines de CI/CD.

      Nota: Este tutorial utiliza uma API escrita em Go como um exemplo. Esta simples API lhe dará uma compreensão clara de como você abordaria a otimização de microsserviços em Go com imagens Docker. Embora este tutorial use uma API Go, você pode aplicar esse processo a praticamente qualquer linguagem de programação.

      Pré-requisitos

      Antes de começar, você precisará de:

      Passo 1 — Baixando a API Go de Exemplo

      Antes de otimizar sua imagem Docker, você deve primeiro fazer o download da API de exemplo, a partir da qual você construirá suas imagens Docker. O uso de uma API Go simples mostrará todas as principais etapas de criação e execução de uma aplicação dentro de um container Docker. Este tutorial usa o Go porque é uma linguagem compilada como o C++ ou Java, mas ao contrário dele, tem uma pegada muito pequena.

      No seu servidor, comece clonando a API Go de exemplo:

      • git clone https://github.com/do-community/mux-go-api.git

      Depois de clonar o projeto, você terá um diretório chamado mux-go-api em seu servidor. Mova-se para este diretório com cd:

      Este será o diretório home do seu projeto. Você construirá suas imagens Docker a partir desse diretório. Dentro dele você encontrará o código fonte para uma API escrita em Go no arquivo api.go. Embora essa API seja mínima e tenha apenas alguns endpoints, ela será apropriada para simular uma API pronta para produção para os propósitos deste tutorial.

      Agora que você baixou a API Go de exemplo, você está pronto para criar uma imagem base do Ubuntu no Docker, com a qual você poderá comparar as imagens posteriores e otimizadas.

      Passo 2 — Construindo uma Imagem Base do Ubuntu

      Para a sua primeira imagem Docker, será útil ver como ela é quando você começa com uma imagem base do Ubuntu. Isso irá empacotar sua API de exemplo em um ambiente similar ao software que você já está rodando no seu servidor Ubuntu. Isso irá empacotar sua API de exemplo em um ambiente similar ao software que você já está rodando no seu servidor Ubuntu. Dentro da imagem, você instalará os vários pacotes e módulos necessários para executar sua aplicação. Você descobrirá, no entanto, que esse processo cria uma imagem bastante pesada do Ubuntu que afetará o tempo de compilação e a legibilidade do código do seu Dockerfile.

      Comece escrevendo um Dockerfile que instrui o Docker a criar uma imagem do Ubuntu, instalar o Go e executar a API de exemplo. Certifique-se de criar o Dockerfile no diretório do repositório clonado. Se você clonou no diretório home, ele deve ser $HOME/mux-go-api.

      Crie um novo arquivo chamado Dockerfile.ubuntu. Abra-o no nano ou no seu editor de texto favorito:

      • nano ~/mux-go-api/Dockerfile.ubuntu

      Neste Dockerfile, você irá definir uma imagem do Ubuntu e instalar o Golang. Em seguida, você vai continuar a instalar as dependências necessárias e construir o binário. Adicione o seguinte conteúdo ao Dockerfile.ubuntu:

      ~/mux-go-api/Dockerfile.ubuntu

      FROM ubuntu:18.04
      
      RUN apt-get update -y 
        && apt-get install -y git gcc make golang-1.10
      
      ENV GOROOT /usr/lib/go-1.10
      ENV PATH $GOROOT/bin:$PATH
      ENV GOPATH /root/go
      ENV APIPATH /root/go/src/api
      
      WORKDIR $APIPATH
      COPY . .
      
      RUN  
        go get -d -v 
        && go install -v 
        && go build
      
      EXPOSE 3000
      CMD ["./api"]
      

      Começando do topo, o comando FROM especifica qual sistema operacional básico a imagem terá. A seguir, o comando RUN instala a linguagem Go durante a criação da imagem. ENV define as variáveis de ambiente específicas que o compilador Go precisa para funcionar corretamente. WORKDIR especifica o diretório onde queremos copiar o código, e o comando COPY pega o código do diretório onde o Dockerfile.ubuntu está e o copia para a imagem. O comando RUN final instala as dependências do Go necessárias para o código-fonte compilar e executar a API.

      Nota: Usar os operadores && para unir os comandos RUN é importante para otimizar os Dockerfiles, porque todo comando RUN criará uma nova camada, e cada nova camada aumentará o tamanho da imagem final.

      Salve e saia do arquivo. Agora você pode executar o comando build para criar uma imagem Docker a partir do Dockerfile que você acabou de criar:

      • docker build -f Dockerfile.ubuntu -t ubuntu .

      O comando build constrói uma imagem a partir de um Dockerfile. A flag -f especifica que você deseja compilar a partir do arquivo Dockerfile.ubuntu, enquanto -t significa tag, o que significa que você está marcando a imagem com o nome ubuntu. O ponto final representa o contexto atual onde o Dockerfile.ubuntu está localizado.

      Isso vai demorar um pouco, então sinta-se livre para fazer uma pausa. Quando a compilação estiver concluída, você terá uma imagem Ubuntu pronta para executar sua API. Mas o tamanho final da imagem pode não ser ideal; qualquer coisa acima de algumas centenas de MB para essa API seria considerada uma imagem excessivamente grande.

      Execute o seguinte comando para listar todas as imagens Docker e encontrar o tamanho da sua imagem Ubuntu:

      Você verá a saída mostrando a imagem que você acabou de criar:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 61b2096f6871 33 seconds ago 636MB . . .

      Como é destacado na saída, esta imagem tem um tamanho de 636MB para uma API Golang básica, um número que pode variar um pouco de máquina para máquina. Em múltiplas compilações, esse grande tamanho afetará significativamente os tempos de deployment e a taxa de transferência da rede.

      Nesta seção, você construiu uma imagem Ubuntu com todas as ferramentas e dependências necessárias do Go para executar a API que você clonou no Passo 1. Na próxima seção, você usará uma imagem Docker pré-criada e específica da linguagem para simplificar seu Dockerfile e agilizar o processo de criação.

      Passo 3 — Construindo uma Imagem Base Específica para a Linguagem

      Imagens pré-criadas são imagens básicas comuns que os usuários modificaram para incluir ferramentas específicas para uma situação. Os usuários podem, então, enviar essas imagens para o repositório de imagens Docker Hub, permitindo que outros usuários usem a imagem compartilhada em vez de ter que escrever seus próprios Dockerfiles individuais. Este é um processo comum em situações de produção, e você pode encontrar várias imagens pré-criadas no Docker Hub para praticamente qualquer caso de uso. Neste passo, você construirá sua API de exemplo usando uma imagem específica do Go que já tenha o compilador e as dependências instaladas.

      Com imagens base pré-criadas que já contêm as ferramentas necessárias para criar e executar sua aplicação, você pode reduzir significativamente o tempo de criação. Como você está começando com uma base que tem todas as ferramentas necessárias pré-instaladas, você pode pular a adição delas ao seu Dockerfile, fazendo com que pareça muito mais limpo e, finalmente, diminuindo o tempo de construção.

      Vá em frente e crie outro Dockerfile e nomeie-o como Dockerfile.golang. Abra-o no seu editor de texto:

      • nano ~/mux-go-api/Dockerfile.golang

      Este arquivo será significativamente mais conciso do que o anterior, porque tem todas as dependências, ferramentas e compilador específicos do Go pré-instalados.

      Agora, adicione as seguintes linhas:

      ~/mux-go-api/Dockerfile.golang

      FROM golang:1.10
      
      WORKDIR /go/src/api
      COPY . .
      
      RUN 
          go get -d -v 
          && go install -v 
          && go build
      
      EXPOSE 3000
      CMD ["./api"]
      

      Começando do topo, você verá que a instrução FROM agora é golang:1.10. Isso significa que o Docker buscará uma imagem Go pré-criada do Docker Hub que tenha todas as ferramentas Go necessárias já instaladas.

      Agora, mais uma vez, compile a imagem do Docker com:

      • docker build -f Dockerfile.golang -t golang .

      Verifique o tamanho final da imagem com o seguinte comando:

      Isso produzirá uma saída semelhante à seguinte:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE golang latest eaee5f524da2 40 seconds ago 744MB . . .

      Embora o próprio Dockerfile seja mais eficiente e o tempo de compilação seja menor, o tamanho total da imagem aumentou. A imagem pré-criada do Golang está em torno de 744MB, uma quantidade significativa.

      Essa é a maneira preferida de criar imagens Docker. Ela lhe dá uma imagem base que a comunidade aprovou como o padrão a ser usado para a linguagem especificada, neste caso, Go. No entanto, para tornar uma imagem pronta para produção, você precisa cortar partes que a aplicação em execução não precisa.

      Tenha em mente que o uso dessas imagens pesadas é bom quando você não tem certeza sobre suas necessidades. Sinta-se à vontade para usá-las como containers descartáveis, bem como a base para a construção de outras imagens. Para fins de desenvolvimento ou teste, onde você não precisa pensar em enviar imagens pela rede, é perfeitamente aceitável usar imagens pesadas. Mas, se você quiser otimizar os deployments, precisará fazer o seu melhor para tornar suas imagens o menor possível.

      Agora que você testou uma imagem específica da linguagem, você pode passar para a próxima etapa, na qual usará a distribuição leve do Alpine Linux como uma imagem base para tornar a imagem Docker mais leve.

      Passo 4 — Construindo Imagens Base do Alpine

      Um dos passos mais fáceis para otimizar as imagens Docker é usar imagens base menores. Alpine é uma distribuição Linux leve projetada para segurança e eficiência de recursos. A imagem Docker do Alpine usa musl libc e BusyBox para ficar compacta, exigindo não mais que 8MB em um container para ser executada. O tamanho minúsculo é devido a pacotes binários sendo refinados e divididos, dando a você mais controle sobre o que você instala, o que mantém o ambiente menor e mais eficiente possível.

      O processo de criação de uma imagem Alpine é semelhante ao modo como você criou a imagem do Ubuntu no Passo 2. Primeiro, crie um novo arquivo chamado Dockerfile.alpine:

      • nano ~/mux-go-api/Dockerfile.alpine

      Agora adicione este trecho:

      ~/mux-go-api/Dockerfile.alpine

      FROM alpine:3.8
      
      RUN apk add --no-cache 
          ca-certificates 
          git 
          gcc 
          musl-dev 
          openssl 
          go
      
      ENV GOPATH /go
      ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
      ENV APIPATH $GOPATH/src/api
      RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" "$APIPATH" && chmod -R 777 "$GOPATH"
      
      WORKDIR $APIPATH
      COPY . .
      
      RUN 
          go get -d -v 
          && go install -v 
          && go build
      
      EXPOSE 3000
      CMD ["./api"]
      

      Aqui você está adicionando o comando apk add para utilizar o gerenciador de pacotes do Alpine para instalar o Go e todas as bibliotecas que ele requer. Tal como acontece com a imagem do Ubuntu, você precisa definir as variáveis de ambiente também.

      Vá em frente e compile a imagem:

      • docker build -f Dockerfile.alpine -t alpine .

      Mais uma vez, verifique o tamanho da imagem:

      Você receberá uma saída semelhante à seguinte:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest ee35a601158d 30 seconds ago 426MB . . .

      O tamanho caiu para cerca de 426MB.

      O tamanho reduzido da imagem base Alpine reduziu o tamanho final da imagem, mas há mais algumas coisas que você pode fazer para torná-la ainda menor.

      A seguir, tente usar uma imagem Alpine pré-criada para o Go. Isso tornará o Dockerfile mais curto e também reduzirá o tamanho da imagem final. Como a imagem Alpine pré-criada para o Go é construída com o Go compilado dos fontes, sua tamanho é significativamente menor.

      Comece criando um novo arquivo chamado Dockerfile.golang-alpine:

      • nano ~/mux-go-api/Dockerfile.golang-alpine

      Adicione o seguinte conteúdo ao arquivo:

      ~/mux-go-api/Dockerfile.golang-alpine

      FROM golang:1.10-alpine3.8
      
      RUN apk add --no-cache --update git
      
      WORKDIR /go/src/api
      COPY . .
      
      RUN go get -d -v 
        && go install -v 
        && go build
      
      EXPOSE 3000
      CMD ["./api"]
      

      As únicas diferenças entre Dockerfile.golang-alpine e Dockerfile.alpine são o comando FROM e o primeiro comando RUN. Agora, o comando FROM especifica uma imagem golang com a tag 1.10-alpine3.8 e RUN só tem um comando para a instalação do Git. Você precisa do Git para o comando go get para trabalhar no segundo comando RUN na parte inferior do Dockerfile.golang-alpine.

      Construa a imagem com o seguinte comando:

      • docker build -f Dockerfile.golang-alpine -t golang-alpine .

      Obtenha sua lista de imagens:

      Você receberá a seguinte saída:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE golang-alpine latest 97103a8b912b 49 seconds ago 288MB

      Agora o tamanho da imagem está em torno de 288MB.

      Mesmo que você tenha conseguido reduzir bastante o tamanho, há uma última coisa que você pode fazer para preparar a imagem para a produção. É chamado de uma compilação de múltiplos estágios ou multi-stage. Usando compilações multi-stage, você pode usar uma imagem para construir a aplicação enquanto usa outra imagem mais leve para empacotar a aplicação compilada para produção, um processo que será executado no próximo passo.

      Passo 5 — Excluindo Ferramentas de Compilação em uma Compilação Multi-Stage

      Idealmente, as imagens que você executa em produção não devem ter nenhuma ferramenta de compilação instalada ou dependências redundantes para a execução da aplicação de produção. Você pode removê-las da imagem Docker final usando compilações multi-stage. Isso funciona através da construção do binário, ou em outros termos, a aplicação Go compilada, em um container intermediário, copiando-o em seguida para um container vazio que não tenha dependências desnecessárias.

      Comece criando outro arquivo chamado Dockerfile.multistage:

      • nano ~/mux-go-api/Dockerfile.multistage

      O que você vai adicionar aqui será familiar. Comece adicionando o mesmo código que está em Dockerfile.golang-alpine. Mas desta vez, adicione também uma segunda imagem onde você copiará o binário a partir da primeira imagem.

      ~/mux-go-api/Dockerfile.multistage

      FROM golang:1.10-alpine3.8 AS multistage
      
      RUN apk add --no-cache --update git
      
      WORKDIR /go/src/api
      COPY . .
      
      RUN go get -d -v 
        && go install -v 
        && go build
      
      ##
      
      FROM alpine:3.8
      COPY --from=multistage /go/bin/api /go/bin/
      EXPOSE 3000
      CMD ["/go/bin/api"]
      

      Salve e feche o arquivo. Aqui você tem dois comandos FROM. O primeiro é idêntico ao Dockerfile.golang-alpine, exceto por ter um AS multistage adicional no comando FROM. Isto lhe dará um nome de multistage, que você irá referenciar na parte inferior do arquivo Dockerfile.multistage. No segundo comando FROM, você pegará uma imagem base alpine e copiará para dentro dela usando o COPY, a aplicação Go compilada da imagem multiestage. Esse processo reduzirá ainda mais o tamanho da imagem final, tornando-a pronta para produção.

      Execute a compilação com o seguinte comando:

      • docker build -f Dockerfile.multistage -t prod .

      Verifique o tamanho da imagem agora, depois de usar uma compilação multi-stage.

      Você encontrará duas novas imagens em vez de apenas uma:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE prod latest 82fc005abc40 38 seconds ago 11.3MB <none> <none> d7855c8f8280 38 seconds ago 294MB . . .

      A imagem <none> é a imagem multistage construída com o comando FROM golang:1.10-alpine3.8 AS multistage. Ela é apenas um intermediário usado para construir e compilar a aplicação Go, enquanto a imagem prod neste contexto é a imagem final que contém apenas a aplicação Go compilada.

      A partir dos 744MB iniciais, você reduziu o tamanho da imagem para aproximadamente 11,3MB. Manter o controle de uma imagem minúscula como esta e enviá-la pela rede para os servidores de produção será muito mais fácil do que com uma imagem de mais de 700MB e economizará recursos significativos a longo prazo.

      Conclusão

      Neste tutorial, você otimizou as imagens Docker para produção usando diferentes imagens Docker de base e uma imagem intermediária para compilar e construir o código. Dessa forma, você empacotou sua API de exemplo no menor tamanho possível. Você pode usar essas técnicas para melhorar a velocidade de compilação e deployment de suas aplicações Docker e de qualquer pipeline de CI/CD que você possa ter.

      Se você estiver interessado em aprender mais sobre como criar aplicações com o Docker, confira o nosso tutorial Como Construir uma Aplicação Node.js com o Docker. Para obter informações mais conceituais sobre como otimizar containers, consulte Building Optimized Containers for Kubernetes.



      Source link

      Como Construir Imagens Docker e Hospedar um Repositório de Imagens Docker com o GitLab


      Introdução

      A containerização está rapidamente se tornando o método de empacotamento e deploy de aplicações mais aceito nos ambientes de nuvem. A padronização que ele fornece, juntamente com sua eficiência de recursos (quando comparado a máquinas virtuais completas) e flexibilidade, o tornam um grande facilitador da moderna mentalidade DevOps. Muitas estratégias interessantes de deployment, orquestração e monitoramento nativas para nuvem tornam-se possíveis quando suas aplicações e microsserviços são totalmente containerizados.

      Os containers Docker são de longe os tipos mais comuns de container atualmente. Embora os repositórios públicos de imagem do Docker como o Docker Hub estejam repletos de imagens de software opensource containerizado que você pode fazer um docker pull hoje, para código privado você precisará pagar um serviço para construir e armazenar suas imagens, ou executar seu próprio software para fazer isso.

      O GitLab Community Edition é um pacote de software auto-hospedado que fornece hospedagem de repositório Git, acompanhamento de projetos, serviços de CI/CD, e um registro de imagem Docker, entre outros recursos. Neste tutorial vamos utilizar o serviço de integração contínua do GitLab para construir imagens Docker a partir de uma aplicação de exemplo em Node.js. Estas imagens serão então testadas e carregadas para o nosso próprio registro privado do Docker.

      Pré-requisitos

      Antes de começarmos, precisamos configurar um servidor GitLab seguro, e um GitLab CI runner para executar tarefas de integração contínua. As seções abaixo fornecerão links e maiores detalhes.

      Um Servidor Gitlab Protegido com SSL

      Para armazenar nosso código fonte, executar tarefas de CI/CD, e hospedar um registro Docker, precisamos de uma instância do GitLab instalada em um servidor Ubuntu 16.04. Atualmente, o GitLab recomenda um servidor com pelo menos 2 núcleos de CPU e 4GB de RAM. Adicionalmente, iremos proteger o servidor com certificados SSL do Let’s Encrypt. Para fazer isto, precisaremos de um nome de domínio apontando para o servidor.

      Você pode completar esses pré-requisitos com os seguintes tutoriais:

      Um GitLab CI Runner

      O tutorial Como configurar pipelines de integração contínua com o GitLab CI no Ubuntu 16.04 fornecerá uma visão geral do serviço de CI ou integração contínua do GitLab e mostrará como configurar um CI runner para processar jobs. Vamos construir isso em cima da aplicação de demonstração e da infraestrutura do runner criados neste tutorial.

      Passo 1 — Configurando um GitLab CI Runner Privilegiado

      No pré-requisito do tutorial de integração contínua com o GitLab, configuramos um GitLab runner utilizando sudo gitlab-runner register e seu processo de configuração interativo. Este runner é capaz de executar builds e testes de software dentro de containers Docker isolados.

      Entretanto, para se construir imagens Docker, nosso runner precisa de acesso total ao próprio serviço do Docker. A maneira recomendada de se configurar isto é utilizar a imagem docker-in-docker oficial do Docker para executar os jobs. Isto requer conceder ao runner um modo de execução privileged ou privilegiado. Portanto, criaremos um segundo runner com este modo ativado.

      Nota: Conceder ao runner o modo privileged basicamente desativa todas as vantagens de segurança da utilização de containers. Infelizmente, os outros métodos de ativar runners compatíveis com o Docker também carregam implicações de segurança semelhantes. Por favor, veja a documentação oficial do GitLab no Docker Build para aprender mais sobre as diferentes opções de runners e qual é a melhor para a sua situação.

      Como existem implicações de segurança para a utilização de runner privilegiado, vamos criar um runner específico do projeto que aceitará somente jobs de Docker em nosso projeto hello_hapi (Os administradores de GitLab sempre podem adicionar manualmente esse runner a outros projetos posteriormente). A partir da página do nosso projeto hello_hapi, clique em Settings na parte inferior do menu à esquerda, em seguida clique em CI/CD no sub-menu:

      Agora, clique no botão Expand ao lado da seção de configurações de Runners:

      Haverá algumas informações sobre como configurar um Specific Runner, incluindo um token de registro. Tome nota desse token. Quando o utilizamos para registrar um novo runner, o runner será bloqueado apenas para este projeto.

      Estando nesta página, clique no botão Disable shared Runners. Queremos ter certeza de que nossos jobs de Docker sempre executarão em nosso runner privilegiado. Se um runner compartilhado não privilegiado estivesse disponível, o GitLab pode optar por utilizá-lo, o que resultaria em erros de build.

      Faça o login no servidor que possui o seu CI runner atual. Se você não tiver uma máquina já configurada com os runners, volte e complete a seção Installing the GitLab CI Runner Service do tutorial de pré-requisitos antes de continuar.

      Agora, execute o seguinte comando para configurar o runner privilegiado específico do projeto:

      • sudo gitlab-runner register -n
      • --url https://gitlab.example.com/
      • --registration-token seu-token
      • --executor docker
      • --description "docker-builder"
      • --docker-image "docker:latest"
      • --docker-privileged

      Output

      Registering runner... succeeded runner=61SR6BwV Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

      Certifique-se de substituir suas próprias informações. Nós definimos todas as opções do nosso runner na linha de comando em vez de usar os prompts interativos, porque os prompts não nos permitem especificar o modo --docker-privileged.

      Agora o seu runner está configurado, registrado e executando. Para verificar, volte ao seu navegador. Clique no ícone de chave inglesa na barra de menu principal do GitLab, em seguida clique em Runners no menu à esquerda. Seus runners serão listados:

      Agora que temos um runner capaz de criar imagens do Docker, vamos configurar um registro privado do Docker para carregar imagens para ele.

      Passo 2 — Configurando o Registro Docker do GitLab

      Configurar seu próprio registro do Docker permite que você envie e extraia imagens de seu próprio servidor privado, aumentando a segurança e reduzindo as dependências do seu fluxo de trabalho em serviços externos.

      O GitLab irá configurar um registro Docker privado com apenas algumas atualizações de configuração. Primeiro vamos configurar a URL onde o registro irá residir. Depois, iremos (opcionalmente) configurar o registro para usar um serviço de armazenamento de objetos compatível com S3 para armazenar seus dados.

      Faça SSH em seu servidor GitLab, depois abra o arquivo de configuração do GitLab:

      • sudo nano /etc/gitlab/gitlab.rb

      Role para baixo até a seção Container Registry settings. Vamos descomentar a linha registry_external_url e configurá-la para o nosso host GitLab com a porta número 5555:

      /etc/gitlab/gitlab.rb

      
      registry_external_url 'https://gitlab.example.com:5555'
      

      A seguir, adicione as duas linhas seguintes para dizer ao registro onde encontrar nossos certificados Let’s Encrypt:

      /etc/gitlab/gitlab.rb

      
      registry_nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem"
      registry_nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"
      

      Salve e feche o arquivo, depois reconfigure o GitLab:

      • sudo gitlab-ctl reconfigure

      Output

      . . . gitlab Reconfigured!

      Atualize o firewall para pemitir tráfego para a porta do registro:

      Agora mude para outra máquina com o Docker instalado e efetue o login no registro Docker privado. Se você não tiver o Docker no seu computador de desenvolvimento local, você pode usar qualquer servidor configurado para executar seus jobs do GitLab CI, já que ele tem o Docker instalado:

      • docker login gitlab.example.com:5555

      Você será solicitado para inserir o seu nome de usuário e senha. Use suas credenciais do GitLab para efetuar login.

      Output

      Login Succeeded

      Sucesso! O registro está configurado e funcionando. Atualmente, ele armazenará arquivos no sistema de arquivos local do servidor GitLab. Se você quiser usar um serviço de armazenamento de objetos, continue com esta seção. Se não, pule para o Passo 3.

      Para configurar um backend de armazenamento de objetos para o registro, precisamos saber as seguintes informações sobre o nosso serviço de armazenamento de objetos:

      • Access Key

      • Secret Key

      • Region (us-east-1) por exemplo, se estiver usando Amazon S3, ou Region Endpoint se estiver usando um serviço compatível com S3 (https://nyc.digitaloceanspaces.com)

      • Nome do Bucket

      Se você estiver usando o DigitalOcean Spaces, você pode descobrir como configurar um novo Space e obter as informações acima lendo Como Criar um Space e uma Chave de API na DigitalOcean.

      Quando você tiver suas informações sobre o amazenamento de objetos, abra o arquivo de configuração do GitLab:

      • sudo nano /etc/gitlab/gitlab.rb

      Novamente, role até a seção de registro do container. Procure pelo bloco registry['storage'], descomente o bloco e atualize-o para o seguinte, novamente certificando-se de substituir suas próprias informações, quando apropriado:

      /etc/gitlab/gitlab.rb

      
      registry['storage'] = {
        's3' => {
          'accesskey' => 'sua-key',
          'secretkey' => 'seu-secret',
          'bucket' => 'seu-bucket-name',
          'region' => 'nyc3',
          'regionendpoint' => 'https://nyc3.digitaloceanspaces.com'
        }
      }
      

      Se você estiver uando Amazon S3, você precisa apenas da region e não do regionendpoint. Se estiver usando um serviço S3 compatível, como o Spaces, você irá precisar do regionendpoint. Neste caso, region na verdade não configura nada e o valor que você digita não importa, mas ainda precisa estar presente e não em branco.

      Salve e feche o arquivo.

      Nota: Atualmente, há um bug em que o registro será encerrado após trinta segundos se seu bucket de armazenamento de objetos estiver vazio. Para evitar isso, coloque um arquivo no seu bucket antes de executar a próxima etapa. Você poderá removê-lo mais tarde, após o registro ter adicionado seus próprios objetos.

      Se você estiver usando o Spaces da DigitalOcean, você pode arrastar e soltar um arquivo para carregá-lo usando a interface do Painel de Controle.

      Reconfigure o GitLab mais uma vez:

      • sudo gitlab-ctl reconfigure

      Em sua outra máquina Docker, efetue login no registro novamente para ter certeza de que tudo está bem:

      • docker login gitlab.example.com:5555

      Você deve receber uma mensagem de Login Succeeded.

      Agora que temos nosso registro do Docker configurado, vamos atualizar a configuração de CI da nossa aplicação para criar e testar nossa app, e enviar as imagens Docker para o nosso registro privado.

      Passo 3 — Atualizando o gitlab-ci.yaml e Construindo uma Imagem Docker

      Nota: Se você não concluiu o artigo de pré-requisito do GitLab CI você precisará copiar o repositório de exemplo para o seu servidor GitLab. Siga a seção Copying the Example Repository From GitHub para fazer isto.

      Para que possamos fazer o building de nossa app no Docker, precisamos atualizar o arquivo .gitlab-ci.yml. Você pode editar este arquivo diretamente no GitLab clicando na página principal do projeto, e depois no botão Edit. Alternativamente, você poderia clonar o repositório para a sua máquina local, editar o arquivo, e então fazer um git push nele de volta para o GitLab. Isso ficaria assim:

      • git clone git@gitlab.example.com:sammy/hello_hapi.git
      • cd hello_hapi
      • # edit the file w/ your favorite editor
      • git commit -am "updating ci configuration"
      • git push

      Primeiro, exclua tudo no arquivo, depois cole nele a seguinte configuração:

      .gitlab-ci.yml

      
      image: docker:latest
      services:
      - docker:dind
      
      stages:
      - build
      - test
      - release
      
      variables:
        TEST_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:$CI_COMMIT_REF_NAME
        RELEASE_IMAGE: gitlab.example.com:5555/sammy/hello_hapi:latest
      
      before_script:
        - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN gitlab.example.com:5555
      
      build:
        stage: build
        script:
          - docker build --pull -t $TEST_IMAGE .
          - docker push $TEST_IMAGE
      
      test:
        stage: test
        script:
          - docker pull $TEST_IMAGE
          - docker run $TEST_IMAGE npm test
      
      release:
        stage: release
        script:
          - docker pull $TEST_IMAGE
          - docker tag $TEST_IMAGE $RELEASE_IMAGE
          - docker push $RELEASE_IMAGE
        only:
          - master
      

      Certifique-se de atualizar os URLs e nomes de usuários realçados com suas próprias informações e, em seguida, salve com o botão Commit changes no GitLab. Se você está atualizando o arquivo fora do GitLab, confirme as mudanças e faça git push de volta no GitLab.

      Este novo arquivo de configuração diz ao GitLab para usar a imagem mais recente do docker (image: docker:latest) e vinculá-la ao serviço docker-in-docker (docker:dind). Então, ele define os estágios de build, test, e release. O estágio de build cria a imagem do Docker usando o Dockerfile fornecido pelo repositório, em seguida o carrega para o nosso registro de imagens Docker. Se isso for bem sucedido, o estágio test vai baixar a imagem que acabamos de construir e executar o comando npm test dentro dele. Se o estágio test for bem sucedido, o estágio release irá lançar a imagem, irá colocar uma tag como hello_hapi:latest e irá retorná-la ao registro.

      Dependendo do seu fluxo de trabalho, você também pode adicionar mais estágios test, ou mesmo estágios deploy que levam o aplicativo para um ambiente de preparação ou produção.

      A atualização do arquivo de configuração deve ter acionado um novo build. Volte ao projeto hello_hapi no GitLab e clique no indicador de status do CI para o commit:

      Na página resultante, você pode clicar em qualquer um dos estágios para ver seu progresso:

      Eventualmente, todas as etapas devem indicar que eles foram bem sucedidos, mostrando ícones com a marca de verificação em verde. Podemos encontrar as imagens Docker que acabaram de ser construídas clicando no item Registry no menu à esquerda:

      Se você clicar no pequeno ícone "document" ao lado do nome da imagem, ele copiará o comando apropriado docker pull ... para a sua área de transferência. Você pode então baixar e executar sua imagem:

      • docker pull gitlab.example.com:5555/sammy/hello_hapi:latest
      • docker run -it --rm -p 3000:3000 gitlab.example.com:5555/sammy/hello_hapi:latest

      Output

      > hello@1.0.0 start /usr/src/app > node app.js Server running at: http://56fd5df5ddd3:3000

      A imagem foi baixada do registro e iniciada em um container. Mude para o seu navegador e conecte-se ao aplicativo na porta 3000 para testar. Neste caso, estamos executando o container em nossa máquina local, assim podemos acessá-la via localhost na seguinte URL:

      http://localhost:3000/hello/test
      

      Output

      Hello, test!

      Sucesso! Você pode parar o container com CTRL-C. A partir de agora, toda vez que enviarmos um novo código para a ramificação master do nosso repositório, vamos construir e testar automaticamente uma nova imagem hello_hapi: latest.

      Conclusão

      Neste tutorial, configuramos um novo GitLab runner para criar imagens do Docker, criamos um regisro privado do Docker para armazená-las, e atualizamos um app Node.js para ser construído e testado dentro de containers Docker.

      Para aprender mais sobre os vários componentes utilizados nesta configuração, você pode ler a documentação oficial do GitLab CE, GitLab Container Registry, e do Docker.

      Por Brian Boucheron



      Source link