{"id":32526,"date":"2019-10-31T21:47:32","date_gmt":"2019-10-31T18:47:32","guid":{"rendered":"https:\/\/prohoster.info\/blog\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\/"},"modified":"2019-10-31T21:47:32","modified_gmt":"2019-10-31T18:47:32","slug":"protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","title":{"rendered":"Processo de Desenvolvimento e Teste com Docker e Gitlab CI","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Convido a conhecer a transcri\u00e7\u00e3o do relat\u00f3rio de Alexander Sigachev da Inventos \"Processo de desenvolvimento e teste com Docker + Gitlab CI\"<\/strong><\/p>\n<p><\/p>\n<p>Aqueles que est\u00e3o apenas come\u00e7ando a implementar o processo de desenvolvimento e teste baseado em Docker + Gitlab CI costumam fazer perguntas b\u00e1sicas. Por onde come\u00e7ar? Como organizar? Como testar?<\/p>\n<p><\/p>\n<p>Esta apresenta\u00e7\u00e3o \u00e9 boa porque explica de maneira estruturada o processo de desenvolvimento e teste utilizando Docker e Gitlab CI. A pr\u00f3pria apresenta\u00e7\u00e3o \u00e9 de 2017. Acredito que dela podemos extrair fundamentos, metodologias, ideias e experi\u00eancias de uso. <\/p>\n<p>\n<center><div class=\"youtube-placeholder\" data-id=\"lJsqRwULRVA\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/lJsqRwULRVA\/hqdefault.jpg\" alt=\"Por que no hosting comum a administra\u00e7\u00e3o do PrestaShop \u00e9 lenta, e no seu n\u00e3o \u00e9?\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<p>Para quem est\u00e1 interessado, convido a continuar lendo. <noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><\/p>\n<p>Meu nome \u00e9 Alexander Sigachev. Trabalho na empresa Inventos. Vou compartilhar minha experi\u00eancia com o Docker e como estamos progressivamente implementando em nossos projetos.<\/p>\n<p><\/p>\n<p>Tema da apresenta\u00e7\u00e3o: O Processo de Desenvolvimento com Docker e Gitlab CI. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e30c4757e4bda1bcc3e20b16e8e2709e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esta \u00e9 a minha segunda apresenta\u00e7\u00e3o sobre Docker. Na \u00e9poca da primeira apresenta\u00e7\u00e3o, us\u00e1vamos Docker apenas em Development nas m\u00e1quinas dos desenvolvedores. O n\u00famero de funcion\u00e1rios que utilizavam Docker era de cerca de 2-3 pessoas. Gradualmente, acumulamos experi\u00eancia e avan\u00e7amos um pouco mais. Link para nossa <noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/gled\/docker-development-70411088\">primeira apresenta\u00e7\u00e3o<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>O que ser\u00e1 abordado nesta apresenta\u00e7\u00e3o? Vamos compartilhar nossa experi\u00eancia sobre os desafios que encontramos e como resolvemos cada problema. Nem tudo foi perfeito, mas nos permitiu avan\u00e7ar.<\/p>\n<p><\/p>\n<p>Nosso lema: dockerize tudo que nossas m\u00e3os alcan\u00e7am.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25ae4f97f1c502384abfe697bac502b1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quais problemas estamos resolvendo?<\/p>\n<p><\/p>\n<p>Quando h\u00e1 v\u00e1rias equipes na empresa, o programador se torna um recurso compartilhado. Existem momentos em que o programador \u00e9 retirado de um projeto e alocado temporariamente em outro.<\/p>\n<p><\/p>\n<p>Para que o programador consiga se adaptar rapidamente, \u00e9 necess\u00e1rio que ele fa\u00e7a o download do c\u00f3digo-fonte do projeto e inicie o ambiente o mais r\u00e1pido poss\u00edvel, o que permitir\u00e1 que ele siga avan\u00e7ando nas tarefas daquele projeto.<\/p>\n<p><\/p>\n<p>Em geral, se come\u00e7armos do zero, a documenta\u00e7\u00e3o do projeto \u00e9 escassa. As informa\u00e7\u00f5es sobre como configurar est\u00e3o dispon\u00edveis apenas para os veteranos. Os funcion\u00e1rios configuram seu ambiente de trabalho em um ou dois dias. Para acelerar isso, utilizamos o Docker.<\/p>\n<p><\/p>\n<p>A pr\u00f3xima raz\u00e3o \u00e9 a padroniza\u00e7\u00e3o das configura\u00e7\u00f5es em Desenvolvimento. Pela minha experi\u00eancia, os desenvolvedores sempre tomam a iniciativa. Em um caso a cada cinco, um dom\u00ednio personalizado \u00e9 introduzido, como vasya.dev. Ao lado, est\u00e1 o vizinho Petya, que tem o dom\u00ednio petya.dev. Eles est\u00e3o desenvolvendo um site ou algum componente do sistema, usando esse nome de dom\u00ednio.<\/p>\n<p><\/p>\n<p>Quando o sistema se expande e esses nomes de dom\u00ednio come\u00e7am a aparecer nas configura\u00e7\u00f5es, ocorre um conflito nos ambientes de Desenvolvimento e o caminho do site \u00e9 reescrito.<\/p>\n<p><\/p>\n<p>A mesma coisa acontece com as configura\u00e7\u00f5es do banco de dados. Algu\u00e9m n\u00e3o se preocupa com a seguran\u00e7a e trabalha com a senha root vazia. Em outro caso, durante a instala\u00e7\u00e3o, o MySQL pediu uma senha e a senha era apenas 123. Muitas vezes ocorre que as configura\u00e7\u00f5es do banco de dados mudam constantemente, dependendo do commit do desenvolvedor. Algu\u00e9m corrigiu, algu\u00e9m n\u00e3o corrigiu a configura\u00e7\u00e3o. Havia estrat\u00e9gias em que n\u00f3s externaliz\u00e1vamos alguma configura\u00e7\u00e3o de teste para <code>.gitignore<\/code> e cada desenvolvedor tinha que instalar o banco de dados. Isso complicava o processo de in\u00edcio. Al\u00e9m de tudo, \u00e9 preciso lembrar do banco de dados. O banco de dados precisa ser inicializado, \u00e9 necess\u00e1rio definir a senha, definir o usu\u00e1rio, criar a tabela e assim por diante.<\/p>\n<p><\/p>\n<p>Outro problema \u00e9 as diferentes vers\u00f5es das bibliotecas. Muitas vezes, o desenvolvedor trabalha em diferentes projetos. H\u00e1 um projeto legado que come\u00e7ou h\u00e1 cinco anos (a partir de 2017 - nota do editor). No in\u00edcio, come\u00e7ou-se com o MySQL 5.5. Existem tamb\u00e9m projetos modernos, onde tentamos implementar vers\u00f5es mais recentes do MySQL, como 5.7 ou superiores (em 2017 - nota do editor).<\/p>\n<p><\/p>\n<p>Quem trabalha com MySQL sabe que essas bibliotecas trazem depend\u00eancias. \u00c9 bastante problem\u00e1tico executar 2 bancos de dados juntos. Pelo menos, \u00e9 problem\u00e1tico conectar clientes antigos a um novo banco de dados. Isso, por sua vez, gera v\u00e1rios problemas.<\/p>\n<p><\/p>\n<p>O pr\u00f3ximo problema \u00e9 quando o desenvolvedor trabalha em uma m\u00e1quina local, ele usa recursos locais, arquivos locais, e RAM local. Toda a intera\u00e7\u00e3o durante o desenvolvimento das solu\u00e7\u00f5es ocorre no que funciona em uma \u00fanica m\u00e1quina. Um exemplo disso \u00e9 quando temos 3 servidores backend em produ\u00e7\u00e3o, e o desenvolvedor salva arquivos no diret\u00f3rio raiz, de onde o nginx pega os arquivos para responder \u00e0s solicita\u00e7\u00f5es. Quando esse c\u00f3digo vai para produ\u00e7\u00e3o, percebe-se que o arquivo est\u00e1 presente em um dos 3 servidores.<\/p>\n<p><\/p>\n<p>Atualmente, est\u00e1 em ascens\u00e3o a abordagem de microsservi\u00e7os. Quando dividimos nossas grandes aplica\u00e7\u00f5es em pequenos componentes que interagem entre si. Isso permite escolher tecnologias espec\u00edficas para o conjunto de tarefas requerido. Tamb\u00e9m permite dividir o trabalho e a \u00e1rea de responsabilidade entre os desenvolvedores.<\/p>\n<p><\/p>\n<p>O desenvolvedor frontend, ao trabalhar com JS, praticamente n\u00e3o influencia o backend. O desenvolvedor backend, por sua vez, desenvolve, neste caso, em Ruby on Rails e n\u00e3o interfere no frontend. A intera\u00e7\u00e3o ocorre atrav\u00e9s de APIs.<\/p>\n<p><\/p>\n<p>Como b\u00f4nus, com o Docker conseguimos otimizar os recursos no staging. Cada projeto, devido \u00e0 sua especificidade, requer configura\u00e7\u00f5es espec\u00edficas. Precisava-se fisicamente alocar um servidor virtual para cada um e configur\u00e1-los separadamente, ou ent\u00e3o dividir algum ambiente vari\u00e1vel, onde os projetos poderiam, dependendo da vers\u00e3o das bibliotecas, influenciar uns aos outros.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/fa5c99f90faef84a356d4791fd915830.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ferramentas. O que estamos usando? <\/p>\n<p><\/p>\n<ul>\n<li>Diretamente o Docker em si. No Dockerfile, s\u00e3o descritas as depend\u00eancias de uma aplica\u00e7\u00e3o. <\/li>\n<li>O Docker-compose \u00e9 a conex\u00e3o que re\u00fane nossos v\u00e1rios aplicativos Docker.<\/li>\n<li>Usamos o GitLab para armazenar o c\u00f3digo fonte.<\/li>\n<li>Usamos o GitLab-CI para integra\u00e7\u00e3o cont\u00ednua.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/b6041827a6ba928e0d33add6b79c581c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A apresenta\u00e7\u00e3o consiste em duas partes.<\/p>\n<p><\/p>\n<p>A primeira parte abordar\u00e1 como iniciamos o Docker nas m\u00e1quinas dos desenvolvedores.<\/p>\n<p><\/p>\n<p>A segunda parte discutir\u00e1 como interagir com o GitLab, como executamos os testes e como fazemos o deploy no Staging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/45746d3323d35e0d18f066c8bfcb2214.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O Docker \u00e9 uma tecnologia que permite (usando uma abordagem declarativa) descrever os componentes necess\u00e1rios. Este \u00e9 um exemplo de Dockerfile. Aqui declaramos que estamos herdando da imagem oficial do Docker Ruby:2.3.0. Isso cont\u00e9m o Ruby vers\u00e3o 2.3 instalado. Instalamos as bibliotecas necess\u00e1rias para compila\u00e7\u00e3o e o NodeJS. Descrevemos que estamos criando um diret\u00f3rio. <code>\/app<\/code>Designamos o diret\u00f3rio app como o diret\u00f3rio de trabalho. Neste diret\u00f3rio, colocamos o necess\u00e1rio Gemfile e Gemfile.lock. Em seguida, realizamos a constru\u00e7\u00e3o dos projetos que instalam essa imagem de depend\u00eancias. Especificamos que o cont\u00eainer estar\u00e1 pronto para ouvir na porta externa 3000. O \u00faltimo comando \u00e9 aquele que executa diretamente o nosso aplicativo. Se executarmos o comando de inicializa\u00e7\u00e3o do projeto, o aplicativo tentar\u00e1 ser executado e lan\u00e7ar\u00e1 o comando especificado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ba503c305ae90f49b39f4ae2cbda1668.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este \u00e9 um exemplo m\u00ednimo de um arquivo docker-compose. Neste caso, mostramos a comunica\u00e7\u00e3o entre dois cont\u00eaineres. Isto se refere diretamente ao servi\u00e7o do banco de dados e ao servi\u00e7o web. Nossos aplicativos web, na maioria das vezes, requerem um banco de dados como backend para armazenamento de dados. Como estamos utilizando o MySQL, o exemplo com MySQL \u00e9 adequado, mas nada impede o uso de outro banco de dados (PostgreSQL, Redis).<\/p>\n<p><\/p>\n<p>Estamos pegando uma imagem do MySQL 5.7.14 do Docker Hub sem altera\u00e7\u00f5es. A imagem que cont\u00e9m nosso aplicativo web \u00e9 constru\u00edda a partir do diret\u00f3rio atual. Durante a primeira execu\u00e7\u00e3o, ela cria a imagem para n\u00f3s. Ap\u00f3s isso, executa o comando que estamos realizando aqui. Se voltarmos um pouco, veremos que foi definida uma command de inicializa\u00e7\u00e3o atrav\u00e9s do Puma. Puma \u00e9 um servi\u00e7o escrito em Ruby. No segundo caso, estamos redefinindo. Este comando pode ser arbitr\u00e1rio, dependendo de nossas necessidades ou tarefas.<\/p>\n<p><\/p>\n<p>Tamb\u00e9m descrevemos que precisamos redirecionar a porta na m\u00e1quina host do desenvolvedor da porta 3000 para a porta 3000 do cont\u00eainer. Isso \u00e9 realizado automaticamente por meio do iptables e do seu mecanismo que est\u00e1 diretamente embutido no Docker. <\/p>\n<p><\/p>\n<p>O desenvolvedor pode tamb\u00e9m, como antes, acessar qualquer endere\u00e7o IP dispon\u00edvel, por exemplo, 127.0.0.1 local ou o endere\u00e7o IP externo da m\u00e1quina.<\/p>\n<p><\/p>\n<p>A \u00faltima linha indica que o cont\u00eainer web depende do cont\u00eainer db. Quando solicitamos a inicializa\u00e7\u00e3o do cont\u00eainer web, o docker-compose iniciar\u00e1 o banco de dados primeiro. Ap\u00f3s a inicializa\u00e7\u00e3o do banco de dados (na verdade \u2014 ap\u00f3s a inicializa\u00e7\u00e3o do cont\u00eainer! A prontid\u00e3o do BD n\u00e3o \u00e9 garantida), o aplicativo, nosso backend, ser\u00e1 iniciado.<\/p>\n<p><\/p>\n<p>Isso evita erros quando o banco de dados n\u00e3o est\u00e1 ativo e ajuda a economizar recursos quando paramos o cont\u00eainer de banco de dados, liberando assim recursos para outros projetos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4acbcf5de89b98db055e8abc419202de.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O que a utiliza\u00e7\u00e3o da dockeriza\u00e7\u00e3o de banco de dados nos proporciona no projeto. Registramos a vers\u00e3o do MySQL para todos os desenvolvedores. Isso ajuda a evitar alguns erros que podem ocorrer devido a discrep\u00e2ncias de vers\u00f5es, quando o syntaxe, configura\u00e7\u00e3o e as defini\u00e7\u00f5es padr\u00e3o mudam. Isso permite especificar nomes de host comuns para o banco de dados, login e senha. Estamos nos afastando do caos de nomes e conflitos em arquivos de configura\u00e7\u00e3o que t\u00ednhamos anteriormente. <\/p>\n<p><\/p>\n<p>Temos a possibilidade de usar uma configura\u00e7\u00e3o mais otimizada para o ambiente de Desenvolvimento, que ser\u00e1 diferente da configura\u00e7\u00e3o padr\u00e3o. O MySQL, por padr\u00e3o, \u00e9 configurado para m\u00e1quinas fracas e sua performance de prateleira \u00e9 muito baixa.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/417d77a06b18e2df9b71440c0f2a1653.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O Docker permite usar o interpretador Python, Ruby, NodeJS, PHP na vers\u00e3o necess\u00e1ria. Nos livramos da necessidade de usar um gerenciador de vers\u00f5es. Anteriormente, para o Ruby, us\u00e1vamos um pacote rpm que permitia mudar de vers\u00e3o conforme o projeto. Al\u00e9m disso, isso permite que, gra\u00e7as ao cont\u00eainer Docker, migremos o c\u00f3digo suavemente e o versionemos junto com suas depend\u00eancias. N\u00e3o temos problemas em entender a vers\u00e3o tanto do interpretador quanto do c\u00f3digo. Para atualizar a vers\u00e3o, \u00e9 necess\u00e1rio parar o cont\u00eainer antigo e iniciar um novo. Se algo der errado, podemos derrubar o novo cont\u00eainer e levantar o cont\u00eainer antigo.<\/p>\n<p><\/p>\n<p>Ap\u00f3s a constru\u00e7\u00e3o da imagem, os cont\u00eaineres ser\u00e3o id\u00eanticos tanto em Desenvolvimento quanto em Produ\u00e7\u00e3o. Isso \u00e9 especialmente relevante para grandes instala\u00e7\u00f5es.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/185a1bfe257f7e3e0eecdc6e0e0d330f.jpg\" style=\"display:block;margin: 0 auto;\" \/> No Frontend, utilizamos JavaScript e NodeJS.<\/p>\n<p><\/p>\n<p>Atualmente, nosso \u00faltimo projeto est\u00e1 em ReactJS. O desenvolvedor iniciou todos os cont\u00eaineres e estava desenvolvendo usando hot-reload.<\/p>\n<p><\/p>\n<p>Em seguida, uma tarefa de constru\u00e7\u00e3o de JavaScript \u00e9 iniciada e o c\u00f3digo, compilado em est\u00e1tica, \u00e9 entregue atrav\u00e9s do nginx, economizando recursos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4c2e28319d56d7fc81845b4133a1bfe6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aqui est\u00e1 o esquema do nosso \u00faltimo projeto.<\/p>\n<p><\/p>\n<p>Quais problemas enfrentamos? Tivemos a necessidade de construir um sistema que interage com dispositivos m\u00f3veis. Eles recebem dados. Uma das funcionalidades \u00e9 enviar notifica\u00e7\u00f5es push para esses dispositivos. <\/p>\n<p><\/p>\n<p>O que fizemos para isso?<\/p>\n<p><\/p>\n<p>Dividimos o aplicativo em componentes como: a parte administrativa em JS, o backend, que opera atrav\u00e9s de uma interface REST sob Ruby on Rails. O backend interage com o banco de dados. O resultado gerado \u00e9 entregue ao cliente. A parte administrativa se comunica com o backend e o banco de dados via interface REST.<\/p>\n<p><\/p>\n<p>Tamb\u00e9m tivemos a necessidade de enviar notifica\u00e7\u00f5es Push. Antes disso, tivemos um projeto em que foi implementado um mecanismo respons\u00e1vel pela entrega de notifica\u00e7\u00f5es em plataformas m\u00f3veis. <\/p>\n<p><\/p>\n<p>Desenvolvemos um esquema onde o operador interage com a interface administrativa pelo navegador, e a interface administrativa interage com o backend, estabelecendo a tarefa de enviar notifica\u00e7\u00f5es Push.<\/p>\n<p><\/p>\n<p>As notifica\u00e7\u00f5es Push interagem com outro componente que foi implementado em NodeJS.<\/p>\n<p><\/p>\n<p>Filas s\u00e3o constru\u00eddas e, em seguida, o envio das notifica\u00e7\u00f5es ocorre por seu pr\u00f3prio mecanismo.<\/p>\n<p><\/p>\n<p>Aqui est\u00e3o representados dois bancos de dados. No momento, estamos utilizando 2 bancos de dados independentes com a ajuda do Docker, que n\u00e3o est\u00e3o relacionados entre si. O \u00fanico ponto em comum \u00e9 que fazem parte de uma rede virtual compartilhada, enquanto os dados f\u00edsicos est\u00e3o armazenados em diret\u00f3rios diferentes na m\u00e1quina do desenvolvedor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/dfde59db7e6886d2d851dcf884049318.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O mesmo, mas em n\u00fameros. Aqui, a reutiliza\u00e7\u00e3o de c\u00f3digo \u00e9 importante.<\/p>\n<p><\/p>\n<p>Se anteriormente falamos sobre reutiliza\u00e7\u00e3o de c\u00f3digo na forma de bibliotecas, neste exemplo nosso servi\u00e7o respons\u00e1vel pelas notifica\u00e7\u00f5es Push \u00e9 reutilizado como um servidor completo. Ele fornece uma API, com a qual nossa nova aplica\u00e7\u00e3o interage.<\/p>\n<p><\/p>\n<p>Naquela \u00e9poca est\u00e1vamos utilizando a vers\u00e3o 4 do NodeJS. Atualmente (em 2017 \u2014 nota do editor), em novos desenvolvimentos, utilizamos a vers\u00e3o 7 do NodeJS. N\u00e3o h\u00e1 problemas em novas componentes incorporarem novas vers\u00f5es de bibliotecas. <\/p>\n<p><\/p>\n<p>Se necess\u00e1rio, podemos realizar um refatoramento e atualizar a vers\u00e3o do NodeJS no servi\u00e7o de notifica\u00e7\u00f5es Push. <\/p>\n<p><\/p>\n<p>Se conseguirmos manter a compatibilidade da API, poderemos substitu\u00ed-lo em outros projetos utilizados anteriormente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5c58c65be078a5a1b9fc17ee2e7b4ad4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O que \u00e9 necess\u00e1rio para adicionar o Docker? Adicionamos um Dockerfile ao nosso reposit\u00f3rio, que descreve as depend\u00eancias necess\u00e1rias. Neste exemplo, os componentes est\u00e3o divididos logicamente. Este \u00e9 o conjunto m\u00ednimo para um desenvolvedor backend.<\/p>\n<p><\/p>\n<p>Ao criar um novo projeto, criamos um Dockerfile, descrevendo o ecossistema necess\u00e1rio (Python, Ruby, NodeJS). O docker-compose descreve as depend\u00eancias necess\u00e1rias \u2014 o banco de dados. Especificamos que precisamos de um banco de dados de tal vers\u00e3o, para armazenar dados em determinados locais.<\/p>\n<p><\/p>\n<p>Utilizamos um terceiro cont\u00eainer separado com nginx para servir os arquivos est\u00e1ticos. A possibilidade de carregar imagens est\u00e1 garantida. O backend as coloca em um volume preparado antecipadamente, que tamb\u00e9m est\u00e1 montado no cont\u00eainer com nginx, que serve os arquivos est\u00e1ticos.<\/p>\n<p><\/p>\n<p>Para armazenar a configura\u00e7\u00e3o do nginx e do mysql, adicionamos uma pasta Docker, onde guardamos as configura\u00e7\u00f5es necess\u00e1rias. Quando um desenvolvedor faz um git clone do reposit\u00f3rio em sua m\u00e1quina, ele j\u00e1 tem um projeto pronto para o desenvolvimento local. N\u00e3o h\u00e1 d\u00favidas sobre qual porta ou quais configura\u00e7\u00f5es aplicar.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/e7a6b308a75cacf8ce60687a9e6081dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Em seguida, temos alguns componentes: admin, inform-API, notifica\u00e7\u00f5es push.<\/p>\n<p><\/p>\n<p>Para executar tudo isso, criamos outro reposit\u00f3rio que chamamos de dockerized-app. Atualmente, usamos v\u00e1rios reposit\u00f3rios para cada componente. Eles diferem apenas logicamente \u2014 no GitLab, isso aparece como uma pasta, e na m\u00e1quina do desenvolvedor, como uma pasta para um projeto espec\u00edfico. Abaixo est\u00e3o os componentes que ser\u00e3o integrados.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f4e2c45c8ec20fca0bac74b3a3892543.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este \u00e9 um exemplo do conte\u00fado do dockerized-app. N\u00f3s tamb\u00e9m destacamos aqui o diret\u00f3rio Docker, onde organizamos as configura\u00e7\u00f5es necess\u00e1rias para a intera\u00e7\u00e3o de todos os componentes. H\u00e1 um README.md que descreve brevemente como iniciar o projeto.<\/p>\n<p><\/p>\n<p>Aqui aplicamos dois arquivos docker-compose. Isso foi feito para permitir o lan\u00e7amento em etapas. Quando um desenvolvedor est\u00e1 trabalhando com o n\u00facleo e n\u00e3o precisa de notifica\u00e7\u00f5es push, ele simplesmente inicia o arquivo docker-compose, economizando assim recursos.<\/p>\n<p><\/p>\n<p>Se houver necessidade de integra\u00e7\u00e3o com notifica\u00e7\u00f5es push, s\u00e3o iniciados o docker-compose.yaml e o docker-compose-push.yaml.<\/p>\n<p><\/p>\n<p>Como o docker-compose.yaml e o docker-compose-push.yaml est\u00e3o na mesma pasta, \u00e9 criada automaticamente uma rede virtual unificada.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/535019c82c72c1602176fbaf4aa5640f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Descri\u00e7\u00e3o dos componentes. Este \u00e9 um arquivo mais detalhado que gerencia a coleta de componentes. O que \u00e9 not\u00e1vel aqui? Introduzimos o componente balanceador.<\/p>\n<p><\/p>\n<p>Este \u00e9 um Docker image pronto, onde o nginx e o aplicativo que escuta o socket do Docker s\u00e3o lan\u00e7ados. Ele regenera dinamicamente a configura\u00e7\u00e3o do nginx \u00e0 medida que os cont\u00eaineres s\u00e3o iniciados e desligados. A intera\u00e7\u00e3o com os componentes \u00e9 distribu\u00edda atrav\u00e9s de nomes de dom\u00ednio de terceiro n\u00edvel.<\/p>\n<p><\/p>\n<p>Para o ambiente de Desenvolvimento, usamos o dom\u00ednio .dev \u2014 api.informer.dev. Aplica\u00e7\u00f5es com o dom\u00ednio .dev est\u00e3o dispon\u00edveis na m\u00e1quina local do desenvolvedor.<\/p>\n<p><\/p>\n<p>Em seguida, as configura\u00e7\u00f5es s\u00e3o passadas para cada projeto e todos os projetos s\u00e3o iniciados simultaneamente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/bc1e11e6f1fd1c837d2c8087d04145c4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se representarmos graficamente, o cliente \u00e9 nosso navegador ou algum instrumento com o qual realizamos solicita\u00e7\u00f5es ao balanceador.<\/p>\n<p><\/p>\n<p>O balanceador determina, pelo nome do dom\u00ednio, a qual cont\u00eainer deve ser feita a solicita\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Isso pode ser o nginx, que fornece o JS do painel administrativo. Pode ser o nginx que fornece a API ou arquivos est\u00e1ticos que s\u00e3o entregues pelo nginx na forma de upload de imagens.<\/p>\n<p><\/p>\n<p>O diagrama mostra que os cont\u00eaineres est\u00e3o conectados a uma rede virtual e escondidos atr\u00e1s de um proxy.<\/p>\n<p><\/p>\n<p>Na m\u00e1quina do desenvolvedor, \u00e9 poss\u00edvel acessar o cont\u00eainer conhecendo o IP, mas, em princ\u00edpio, n\u00e3o fazemos isso. Praticamente n\u00e3o h\u00e1 necessidade de acesso direto.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/2908c31fd9d3c79f6189bdbeeb6d028f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Qual exemplo olhar para dockerizar sua aplica\u00e7\u00e3o? Na minha opini\u00e3o, um bom exemplo \u00e9 a imagem oficial do docker para MySQL.<\/p>\n<p><\/p>\n<p>\u00c9 bastante complicado. Existem muitas vers\u00f5es. Mas sua funcionalidade atende a v\u00e1rias necessidades que podem surgir no decorrer do desenvolvimento. Se voc\u00ea dedicar tempo para entender como tudo isso interage, n\u00e3o deve ter problemas ao implement\u00e1-lo de forma aut\u00f4noma.<\/p>\n<p><\/p>\n<p>No hub.docker.com, geralmente h\u00e1 links para github.com, onde est\u00e3o os dados brutos a partir dos quais voc\u00ea pode construir a imagem por conta pr\u00f3pria.<\/p>\n<p><\/p>\n<p>Al\u00e9m disso, este reposit\u00f3rio cont\u00e9m o script docker-endpoint.sh, que \u00e9 respons\u00e1vel pela inicializa\u00e7\u00e3o prim\u00e1ria e pelo processamento subsequente do lan\u00e7amento da aplica\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Este exemplo tamb\u00e9m oferece a possibilidade de configura\u00e7\u00e3o por meio de vari\u00e1veis de ambiente. Ao definir a vari\u00e1vel de ambiente ao iniciar um cont\u00eainer \u00fanico ou atrav\u00e9s do docker-compose, podemos especificar que precisamos configurar uma senha vazia para o docker para o root no MySQL ou alguma outra que desejamos.<\/p>\n<p><\/p>\n<p>H\u00e1 a op\u00e7\u00e3o de criar uma senha aleat\u00f3ria. Dizemos que precisamos de um usu\u00e1rio, que precisamos definir uma senha para o usu\u00e1rio e que precisamos criar um banco de dados.<\/p>\n<p><\/p>\n<p>Em nossos projetos, unificamos um pouco o Dockerfile, que \u00e9 respons\u00e1vel pela inicializa\u00e7\u00e3o. N\u00f3s o ajustamos para atender \u00e0s nossas necessidades, ampliando os direitos do usu\u00e1rio que a aplica\u00e7\u00e3o utiliza. Isso permitiu criar um banco de dados a partir do console da aplica\u00e7\u00e3o. Em aplica\u00e7\u00f5es Ruby, h\u00e1 comandos para criar, modificar e eliminar bancos de dados.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4a9b56e21819d28dd39753134d23fee4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este \u00e9 um exemplo de como uma vers\u00e3o espec\u00edfica do MySQL aparece no github.com. O Dockerfile pode ser aberto para ver como a instala\u00e7\u00e3o ocorre.<\/p>\n<p><\/p>\n<p>O script docker-endpoint.sh \u00e9 respons\u00e1vel pelo ponto de entrada. Durante a inicializa\u00e7\u00e3o inicial, algumas a\u00e7\u00f5es de prepara\u00e7\u00e3o s\u00e3o necess\u00e1rias e todas essas a\u00e7\u00f5es est\u00e3o descritas no script de inicializa\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/4153fa46526f3d802931dd1db48b08cd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vamos para a segunda parte.<\/p>\n<p><\/p>\n<p>Para armazenar os c\u00f3digos fonte, mudamos para o gitlab. \u00c9 um sistema poderoso que possui uma interface visual.<\/p>\n<p><\/p>\n<p>Um dos componentes do Gitlab \u00e9 o Gitlab CI. Ele permite descrever a sequ\u00eancia de comandos que ser\u00e3o usados para organizar a entrega de c\u00f3digo ou para a execu\u00e7\u00e3o de testes automatizados.<\/p>\n<p><\/p>\n<p>Apresenta\u00e7\u00e3o sobre Gitlab CI 2 <noindex><a rel=\"nofollow\" href=\"https:\/\/goo.gl\/uohKjI\">https:\/\/goo.gl\/uohKjI<\/a><\/noindex> \u2014 apresenta\u00e7\u00e3o do Ruby Russia club \u2014 \u00e9 bastante detalhada e pode interess\u00e1-lo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/5d26d20500f34eeb9768e6c3d91bbefa.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Agora, vamos ver o que \u00e9 necess\u00e1rio para ativar o Gitlab CI. Para iniciar o Gitlab CI, precisamos simplesmente colocar o arquivo .gitlab-ci.yml na raiz do projeto.<\/p>\n<p><\/p>\n<p>Aqui descrevemos o que queremos executar em uma sequ\u00eancia de estados do tipo teste, implanta\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Executamos scripts que chamam diretamente a constru\u00e7\u00e3o do nosso aplicativo com docker-compose. Este \u00e9 um exemplo do backend.<\/p>\n<p><\/p>\n<p>Em seguida, dizemos que \u00e9 necess\u00e1rio executar as migra\u00e7\u00f5es para a altera\u00e7\u00e3o do banco de dados e executar os testes.<\/p>\n<p><\/p>\n<p>Se os scripts forem executados corretamente e n\u00e3o retornarem c\u00f3digos de erro, o sistema passar\u00e1 \u00e0 segunda fase da implanta\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>A fase de implanta\u00e7\u00e3o, neste momento, \u00e9 implementada para staging. N\u00e3o organizamos uma reinicializa\u00e7\u00e3o sem interrup\u00e7\u00f5es.<\/p>\n<p><\/p>\n<p>For\u00e7amos a parada de todos os cont\u00eaineres e depois levantamos todos os cont\u00eaineres novamente, constru\u00eddos na primeira etapa durante os testes.<\/p>\n<p><\/p>\n<p>Executamos novamente as migra\u00e7\u00f5es do banco de dados para o ambiente vari\u00e1vel atual que foram escritas pelos desenvolvedores.<\/p>\n<p><\/p>\n<p>H\u00e1 uma nota de que isso deve ser aplicado apenas para a branch master.<\/p>\n<p><\/p>\n<p>Quando outras branches s\u00e3o alteradas, n\u00e3o ser\u00e3o executadas.<\/p>\n<p><\/p>\n<p>H\u00e1 uma possibilidade de organizar vers\u00f5es por branches.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/8a5b880bd9a0d4bab0b276568e2ba413.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Para organizar isso, precisamos instalar o Gitlab Runner.<\/p>\n<p><\/p>\n<p>Esta ferramenta \u00e9 escrita em Golang. \u00c9 um \u00fanico arquivo, como \u00e9 comum no mundo Golang, e n\u00e3o requer depend\u00eancias.<\/p>\n<p><\/p>\n<p>Ao iniciar, registramos o Gitlab Runner.<\/p>\n<p><\/p>\n<p>Obtivemos a chave no web interface do Gitlab.<\/p>\n<p><\/p>\n<p>Ent\u00e3o chamamos o comando de inicializa\u00e7\u00e3o no terminal.<\/p>\n<p><\/p>\n<p>Configuramos o Gitlab Runner em modo de di\u00e1logo (Shell, Docker, VirtualBox, SSH)<\/p>\n<p><\/p>\n<p>O c\u00f3digo no Gitlab Runner ser\u00e1 executado a cada commit, dependendo da configura\u00e7\u00e3o do .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/37c8ac7499f0cfba2eb07a84083e44e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Como isso \u00e9 visualmente apresentado no GitLab na interface web. Depois de conectar o GitLab CI, aparece uma bandeira que mostra em que estado o build est\u00e1 no momento.<\/p>\n<p><\/p>\n<p>Podemos ver que h\u00e1 4 minutos foi feito um commit que passou por todos os testes sem causar problemas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/33ac79c45f0651a5f8bde75092c4ac44.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Podemos olhar mais detalhadamente os builds. Aqui vemos que dois estados j\u00e1 foram passados: o estado de teste e o estado de implanta\u00e7\u00e3o no staging.<\/p>\n<p><\/p>\n<p>Se clicarmos em um build espec\u00edfico, haver\u00e1 a sa\u00edda do console dos comandos que foram executados no processo de acordo com o .gitlab-ci.yml.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d26dd28708c7fc8a409af4be4d48f502.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Assim \u00e9 como a hist\u00f3ria do nosso produto se apresenta. Vemos que houve tentativas bem-sucedidas. Quando os testes falham, o c\u00f3digo n\u00e3o avan\u00e7a para o pr\u00f3ximo passo e n\u00e3o h\u00e1 atualiza\u00e7\u00e3o no staging.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/ee7bd81dc283c7af0c194779d4230780.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quais problemas est\u00e1vamos resolvendo no staging quando implementamos o Docker? Nosso sistema \u00e9 composto por componentes e surgiu a necessidade de reiniciar apenas parte dos componentes que foram atualizados no reposit\u00f3rio, em vez de reiniciar todo o sistema.<\/p>\n<p><\/p>\n<p>Para isso, tivemos que organizar tudo em pastas separadas.<\/p>\n<p><\/p>\n<p>Depois que fizemos isso, surgiu um problema em que o Docker-compose cria um espa\u00e7o de rede separado para cada pasta e n\u00e3o v\u00ea os componentes vizinhos.<\/p>\n<p><\/p>\n<p>Para contornar isso, criamos manualmente uma rede no Docker. No Docker-compose, especificamos que este projeto usaria essa rede.<\/p>\n<p><\/p>\n<p>Assim, cada componente que inicia com essa rede pode ver os componentes em outras partes do sistema.<\/p>\n<p><\/p>\n<p>O pr\u00f3ximo problema \u00e9 a separa\u00e7\u00e3o do staging entre v\u00e1rios projetos.<\/p>\n<p><\/p>\n<p>Para que tudo isso parecesse bonito e o mais pr\u00f3ximo poss\u00edvel do production, \u00e9 bom usar a porta 80 ou 443, que \u00e9 amplamente utilizada na WEB.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/f863cf1833271bf132455a70ad7d2706.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Como resolvemos isso? Designamos um \u00fanico GitLab Runner para todos os grandes projetos.<\/p>\n<p><\/p>\n<p>O GitLab permite iniciar v\u00e1rios GitLab Runners distribu\u00eddos que simplesmente pegam todas as tarefas em ordem aleat\u00f3ria.<\/p>\n<p><\/p>\n<p>Para que n\u00e3o houvesse confus\u00e3o, limitamos nosso grupo de projetos a um \u00fanico GitLab Runner, que consegue lidar bem com nossos volumes.<\/p>\n<p><\/p>\n<p>Retiramos o nginx-proxy para um script de execu\u00e7\u00e3o separado e nele especificamos as redes de todos os projetos. <\/p>\n<p><\/p>\n<p>Nosso projeto tem uma rede \u00fanica, enquanto o balanceador tem v\u00e1rias redes com os nomes dos projetos. Ele pode proxy para outros dom\u00ednios.<\/p>\n<p><\/p>\n<p>Recebemos solicita\u00e7\u00f5es pelo dom\u00ednio na porta 80, que s\u00e3o gerenciadas por um grupo de cont\u00eaineres que atende a esse dom\u00ednio.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/25c769f029b272a17fd06bbe60cf0ea0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quais foram os outros problemas? O fato \u00e9 que, por padr\u00e3o, todos os cont\u00eaineres s\u00e3o executados como o usu\u00e1rio root. Este root n\u00e3o \u00e9 o mesmo root do sistema host.<\/p>\n<p><\/p>\n<p>No entanto, se voc\u00ea entrar no cont\u00eainer, estar\u00e1 como root, e o arquivo que criamos nesse cont\u00eainer recebe permiss\u00f5es de root.<\/p>\n<p><\/p>\n<p>Se um desenvolvedor entrou no cont\u00eainer e executou alguns comandos que geraram arquivos, depois saiu do cont\u00eainer, ent\u00e3o em seu diret\u00f3rio de trabalho ele ter\u00e1 um arquivo ao qual n\u00e3o tem acesso.<\/p>\n<p><\/p>\n<p>Como podemos resolver isso? Podemos adicionar usu\u00e1rios que estar\u00e3o dentro do cont\u00eainer.<\/p>\n<p><\/p>\n<p>Quais problemas surgiram quando adicionamos o usu\u00e1rio?<\/p>\n<p><\/p>\n<p>Ao criar um usu\u00e1rio, frequentemente n\u00e3o coincidimos o ID do grupo (UID) com o ID do usu\u00e1rio (GID).<\/p>\n<p><\/p>\n<p>Para resolver esse problema, dentro do cont\u00eainer usamos usu\u00e1rios com ID 1000.<\/p>\n<p><\/p>\n<p>No nosso caso, isso coincidiu com o fato de que praticamente todos os desenvolvedores usam o sistema operacional Ubuntu. E no Ubuntu, o primeiro usu\u00e1rio tem o ID 1000.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/d4911374e4953fdcd807c387efeafec3.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quais s\u00e3o nossos planos?<\/p>\n<p><\/p>\n<p>Ler a documenta\u00e7\u00e3o do Docker novamente. O projeto est\u00e1 em constante desenvolvimento, a documenta\u00e7\u00e3o est\u00e1 mudando. As informa\u00e7\u00f5es obtidas h\u00e1 dois ou tr\u00eas meses j\u00e1 est\u00e3o come\u00e7ando a ficar desatualizadas. <\/p>\n<p><\/p>\n<p>Parte dos problemas que resolvemos pode j\u00e1 ter sido solucionada com ferramentas padr\u00f5es.<\/p>\n<p><\/p>\n<p>Estamos ansiosos para avan\u00e7ar e nos concentrar diretamente na orquestra\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Um dos exemplos \u00e9 o mecanismo integrado ao Docker chamado Docker Swarm, que vem pronto para uso. Gostar\u00edamos de implementar algo em produ\u00e7\u00e3o usando a tecnologia Docker Swarm.<\/p>\n<p><\/p>\n<p>A cria\u00e7\u00e3o de cont\u00eaineres dificultou o trabalho com logs. Atualmente, os logs est\u00e3o isolados. Eles est\u00e3o espalhados pelos cont\u00eaineres. Um dos objetivos \u00e9 facilitar o acesso aos logs atrav\u00e9s de uma interface web.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Processo de Desenvolvimento e Teste com Docker e Gitlab CI\" src=\"\/wp-content\/uploads\/2019\/04\/cff8c72dd8af7de1fa0227601bd1d69c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/449742\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &#171;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&#187; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Docker + Gitlab CI \u0447\u0430\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c? \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c? \u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c? \u042d\u0442\u043e\u0442 \u0434\u043e\u043a\u043b\u0430\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32526","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:47:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47O Processo de Desenvolvimento e Testes com Docker e Gitlab CI | ProHoster","description":"Sugiro que voc\u00ea confira a transcri\u00e7\u00e3o da apresenta\u00e7\u00e3o de Alexander Sigachev da Inventos \"O Processo de Desenvolvimento e Testes com Docker + Gitlab CI\". Aqueles que est\u00e3o apenas come\u00e7ando a implementar o processo de desenvolvimento.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker \u0438 Gitlab CI | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0421\u0438\u0433\u0430\u0447\u0435\u0432\u0430 \u0438\u0437 Inventos &quot;\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 Docker + Gitlab CI&quot; \u0422\u0435, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438.","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/protsess-razrabotki-i-testirovaniya-s-docker-i-gitlab-ci","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:47:32+00:00","article:modified_time":"2019-10-31T18:47:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32526","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 11:18:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:57:22","updated":"2026-01-21 11:18:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/32526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=32526"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/32526\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/24326"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=32526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=32526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=32526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}