docker para desenvolvedores - tcxsproject.com.br livros hacker gorpo orko... ·...

175

Upload: others

Post on 19-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé
Page 2: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Docker paradesenvolvedores

Rafael Gomes

Esse livro está à venda emhttp://leanpub.com/dockerparadesenvolvedores

Essa versão foi publicada em 2017-04-30

This is a Leanpub book. Leanpub empowers authors andpublishers with the Lean Publishing process. LeanPublishing is the act of publishing an in-progress ebookusing lightweight tools and many iterations to get readerfeedback, pivot until you have the right book and buildtraction once you do.

This work is licensed under a Creative CommonsAttribution 4.0 International License

Page 3: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Tweet Sobre Esse Livro!Por favor ajude Rafael Gomes a divulgar esse livro noTwitter!

A hashtag sugerida para esse livro é#docker-para-desenvolvedores.

Descubra o que as outras pessoas estão falando sobre esselivro clicando nesse link para buscar a hashtag no Twitter:

https://twitter.com/search?q=#docker-para-desenvolvedores

Page 4: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Conteúdo

Prefácio . . . . . . . . . . . . . . . . . . . . . . . . . . 1Abraços, . . . . . . . . . . . . . . . . . . . . . . . 2

Como ler esse livro . . . . . . . . . . . . . . . . . . . 3

Agradecimentos . . . . . . . . . . . . . . . . . . . . . 5

Introdução . . . . . . . . . . . . . . . . . . . . . . . . 8

Por que usar Docker? . . . . . . . . . . . . . . . . . . 9

O que é Docker? . . . . . . . . . . . . . . . . . . . . . 17

Instalação . . . . . . . . . . . . . . . . . . . . . . . . . 21Instalando no GNU/Linux . . . . . . . . . . . . . . 21Instalando no MacOS . . . . . . . . . . . . . . . . 24Instalando no Windows . . . . . . . . . . . . . . . 25

Comandos básicos . . . . . . . . . . . . . . . . . . . . 29Executando um container . . . . . . . . . . . . . . 29Verificando a lista de containers . . . . . . . . . . 33Gerenciamento de containers . . . . . . . . . . . . 34

Criando sua própria imagem no Docker . . . . . . . 36

Page 5: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

CONTEÚDO

Entendendo armazenamento no Docker . . . . . . . 44

Entendendo a rede no Docker . . . . . . . . . . . . . 50

Utilizando Docker em múltiplos ambientes . . . . . . 60

Gerenciando múltiplos containers docker com Doc-ker Compose . . . . . . . . . . . . . . . . . . . . . 70

Como usar Docker sem GNU/Linux . . . . . . . . . . 78

Transformando sua aplicação em container . . . . . 87

Base de código . . . . . . . . . . . . . . . . . . . . . . 89

Dependência . . . . . . . . . . . . . . . . . . . . . . . 93

Configurações . . . . . . . . . . . . . . . . . . . . . . 97

Serviços de Apoio . . . . . . . . . . . . . . . . . . . . 101

Construa, lance, execute . . . . . . . . . . . . . . . . 105

Processos . . . . . . . . . . . . . . . . . . . . . . . . . 110

Vínculo de portas . . . . . . . . . . . . . . . . . . . . 113

Concorrência . . . . . . . . . . . . . . . . . . . . . . . 117

Descartabilidade . . . . . . . . . . . . . . . . . . . . . 125

Paridade entre desenvolvimento/produção . . . . . . 130

Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

Page 6: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

CONTEÚDO

Processos de administração . . . . . . . . . . . . . . 135

Dicas para uso do Docker . . . . . . . . . . . . . . . . 139Dicas para Rodar . . . . . . . . . . . . . . . . . . . 139Boas práticas para construção de imagens . . . . . 148

Apêndice . . . . . . . . . . . . . . . . . . . . . . . . . 158Container ou máquina virtual? . . . . . . . . . . . 158Comandos úteis . . . . . . . . . . . . . . . . . . . 164Posso rodar aplicações GUI? . . . . . . . . . . . . 165

Page 7: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

PrefácioNo desenvolvimento de software é comum criar-se boas práti-cas a padrões. Em específico a aplicações web, certos conceitose práticas como DevOps, infraestrutura em Nuvem, phoenix,imutável e 12 factor apps são teorias bem aceitas que ajudamna produtividade e manutenção dos sistemas. Por serem con-ceitos não tão novos, são muitas as ferramentas e sistemasque podem auxiliar na implantação desses. Mas Docker é umadas primeiras e mais comentadas ferramentas e plataformasque combina tantos desses conceitos de maneira coesa erelativamente simples de usar. Como qualquer ferramenta,Docker é um investimento que oferecemelhor retorno quandose entende seu propósito e como usa-lo apropriadamente.

Existem várias apresentações, artigos e documentações sobreDocker. Porém existia a oportunidade de um livro ligandoa teoria com a prática da ferramenta. Em que o leitor podeentender as motivações de Docker e também como organizarsua aplicação para extrair o maior proveito da ferramenta.Estou muito alegre que o Rafael escreveu este livro, queacredito ser uma contribuição importante para nossa área. ORafael é extremamente engajado na comunidade de Dockere Devops pelo Brasil, além disso entende o que as pessoasbuscam de conhecimento na área. Nesse livro você vai poderentender o básico sobre Docker com uma liguagem simples evários exemplos práticos. Espero que esse livro seja mais umpasso para impulsionar sua jornada. Desejo-lhe sucesso e tudode melhor.

Page 8: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Prefácio 2

Abraços,

Luís Armando Bianchin

Page 9: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como ler esse livroEsse material foi dividido em duas grandes partes. A primeiratrata das questões mais básicas do Docker. É exatamente omínimo necessário que um desenvolvedor precisa saber parautilizar essa tecnologia com propriedade, ou seja, ciente doque exatamente acontece ao executar cada comando.

Nessa primeira parte tentaremos não abordar questões de“baixo nível” do Docker, pois são de maior apelo para a equiperesponsável pela infraestrutura.

Caso você não saiba nada sobre Docker, aconselhamosmuitoa leitura dessa primeira parte, pois assim conseguirá aprovei-tar a segunda parte, focada na construção de uma aplicaçãoweb no Docker seguindo as melhores práticas, sem pausas.Neste livro, adotamos as práticas do 12factor1.

O 12factor será detalhado no início da segunda parte, maspodemos adiantar que o consideramos os “12 mandamentospara aplicações web no Docker”, ou seja, uma vez que suaaplicação siga todas as boas práticas apresentadas neste docu-mento, você possivelmente estará usando todo potencial queo Docker tem a lhe proporcionar.

Essa segunda parte é dividida por cada boa prática do 12fac-tor. Dessa forma, apresentamos um código de exemplo noprimeiro capítulo, que será evoluído ao longo do desenvol-vimento do livro. A ideia é que você possa exercitar com umcódigo de verdade e, assim, assimilar o conteúdo de forma

1https://12factor.net/pt_br/

Page 10: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como ler esse livro 4

prática. Também organizamos alguns apêndices com assuntosextras importantes, mas que não se encaixaram nos capítulos.

Page 11: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

AgradecimentosMeu primeiro agradecimento vai para a pessoa que me deu achance de estar aqui e poder escrever esse livro: minha mãe.A famosa Cigana, ou Dona Arlete, pessoa maravilhosa, quepra mim é um exemplo de ser humano.

Quero agradecer também a minha segunda mãe, Dona Maria,que tanto cuidou de mim quando eu era criança, enquantoDona Arlete tomava conta dos outros dois filhos e um sobri-nho. Me sinto sortudo por ter duas, enquanto muitos não temao menos uma mãe.

Aproveito para agradecer a pessoa que me apresentou oDocker, Robinho2, também conhecido como Robson Peixoto.Em uma conversa informal no evento Linguágil, em Salvador(BA), ele me falou: “Estude Docker!” E, aqui estou eu termi-nando um livro que transformou a minha vida. Obrigado deverdade Robinho!

Obrigado a Luís Armando Bianchin, que começou como autorjunto comigo, mas depois por força do destino acabou nãopodendo continuar. Fica aqui meu agradecimento, pois foicom seu feedback constante que pude continuar a fazer olivro.

Obrigado a Paulo Caroli que tanto me incentivou a escrevero livro e indicou a plataforma Leanpub pra fazer isso. Se nãofosse ele, o livro não teria saído tão rápido.

2https://twitter.com/robinhopeixoto

Page 12: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Agradecimentos 6

Obrigada a fantástica Emma Pinheiro3, pela belíssima capa.

Quero agradecer muito as pessoas incríveis do Raul HackerClub4 que tanto me incentivaram em todo esse tempo.

Quero agradecer a mãe do meu filho, Eriane Soares, hojeminha grande amiga que tanto me incentivou a escrever olivro enquanto morávamos juntos!

Como todo produto de conhecimento aberto, esse livro nãoseria possível sem ajuda dessa vibrante comunidade DockerBrasil. Para alguns membros darei destaque pelo empenho aoler diversos capítulos inúmeras vezes e dedicar seu preciosotempo sugerindo melhorias:

• Gjuniioor [email protected]• Marco Antonio Martins Junior5 - Escreveu os capítulos“Posso rodar aplicações GUI” e “Comandos úteis”.

• Jorge Flávio Costa6

• Glesio Paiva7

• Bruno Emanuel Silva8

• George Moura9

• Felipe de Morais10

• Waldemar Neto11

• Igor Garcia

3https://twitter.com/n3k00n34http://raulhc.cc/5https://twitter.com/somatorio6https://twitter.com/JFCostta7https://twitter.com/glesio8https://twitter.com/jwalker_pe9https://twitter.com/georgemoura10https://twitter.com/felipedemorais_11https://twitter.com/waldemarnt

Page 13: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Agradecimentos 7

• Diogo Fernandes12

É bem possível que eu tenha esquecido o nome de pessoasaqui, mas a medida que for resgatando meus logs, vou atua-lizar.

12https://twitter.com/diogocfernandes

Page 14: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

IntroduçãoEssa parte do livro é direcionada a quem não tem conhe-cimento básico do Docker. Caso você já saiba usar, fique àvontade para pular. Entretanto, mesmo que você já conheçao Docker, apresentamos explicações sobre vários recursosdisponíveis e como funcionam.

Mesmo que você já use o Docker, ler essa parte do livro, emalgum momento da sua vida, pode ser importante para saberde forma mais consistente o que acontece com cada comandoexecutado.

Page 15: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker?Docker tem sido um assunto bem comentado ultimamente,muitos artigos foram escritos, geralmente tratando sobre comousá-lo, ferramentas auxiliares, integrações e afins, mas muitaspessoas ainda fazem a pergunta mais básica quando se tratada possibilidade de utilizar qualquer nova tecnologia: “Porque devo usar isso?” Ou seria: “O que isso tem a me oferecerdiferente do que já tenho hoje?”

É normal que ainda duvidem do potencial do Docker, algunsaté acham que se trata de um hype13. Mas nesse capítulo

13http://techfree.com.br/2015/06/sera-que-esse-modelo-de-containers-e-um-hype/

Page 16: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 10

pretendemos demonstrar alguns bons motivos para se utilizarDocker.

Vale frisar que o Docker não é uma “bala de prata” - ele não sepropõe a resolver todos problemas, muito menos ser a soluçãoúnica para as mais variadas situações.

Abaixo alguns bons motivos para se utilizar Docker:

1 – Ambientes semelhantes

Uma vez que sua aplicação seja transformada em uma ima-gem Docker, ela pode ser instanciada como container emqualquer ambiente que desejar. Isso significa que poderá uti-lizar sua aplicação no notebook do desenvolvedor da mesmaforma que seria executada no servidor de produção.

A imagem Docker aceita parâmetros durante o início docontainer, isso indica que amesma imagem pode se comportarde formas diferentes entre distintos ambientes. Esse containerpode conectar-se a seu banco de dados local para testes,usando as credenciais e base de dados de teste. Mas quandoo container, criado a partir da mesma imagem, receber parâ-metros do ambiente de produção, acessará a base de dadosem uma infraestrutura mais robusta, com suas respectivascredenciais e base de dados de produção, por exemplo.

As imagens Docker podem ser consideradas como implan-tações atômicas - o que proporciona maior previsibilidadecomparado a outras ferramentas como Puppet, Chef, Ansible,etc - impactando positivamente na análise de erros, assimcomo na confiabilidade do processo de entrega contínua14,que se baseia fortemente na criação de um único artefato que

14https://www.thoughtworks.com/continuous-delivery

Page 17: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 11

migra entre ambientes. No caso do Docker, o artefato seria aprópria imagem com todas as dependências requeridas paraexecutar seu código, seja ele compilado ou dinâmico.

2 – Aplicação como pacote completo

Utilizando as imagens Docker é possível empacotar todasua aplicação e dependências, facilitando a distribuição, poisnão será mais necessário enviar uma extensa documentaçãoexplicando como configurar a infraestrutura necessária parapermitir a execução, basta disponibilizar a imagem em repo-sitório e liberar o acesso para o usuário e, ele mesmo podebaixar o pacote, que será executado sem problemas.

A atualização também é positivamente afetada, pois a es-trutura de camadas15 do Docker viabiliza que, em caso demudança, apenas a parte modificada seja transferida e assim oambiente pode ser alterado de forma mais rápida e simples. Ousuário precisa executar apenas um comando para atualizara imagem da aplicação, que será refletida no container emexecução apenas no momento desejado. As imagens Dockerpodem utilizar tags e, assim, viabilizar o armazenamento demúltiplas versões da mesma aplicação. Isso significa que emcaso de problema na atualização, o plano de retorno serábasicamente utilizar a imagem com a tag anterior.

3 – Padronização e replicação

Como as imagens Docker são construídas através de arquivosde definição16, é possível garantir que determinado padrão

15http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/16https://docs.docker.com/engine/reference/builder/

Page 18: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 12

seja seguido, aumentando a confiança na replicação. Bastaque as imagens sigam as melhores práticas17 de construçãopara que seja viável escalarmos18 a estrutura rapidamente.

Caso a equipe receba uma nova pessoa para trabalhar nodesenvolvimento, essa poderá receber o ambiente de trabalhocom alguns comandos. Esse processo durará o tempo dodownload das imagens a serem utilizadas, assim como osarquivos de definições da orquestração das mesmas. Issofacilita a introdução de um novo membro no processo dedesenvolvimento da aplicação, que poderá reproduzir rapida-mente o ambiente em sua estação e assim desenvolver códigosseguindo o padrão da equipe.

Na necessidade de se testar nova versão de determinada parteda solução, usando imagens Docker, normalmente basta amudança de um ou mais parâmetros do arquivo de definiçãopara iniciar um ambiente modificado com a versão requeridapara avaliação. Ou seja: criar e modificar a infraestruturaficou bem mais fácil e rápido.

4 – Idioma comum entre Infraestruturae desenvolvimento

A sintaxe usada para parametrizar as imagens e ambientesDocker pode ser considerada um idioma comum entre áreasque costumeiramente não dialogavam bem. Agora é possívelambos os setores apresentarem propostas e contra propostascom base em um documento comum.

A infraestrutura requerida estará presente no código do de-senvolvedor e a área de infraestrutura poderá analisar o

17https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/18https://pt.wikipedia.org/wiki/Escalabilidade

Page 19: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 13

documento, sugerindo mudanças para adequação de padrõesdo seu setor ou não. Tudo isso em comentários e aceitaçãode merge ou pull request do sistema de controle de versão decódigos.

5 – Comunidade

Assim como é possível acessar o github19 ou gitlab20 à procurade exemplos de código, usando o repositório de imagens doDocker21 é possível conseguir bons modelos de infraestruturade aplicações ou serviços prontos para integrações complexas.

Um exemplo é o nginx22 como proxy reverso e mysql23 comobanco de dados. Caso a aplicação necessite desses dois recur-sos, você não precisa perder tempo instalando e configurandototalmente esses serviços. Basta utilizar as imagens do reposi-tório, configurando parâmetros mínimos para adequação como ambiente. Normalmente as imagens oficiais seguem as boaspráticas de uso dos serviços oferecidos.

Utilizar essas imagens não significa ficar “refém” da confi-guração trazida com elas, pois é possível enviar sua própriaconfiguração para os ambientes e evitar apenas o trabalho dainstalação básica.

Dúvidas

Algumas pessoas enviaram dúvidas relacionadas às vanta-gens que explicitamos nesse texto. Assim, ao invés de respondê-

19http://github.com/20https://about.gitlab.com/21http://hub.docker.com/22https://hub.docker.com/_/nginx/23https://hub.docker.com/_/mysql/

Page 20: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 14

las pontualmente, resolvemos publicar as perguntas e as res-pectivas respostas aqui.

Qual a diferença entre imagem Docker edefinições criadas por ferramenta deautomação de infraestrutura?

Como exemplo de ferramentas de automação de infraestru-tura temos o Puppet24, Ansible25 e Chef26. Elas podem garantirambientes parecidos, uma vez que faz parte do seu papelmanter determinada configuração no ativo desejado.

A diferença entre a solução Docker e gerência de configuraçãopode parecer bem tênue, pois ambas podem suportar a confi-guração necessária de toda infraestrutura que uma aplicaçãodemanda para ser implantada, mas achamos que uma dasdistinções mais relevante está no seguinte fato: a imagem éuma abstração completa e não requer qualquer tratamentopara lidar com as mais variadas distribuições GNU/Linuxexistentes, já que a imagem Docker carrega em si uma cópiacompleta dos arquivos de uma distribuição enxuta.

Carregar em si a cópia de uma distribuição GNU/Linuxnão costuma ser problema para o Docker, pois utilizando omodelo de camadas, economiza bastante recurso, reutilizandoas camadas de base. Leia esse artigo27 para entender maissobre armazenamento do Docker.

Outra vantagem da imagem em relação a gerência de confi-guração é que, utilizando a imagem, é possível disponibilizaro pacote completo da aplicação em um repositório e, esse

24https://puppetlabs.com/25https://www.ansible.com/26https://www.chef.io/chef/27http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/

Page 21: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 15

“produto final”, ser utilizado facilmente sem necessidade deconfiguração completa. Apenas um arquivo de configuraçãoe um comando custumam ser suficientes para iniciar umaaplicação criada como imagem Docker.

Ainda sobre o processo de imagem Docker como produto norepositório: pode ser usado também no processo de atualiza-ção da aplicação, como já explicamos nesse capítulo.

O uso da imagem base no Docker dedeterminada distribuição não é o mesmo quecriar uma definição de gerência de configuraçãopara uma distribuição?

Não! A diferença está na perspectiva do hospedeiro. No casodo Docker não importa qual distribuição GNU/Linux é utili-zada no host, pois há uma parte da imagem que carrega todosos arquivos de uma mini distribuição que será suficiente parasuportar tudo que a aplicação precisa. Caso seu Docker hostseja Fedora e a aplicação precisar de arquivos do Debian, nãose preocupe, pois a imagem em questão trará arquivos Debianpara suportar o ambiente. E, como já foi dito anteriormente,isso normalmente não chega a impactar negativamente noconsumo de espaço em disco.

Quer dizer então que agora eu, desenvolvedor,preciso me preocupar com tudo daInfraestrutura?

Não! Quando citamos que é possível o desenvolvedor especifi-car a infraestrutura, estamos falando da camadamais próximada aplicação e não de toda a arquitetura necessária (Sistemaoperacional básico, regras de firewall, rotas de rede e etc).

Page 22: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Por que usar Docker? 16

A ideia do Docker é que os assuntos relevantes e diretamenteligados a aplicação possam ser configurados pelo desenvol-vedor. Isso não o obriga a realizar essa atividade. É umapossibilidade que agrada muitos desenvolvedores, mas casonão seja a situação, pode ficar tranquilo, outra equipe tratarádessa parte. Apenas o processo de implantação será poucomais lento.

Muitas pessoas falam de Docker para microserviços. É possível usar o Docker paraaplicações monolíticas?

Sim! Porém, em alguns casos, é necessário pequenasmodifica-ções na aplicação, para que ela possa usufruir das facilidadesdo Docker. Um exemplo comum é o log que, normalmente,a aplicação envia para determinado arquivo, ou seja, nomodelo Docker as aplicações que estão nos containers nãodevem tentar escrever ou gerir arquivos de logs. Ao invésdisso, cada processo em execução escreve seu próprio fluxo deevento, sem buffer, para o stdout28, pois o Docker tem driversespecíficos para tratar o log enviado dessa forma. Essa partede melhores práticas de gerenciador de logs será detalhada emcapítulos posteriores.

Em alguns momentos você perceberá que o uso do Dockerpara sua aplicação demanda muito esforço. Nesses casos,normalmente, o problema está mais em como a aplicaçãotrabalha do que na configuração do Docker. Esteja atento.

Tem mais dúvidas e/ou bons motivos para utilizar Docker?Comente aqui29.

28https://pt.wikipedia.org/wiki/Fluxos_padr%C3%A3o29http://techfree.com.br/2016/03/porque-usar-docker/

Page 23: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

O que é Docker?De forma bem resumida, podemos dizer que o Docker éuma plataforma aberta, criada com o objetivo de facilitar odesenvolvimento, a implantação e a execução de aplicaçõesem ambientes isolados. Foi desenhada especialmente paradisponibilizar uma aplicação da forma mais rápida possível.

Usando o Docker, você pode facilmente gerenciar a infra-estrutura da aplicação, isso agilizará o processo de criação,manutenção e modificação do seu serviço.

Todo processo é realizado sem necessidade de qualquer acessoprivilegiado à infraestrutura corporativa. Assim, a equiperesponsável pela aplicação pode participar da especificação doambiente junto com a equipe responsável pelos servidores.

O Docker viabilizou uma “linguagem” comum entre desen-volvedores e administradores de servidores. Essa nova “lin-guagem” é utilizada para construir arquivos com as definições

Page 24: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

O que é Docker? 18

da infraestrutura necessária e como a aplicação será dispostanesse ambiente, em qual porta fornecerá seu serviço, quais da-dos de volumes externos serão requisitados e outras possíveisnecessidades.

O Docker também disponibiliza uma nuvem pública paracompartilhamento de ambientes prontos, que podem ser uti-lizados para viabilizar customizações para ambientes especí-ficos. É possível obter uma imagem pronta do apache e con-figurar os módulos específicos necessários para a aplicaçãoe, assim, criar seu próprio ambiente customizado. Tudo compoucas linhas de descrição.

O Docker utiliza o modelo de container para “empacotar”a aplicação que, após ser transformada em imagem Docker,pode ser reproduzida em plataforma de qualquer porte; ouseja, caso a aplicação funcione sem falhas em seu notebook,funcionará também no servidor ou no mainframe. Construauma vez, execute onde quiser.

Os containers são isolados a nível de disco, memória, pro-cessamento e rede. Essa separação permite grande flexibili-dade, onde ambientes distintos podem coexistir no mesmohost, sem causar qualquer problema. Vale salientar que ooverhead nesse processo é o mínimo necessário, pois cadacontainer normalmente carrega apenas um processo, que éaquele responsável pela entrega do serviço desejado. Emtodo caso, esse container também carrega todos os arquivosnecessários (configuração, biblioteca e afins) para execuçãocompletamente isolada.

Outro ponto interessante no Docker é a velocidade paraviabilizar o ambiente desejado; como é basicamente o iníciode um processo e não um sistema operacional inteiro, o tempode disponibilização é, normalmente, medido em segundos.

Page 25: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

O que é Docker? 19

Virtualização a nível do sistemaoperacional

Omodelo de isolamento utilizado no Docker é a virtualizaçãoa nível do sistema operacional, um método de virtualizaçãoonde o kernel do sistema operacional permite que múltiplosprocessos sejam executados isoladamente no mesmo host.Esses processos isolados em execução são denominados noDocker de container.

Para criar o isolamento necessário do processo, o Docker usa afuncionalidade do kernel, denominada de namespaces30, quecria ambientes isolados entre containers: os processos de umaaplicação em execução não terão acesso aos recursos de outra.A menos que seja expressamente liberado na configuração decada ambiente.

30http://man7.org/linux/man-pages/man7/namespaces.7.html

Page 26: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

O que é Docker? 20

Para evitar a exaustão dos recursos da máquina por apenasum ambiente isolado, o Docker usa a funcionalidade cgroups31

do kernel, responsável por criar limites de uso do hardwarea disposição. Com isso é possível coexistir no mesmo hostdiferentes containers sem que um afete diretamente o outropor uso exagerado dos recursos compartilhados.

31https://en.wikipedia.org/wiki/Cgroups

Page 27: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

InstalaçãoO Docker deixou de ser apenas um software para virar umconjunto deles: um ecossistema.

Nesse ecossistema temos os seguintes softwares:

• Docker Engine: É o software base de toda solução. Étanto o daemon responsável pelos containers como ocliente usado para enviar comandos para o daemon.

• Docker Compose: É a ferramenta responsável peladefinição e execução de múltiplos containers com baseem arquivo de definição.

• Docker Machine: é a ferramenta que possibilita criar emanter ambientes docker em máquinas virtuais, ambi-entes de nuvem e até mesmo em máquina física.

Não citamos o Swarm32 e outras ferramentas por não estaremalinhados com o objetivo desse livro: introdução para desen-volvedores.

Instalando no GNU/Linux

Explicamos a instalação da forma mais genérica possível,dessa forma você poderá instalar as ferramentas em qualquerdistribuição GNU/Linux que esteja usando.

32https://docs.docker.com/swarm/overview/

Page 28: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 22

Docker engine no GNU/Linux

Para instalar o docker engine é simples. Acesse seu terminalpreferido do GNU/Linux e torne-se usuário root:

1 su - root

ou no caso da utilização de sudo

1 sudo su - root

Execute o comando abaixo:

1 wget -qO- https://get.docker.com/ | sh

Aconselhamos que leia o script que está sendo executado noseu sistema operacional. Acesse esse link33 e analise o códigoassim que tiver tempo para fazê-lo.

Esse procedimento demora um pouco. Após terminar o teste,execute o comando abaixo:

1 docker container run hello-world

Tratamento de possíveis problemas

Se o acesso a internet da máquina passar por controle detráfego (aquele que bloqueia o acesso a determinadas páginas)você poderá encontrar problemas no passo do apt-key. Casoenfrente esse problema, execute o comando abaixo:

33https://get.docker.com/

Page 29: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 23

1 wget -qO- https://get.docker.com/gpg | sudo apt-k\

2 ey add -

Instalando Docker compose com pip

O pip34 é um gerenciador de pacotes Python e, como o docker-compose, é escrito nessa linguagem, é possível instalá-lo daseguinte forma:

1 pip install docker-compose

Tratamento de possíveis problemas

Caso não tenha instalado o comando pip em seu computador,normalmente ele pode ser instalado usando seu sistema degerenciamento de pacote com o nome python-pip ou seme-lhante.

Docker machine no GNU/Linux

Instalar o docker machine é simples. Acesse o seu terminalpreferido do GNU/Linux e torne-se usuário root:

1 su - root

ou no caso da utilização de sudo

1 sudo su - root

Execute o comando abaixo:34https://en.wikipedia.org/wiki/Pip_(package_manager)

Page 30: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 24

1 $ curl -L https://github.com/docker/machine/relea\

2 ses/download/v0.10.0/docker-machine-`uname -s`-`u\

3 name -m` > /usr/local/bin/docker-machine && \

4 chmod +x /usr/local/bin/docker-machine

Para testar, execute o comando abaixo:

1 docker-machine version

Obs.: O exemplo anterior utiliza a versão mais recente nomomento desta publicação. Verifique se há alguma versãoatualizada consultando a documentação oficial35.

Instalando no MacOS

A instalação das ferramentas do Ecossistema Docker no Ma-cOS pode ser realizada através de um único grande pacotechamado Docker for Mac.

Você pode instalar via brew cask com o comando abaixo:

1 brew cask install docker

Para efetuar a configuração inicial, você deve executar oaplicativo Docker:

35https://docs.docker.com/machine/install-machine/

Page 31: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 25

Na tela seguinte selecione a opção Ok.

Será solicitado seu usuário e senha para liberar a instalaçãodos softwares. Preencha e continue o processo.

Para testar, abra um terminal e execute o comando abaixo:

1 docker container run hello-world

Instalando no Windows

A instalação das ferramentas do Ecossistema Docker no Win-dows é realizada através de um único grande pacote, que sechama Docker Toolbox.

Page 32: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 26

O Docker Toolbox funciona apenas em versões 64bit36 doWindows e soemnte para as versões superiores ao Windows7.

É importante salientar também que é necessário habilitar osuporte de virtualização. Na versão 8 do Windows, é possívelverificar através do Task Manager. Na aba Performanceclique em CPU para visualizar a janela abaixo:

Para verificar o suporte a virtualização do Windows 7, utilizeesse link37 para maiores informações.

Instalando o Docker Toolbox

Acesse a página de download38 do Docker toolbox e baixe oinstalador correspondente ao Windows.

Após duplo clique no instalador, verá essa tela:

36https://support.microsoft.com/en-us/kb/82721837http://www.microsoft.com/en-us/download/details.aspx?id=59238https://www.docker.com/products/docker-toolbox

Page 33: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 27

Apenas clique em Next.

Page 34: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Instalação 28

Por fim, clique em Finish.

Para testar, procure e execute o software Docker QuickstartTerminal, pois ele fará todo processo necessário para começara utilizar o Docker.

Nesse novo terminal execute o seguinte comando para teste:

1 docker container run hello-world

Page 35: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicosPara utilização do Docker é necessário conhecer alguns co-mandos e entender de forma clara e direta para que servem,assim como alguns exemplos de uso.

Não abordaremos os comandos de criação de imagem e tra-tamento de problemas (troubleshooting) no Docker, pois têmcapítulos específicos para o detalhamento.

Executando um container

Para iniciar um container é necessário saber a partir dequal imagem será executado. Para listar as imagens que seuDocker host tem localmente, execute o comando abaixo:

1 docker image list

As imagens retornadas estão presentes no seu Docker hoste não demandam qualquer download da nuvem pública doDocker39, a menos que deseje atualizá-la. Para atualizar aimagem basta executar o comando abaixo:

1 docker image pull python

39hub.docker.com

Page 36: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 30

Usamos a imagem chamada python como exemplo, mas casodeseje atualizar qualquer outra imagem, basta colocar seunome no lugar de python.

Caso deseje inspecionar a imagem que acabou de atualizar,basta usar o comando abaixo:

1 docker image inspect python

O comando inspect40 é responsável por informar todos osdados referentes à imagem.

Agora que temos a imagem atualizada e inspecionada, pode-mos iniciar o container. Mas antes de simplesmente copiare colar o comando, vamos entender como ele realmentefunciona.

1 docker container run <parâmetros> <imagem> <CMD> \

2 <argumentos>

Os parâmetros mais utilizados na execução do container são:

Parâmetro Explicação

-d Execução do container embackground

-i Modo interativo. Mantém o STDINaberto mesmo sem console anexado

-t Aloca uma pseudo TTY–rm Automaticamente remove o

container após finalização (Nãofunciona com -d)

–name Nomear o container

40https://docs.docker.com/engine/reference/commandline/inspect/

Page 37: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 31

Parâmetro Explicação

-v Mapeamento de volume-p Mapeamento de porta-m Limitar o uso de memória RAM-c Balancear o uso de CPU

Segue um exemplo simples no seguinte comando:

1 docker container run -it --rm --name meu_python p\

2 ython bash

De acordo com o comando acima, será iniciado um containercom o nomemeu_python, criado a partir da imagem pythone o processo executado nesse container será o bash.

Vale lembrar que, caso o CMD não seja especificado nocomando docker container run, é utilizado o valor padrãodefinido no Dockerfile da imagem utilizada. No nosso caso épython e seu comando padrão executa o binário python, ouseja, se não fosse especificado o bash, no final do comandode exemplo acima, ao invés de um shell bash do GNU/Linux,seria exibido um shell do python.

Mapeamento de volumes

Para realizar mapeamento de volume basta especificar qualorigem do dado no host e onde deve ser montado dentro docontainer.

1 docker container run -it --rm -v "<host>:<contain\

2 er>" python

O uso de armazenamento é melhor explicado em capítulosfuturos, por isso não detalharemos o uso desse parâmetro.

Page 38: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 32

Mapeamento de portas

Para realizar o mapeamento de portas basta saber qual portaserá mapeada no host e qual deve receber essa conexão dentrodo container.

1 docker container run -it --rm -p "<host>:<contain\

2 er>" python

Um exemplo com a porta 80 do host para uma porta 8080dentro do container tem o seguinte comando:

1 docker container run -it --rm -p 80:8080 python

Com o comando acima temos a porta 80 acessível no Dockerhost que repassa todas as conexões para a porta 8080 dentrodo container. Ou seja, não é possível acessar a porta 8080 noendereço IP do Docker host, pois essa porta está acessívelapenas dentro do container que é isolada a nível de rede,como já dito anteriormente.

Gerenciamento dos recursos

Na inicialização dos containers é possível especificar algunslimites de utilização dos recursos. Trataremos aqui apenas dememória RAM e CPU, os mais utilizados.

Para limitar o uso de memória RAM que pode ser utilizadapor esse container, basta executar o comando abaixo:

Page 39: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 33

1 docker container run -it --rm -m 512M python

Com o comando acima estamos limitando esse container autilizar somente 512 MB de RAM.

Para balancear o uso da CPU pelos containers, utilizamosespecificação de pesos para cada container, quanto menor opeso, menor sua prioridade no uso. Os pesos podem oscilar de1 a 1024.

Caso não seja especificado o peso do container, ele usará omaior peso possível, nesse caso 1024.

Usaremos como exemplo o peso 512:

1 docker container run -it --rm -c 512 python

Para entendimento, vamos imaginar que três containers fo-ram colocados em execução. Um deles tem o peso padrão 1024e dois têm o peso 512. Caso os três processos demandem todaCPU o tempo de uso deles será dividido da seguinte maneira:

• O processo com peso 1024 usará 50% do tempo deprocessamento

• Os dois processos com peso 512 usarão 25% do tempode processamento, cada.

Verificando a lista de containers

Para visualizar a lista de containers de um determinadoDocker host utilizamos o comando docker ps41.

Esse comando é responsável por mostrar todos os containers,mesmo aqueles não mais em execução.

41https://docs.docker.com/engine/reference/commandline/ps/

Page 40: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 34

1 docker container list <parâmetros>

Os parâmetros mais utilizados na execução do container são:

Parâmetro Explicação

-a Lista todos os containers, inclusiveos desligados

-l Lista os últimos containers,inclusive os desligados

-n Lista os últimos N containers,inclusive os desligados

-q Lista apenas os ids dos containers,ótimo para utilização em scripts

Gerenciamento de containers

Uma vez iniciado o container a partir de uma imagem épossível gerenciar a utilização com novos comandos.

Caso deseje desligar o container basta utilizar o comandodocker stop42. Ele recebe como argumento o ID ou nome docontainer. Ambos os dados podem ser obtidos com o dockerps, explicado no tópico anterior.

Um exemplo de uso:

1 docker container stop meu_python

No comando acima, caso houvesse um container chamadomeu_python em execução, ele receberia um sinal SIGTERM

42https://docs.docker.com/engine/reference/commandline/stop/

Page 41: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Comandos básicos 35

e, caso não fosse desligado, receberia um SIGKILL depois de10 segundos.

Caso deseje reiniciar o container que foi desligado e nãoiniciar um novo, basta executar o comando docker start43:

1 docker container start meu_python

Vale ressaltar que a ideia dos containers é a deserem descartáveis. Caso você use omesmo con-tainer por muito tempo sem descartá-lo, prova-velmente está usando o Docker incorretamente.O Docker não é uma máquina, é um processoem execução. E, como todo processo, deve serdescartado para que outro possa tomar seu lugarna reinicialização do mesmo.

43https://docs.docker.com/engine/reference/commandline/start/

Page 42: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própriaimagem no DockerAntes de explicarmos como criar sua imagem, vale a penatocarmos em uma questão que normalmente confunde inici-antes do docker: “Imagem ou container?”

Qual a diferença entre Imagem eContainer?

Traçando um paralelo com o conceito de orientação a objeto44,a imagem é a classe e o container o objeto. A imagem éa abstração da infraestrutura em estado somente leitura, deonde será instanciado o container.

Todo container é iniciado a partir de uma imagem, dessaforma podemos concluir que nunca teremos uma imagem emexecução.

Um container só pode ser iniciado a partir de uma únicaimagem. Caso deseje um comportamento diferente, será ne-cessário customizar a imagem.

Anatomia da imagem

As imagens podem ser oficiais ou não oficiais.

44https://pt.wikipedia.org/wiki/Orienta%C3%A7%C3%A3o_a_objetos

Page 43: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 37

Imagens oficiais e não oficiais

As imagens oficiais do docker são aquelas sem usuários emseus nomes. A imagem “ubuntu:16.04″ é oficial, por ou-tro lado, a imagem “nuagebec/ubuntu”45 não é oficial. Essasegunda imagem é mantida pelo usuário nuagebec46, quemantém outras imagens não oficiais.

As imagens oficiais são mantidas pela empresa docker edisponibilizadas47 na nuvem docker.

O objetivo das imagens oficiais é prover um ambiente básico(ex. debian, alpine, ruby, python), um ponto de partida paracriação de imagens pelos usuários, como explicaremos maisadiante, ainda nesse capítulo.

As imagens não oficiais são mantidas pelos usuários queas criaram. Falaremos sobre envio de imagens para nuvemdocker em outro tópico.

Nome da imagem

O nome de uma imagem oficial é composto por duas partes.A primeira, a documentação48 chama de “repositório” e, a se-gunda, é chamada de “tag”. No caso da imagem “ubuntu:14.04”,ubuntu é o repositório e 14.04 é a tag.

Para o docker, o “repositório” é uma abstração do conjuntode imagens. Não confunda com o local de armazenamento dasimagens, que detalharemos mais adiante. Já a “tag”, é umaabstração para criar unidade dentro do conjunto de imagensdefinidas no “repositório”.

45https://hub.docker.com/r/nuagebec/ubuntu/46https://hub.docker.com/u/nuagebec/47https://hub.docker.com/explore/48https://docs.docker.com/engine/userguide/containers/dockerimages/

Page 44: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 38

Um “repositório” pode conter mais de uma “tag” e cadaconjunto repositório:tag representa uma imagem diferente.

Execute o comando49 abaixo para visualizar todas as imagensque se encontram localmente na sua estação, nesse momento:

1 docker image list

Como criar imagens

Há duas formas de criar imagens customizadas: com commite com Dockerfile.

Criando imagens com commit

É possível criar imagens executando o comando commit50,relacionado a um container. Esse comando usa o status atualdo container escolhido e cria a imagem com base nele.

Vamos ao exemplo. Primeiro criamos um container qualquer:

1 docker container run -it --name containercriado u\

2 buntu:16.04 bash

Agora que estamos no bash do container, instalamos o nginx:

1 apt-get update

2 apt-get install nginx -y

3 exit

Paramos o container com o comando abaixo:49https://docs.docker.com/engine/reference/commandline/images/50https://docs.docker.com/engine/reference/commandline/commit/

Page 45: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 39

1 docker container stop containercriado

Agora, efetuamos o commit desse container em uma ima-gem:

1 docker container commit containercriado meuubuntu\

2 :nginx

No exemplo do comando acima, containercriado é o nomedo container criado e modificado nos passos anteriores; onome meuubuntu:nginx é a imagem resultante do commit;o estado do containercriado é armazenado em uma imagemchamada meuubuntu:nginx que, nesse caso, a única modifi-cação que temos da imagem oficial do ubuntu na versão 16.04é o pacote nginx instalado.

Para visualizar a lista de imagens e encontrar a que acabou decriar, execute novamente o comando abaixo:

1 docker image list

Para testar sua nova imagem, vamos criar um container apartir dela e verificar se o nginx está instalado:

1 docker container run -it --rm meuubuntu:nginx dpk\

2 g -l nginx

Se quiser validar, pode executar o mesmo comando na ima-gem oficial do ubuntu:

Page 46: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 40

1 docker container run -it --rm ubuntu:16.04 dpkg -\

2 l nginx

Vale salientar que o método commit não é amelhor opção para criar imagens, pois, comoverificamos, o processo de modificação da ima-gem é completamente manual e apresenta certadificuldade para rastrear as mudanças efetuadas,uma vez que, o que foi modificado manualmentenão é registrado, automaticamente, na estruturado docker.

Criando imagens com Dockerfile

Quando se utiliza Dockerfile para gerar uma imagem, ba-sicamente, é apresentada uma lista de instruções que serãoaplicadas em determinada imagem para que outra imagemseja gerada com base nas modificações.

Dockerfile

Podemos resumir que o arquivo Dockerfile, na verdade, re-presenta a exata diferença entre uma determinada imagem,que aqui chamamos de base, e a imagem que se deseja criar.Nesse modelo temos total rastreabilidade sobre o que serámodificado na nova imagem.

Page 47: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 41

Voltemos ao exemplo da instalação do nginx no ubuntu 16.04.

Primeiro crie um arquivo qualquer para um teste futuro:

1 touch arquivo_teste

Crie um arquivo chamadoDockerfile e dentro dele o seguinteconteúdo:

1 FROM ubuntu:16.04

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

3 COPY arquivo_teste /tmp/arquivo_teste

4 CMD bash

No arquivo acima, utilizamos quatro instruções51:

FROM para informar qual imagem usaremos como base,nesse caso foi ubuntu:16.04.

RUN para informar quais comandos serão executados nesseambiente para efetuar as mudanças necessárias na infraestru-tura do sistema. São como comandos executados no shell doambiente, igual ao modelo por commit, mas nesse caso foiefetuado automaticamente e, é completamente rastreável, jáque esse Dockerfile será armazenado no sistema de controlede versão.

COPY é usado para copiar arquivos da estação onde estáexecutando a construção para dentro da imagem. Usamos umarquivo de teste apenas para exemplificar essa possibilidade,mas essa instrução é muito utilizada para enviar arquivos deconfiguração de ambiente e códigos para serem executadosem serviços de aplicação.

51https://docs.docker.com/engine/reference/builder/

Page 48: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 42

CMD para informar qual comando será executado por pa-drão, caso nenhum seja informado na inicialização de umcontainer a partir dessa imagem. No exemplo, colocamos ocomando bash, se essa imagem for usada para iniciar umcontainer e não informamos o comando, ele executará o bash.

Após construir seu Dockerfile basta executar o comando52

abaixo:

1 docker image build -t meuubuntu:nginx_auto .

Tal comando tem a opção “-t”, serve para informar o nome daimagem a ser criada. No caso, será meuubuntu:nginx_autoe o “.” ao final, informa qual contexto deve ser usado nessaconstrução de imagem. Todos os arquivos da pasta atual serãoenviados para o serviço do docker e apenas eles podem serusados para manipulações do Dockerfile (exemplo do uso doCOPY).

A ordem importa

É importante atentar que o arquivoDockerfile é uma sequên-cia de instruções lidas do topo à base e cada linha é executadapor vez. Se alguma instrução depender de outra instrução,essa dependência deve ser descrita mais acima no documento.

O resultado de cada instrução do arquivo é armazenadoem cache local. Caso o Dockerfile não seja modificado napróxima criação da imagem (build), o processo não demorará,pois tudo estará no cache. Se houver alterações, apenas ainstrução modificada e as posteriores serão executadas nova-mente.

52https://docs.docker.com/engine/reference/commandline/build/

Page 49: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Criando sua própria imagem no Docker 43

A sugestão para melhor aproveitar o cache do Dockerfile ésempre manter as instruções frequentemente alteradas maispróximas da base do documento. Vale lembrar de atendertambém as dependências entre instruções.

Um exemplo para deixar mais claro:

1 FROM ubuntu:16.04

2 RUN apt-get update

3 RUN apt-get install nginx

4 RUN apt-get install php5

5 COPY arquivo_teste /tmp/arquivo_teste

6 CMD bash

Caso modifiquemos a terceira linha do arquivo e, ao invésde instalar o nginx, mudarmos para apache2, a instrução quefaz o update no apt não será executada novamente, e sima instalação do apache2, pois acabou de entrar no arquivo,assim como o php5 e a cópia do arquivo, pois todos eles sãosubsequentes a linha modificada.

Como podemos perceber, de posse do arquivo Dockerfile, épossível ter a exata noção de quais mudanças foram efetuadasna imagem e, assim, registrar as modificações no sistema decontrole de versão.

Enviando sua imagem para nuvem

Page 50: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendoarmazenamento noDockerPara entender como o docker gerencia seus volumes, primeiroprecisamos explicar como funciona ao menos um backend53

de armazenamento do Docker. Faremos aqui com oAUFS, quefoi o primeiro e ainda é padrão em boa parte das instalaçõesdo Docker.

53http://searchdatacenter.techtarget.com/definition/back-end

Page 51: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo armazenamento no Docker 45

Como funciona um backend do Docker(Ex.: AUFS)

Backend de armazenamento é a parte da solução do Dockerque cuida do gerenciamento dos dados. No Docker temosvárias possibilidades de backend de armazenamento, masnesse texto falaremos apenas do que implementa o AUFS.

AUFS54 é um unification filesystem. É responsável por geren-ciar múltiplos diretórios, empilhá-los uns sobre os outros efornecer uma única e unificada visão, como se todos juntosfossem apenas um diretório.

Esse único diretório é utilizado para apresentar o container efunciona como se fosse um único sistema de arquivos comum.Cada diretório usado na pilha corresponde a uma camada.E, é dessa forma que o Docker as unifica e proporciona areutilização entre containeres. Pois, o mesmo diretório cor-respondente à imagem pode ser montado em várias pilhas devários containeres.

Com exceção da pasta (camada) correspondente ao container,todas as outras são montadas com permissão de somenteleitura, caso contrário asmudanças de um container poderiaminterferir em outro. O que, de fato, é totalmente contra osprincípios do Linux Container.

Caso seja necessário modificar um arquivo nas camadas (pas-tas) referentes às imagens, se utiliza a tecnologia Copy-on-write55 (CoW), responsável por copiar o arquivo para a pasta(camada) do container e fazer todas as modificações nessenível. Dessa forma, o arquivo original da camada inferior

54https://en.wikipedia.org/wiki/Aufs55https://en.wikipedia.org/wiki/Copy-on-write

Page 52: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo armazenamento no Docker 46

é sobreposto nessa pilha, ou seja, o container em questãosempre verá apenas os arquivos das camadas mais altas.

Removendo um arquivo

No caso da remoção, o arquivo da camada superior é marcadocomo whiteout file, viabilizando a visualização do arquivo decamadas inferiores.

Problema com performance

O Docker tira proveito da tecnologia Copy-on-write (CoW)do AUFS para permitir o compartilhamento de imagem eminimizar o uso de espaço em disco. AUFS funciona nonível de arquivo. Isto significa que todas as operações AUFSCoW copiarão arquivos inteiros, mesmo que, apenas pequenaparte do arquivo esteja sendo modificada. Esse comporta-mento pode ter impacto notável no desempenho do container,especialmente se os arquivos copiados são grandes e estãolocalizados abaixo de várias camadas de imagens. Nesse casoo procedimento copy-on-write dedicará muito tempo parauma cópia interna.

Page 53: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo armazenamento no Docker 47

Volume como solução para performance

Ao utilizar volumes, o Docker monta essa pasta (camada) nonível imediatamente inferior ao do container, o que permite oacesso rápido de todo dado armazenado nessa camada (pasta),resolvendo o problema de performance.

O volume também resolve questões de persistência de da-dos, pois as informações armazenadas na camada (pasta) docontainer são perdidas ao remover o container, ou seja, aoutilizar volumes temos maior garantia no armazenamentodesses dados.

Usando volumes

Mapeamento de pasta específica do host

Nesse modelo o usuário escolhe uma pasta específica do host(Ex.: /var/lib/container1) e a mapeia em uma pasta interna docontainer (Ex.: /var). O que é escrito na pasta /var do containeré escrito também na pasta /var/lib/container1 do host.

Segue o exemplo de comando usado para esse modelo demapeamento:

1 docker container run -v /var/lib/container1:/var \

2 ubuntu

Esse modelo não é portável. Necessita que o host tenha umapasta específica para que o container funcione adequada-mente.

Page 54: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo armazenamento no Docker 48

Mapeamento via container de dados

Nesse modelo é criado um container e, dentro desse, é nome-ado um volume a ser consumido por outros containeres. Dessaforma não é preciso criar uma pasta específica no host parapersistir dados. Essa pasta é criada automaticamente dentroda pasta raiz do Docker daemon. Porém, você não precisa sepreocupar com essa pasta, pois toda a referência será feita parao container detentor do volume e não para a pasta.

Segue um exemplo de uso do modelo de mapeamento:

1 docker create -v /dbdata --name dbdata postgres /\

2 bin/true

No comando acima, criamos um container de dados, onde apasta /dbdata pode ser consumida por outros containeres, ouseja, o conteúdo da pasta /dbtada poderá ser visualizado e/oueditado por outros containeres.

Para consumir esse volume do container basta utilizar ocomando:

1 docker container run -d --volumes-from dbdata --n\

2 ame db2 postgres

Agora o container db2 tem uma pasta /dbdata que é a mesmado container dbdata, tornando esse modelo completamenteportável.

Uma desvantagem é a necessidade de manter um containerapenas para isso, pois em alguns ambientes os containeres sãoremovidos com certa regularidade e, dessa forma, é necessárioter cuidado com containeres especiais. O que, de certa forma,é um problema adicional de gerenciamento.

Page 55: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo armazenamento no Docker 49

Mapeamento de volumes

Na versão 1.9 do Docker foi acrescentada a possibilidade decriar volumes isolados de containeres. Agora é possível criarum volume portável, sem a necessidade de associá-lo a umcontainer especial.

Segue um exemplo de uso do modelo de mapeamento:

1 docker volume create --name dbdata

No comando acima, o docker criou um volume que pode serconsumido por qualquer container.

A associação do volume ao container acontece de formaparecida à praticada no mapeamento de pasta do host, poisnesse caso você precisa associar o volume a uma pasta dentrodo container, como podemos ver abaixo:

1 docker container run -d -v dbdata:/var/lib/data p\

2 ostgres

Esse modelo é o mais indicado desde o lançamento, pois pro-porciona portabilidade. Não é removido facilmente quando ocontainer é deletado e ainda é bastante fácil de gerenciar.

Page 56: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede noDockerO que o docker chama de rede, na verdade é uma abstraçãocriada para facilitar o gerenciamento da comunicação dedados entre containers e os nós externos ao ambiente docker.

Não confunda a rede do docker com a já conhecida redeutilizada para agrupar os endereços IP (ex: 192.168.10.0/24).Sendo assim, sempre que mencionarmos esse segundo tipo derede, usaremos “rede IP“.

Redes padrões do Docker

O docker é disponibilizado com três redes por padrão. Essasredes oferecem configurações específicas para gerenciamentodo tráfego de dados. Para visualizar essas interfaces, bastautilizar o comando abaixo:

docker network ls

O retorno será:

Page 57: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 51

Bridge

Cada container iniciado no docker é associado a uma redeespecífica. Essa é a rede padrão para qualquer container, amenos que associemos, explicitamente, outra rede a ele. Arede confere ao container uma interface que faz bridge coma interface docker0 do docker host. Essa interface recebe,automaticamente, o próximo endereço disponível na rede IP172.17.0.0/16.

Todos os containers que estão nessa rede poderão se comuni-car via protocolo TCP/IP. Se você souber qual endereço IP docontainer deseja conectar, é possível enviar tráfego para ele.Afinal, estão todos na mesma rede IP (172.17.0.0/16).

Um detalhe a se observar: como os IPs são cedidos automati-camente, não é tarefa trivial descobrir qual IP do container dedestino. Para ajudar nessa localização, o docker disponibiliza,na inicialização de um container, a opção “–link“.

Vale ressaltar que “–link” é uma opção defasada eseu uso desaconselhado. Explicaremos esta fun-cionalidade apenas para efeito de entendimentodo legado. Essa função foi substituída por umDNS embutido no docker e, não funciona pararedes padrões do docker, apenas disponível pararedes criadas pelo usuário.

A opção “–link” é responsável por associar o IP do containerde destino ao seu nome. Caso você inicie um container a partirda imagem docker domysql com nome “bd”, em seguida inicieoutro com nome “app” a partir da imagem tutum/apache-php, você deseja que esse último container possa conectarno mysql usando o nome do container “bd”, basta iniciar daseguinte forma ambos os containers:

Page 58: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 52

1 docker container run -d --name bd -e MYSQL_ROOT_P\

2 ASSWORD=minhasenha mysql

3

4 docker container run -d -p 80:80 --name app --lin\

5 k db tutum/apache-php

Após executar os comandos, o container com o nome “app”poderá conectar no container do mysql usando o nome “bd”,ou seja, toda vez que ele tentar acessar o nome “bd” ele seráautomaticamente resolvido para o IP da rede IP 172.17.0.0/16que o container do mysql obteve na sua inicialização.

Pra testar, utilizaremos a funcionalidade exec para rodaro comando dentro de um container já existente. Para tal,usaremos o nome do container como parâmetro do comandoabaixo:

1 docker container exec -it app ping db

A ação será responsável por executar o comando “ping db”dentro do container “app”, ou seja, o container “app” enviarápacotes icmp, normalmente usado para testar conectividadeentre dois hosts, para o endereço “db”. O nome “db” é tradu-zido para o IP que o container, iniciado a partir da imagem domysql, obteve ao iniciar.

Exemplo: O container “db” iniciou primeiro e obteve o IP172.17.0.2. O container “app” iniciou em seguida e recebeu oIP 172.17.0.3. Quando o container “app” executar o comando“ping db”, na verdade, ele enviará pacotes icmp para o ende-reço 172.17.0.2.

Atenção: O nome da opção “–link” causa certaconfusão, pois não cria link de rede IP entre os

Page 59: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 53

containers, uma vez que a comunicação entreeles já é possível, mesmo sem a opção link serconfigurada. Como esclarecido no parágrafo an-terior, apenas facilita a tradução de nomes parao IP dinâmico obtido na inicialização.

Os containers configurados para essa rede terão a possibi-lidade de tráfego externo utilizando as rotas das redes IPdefinidas no docker host. Caso o docker host tenha acesso ainternet, automaticamente, os containers em questão tambémterão.

Nessa rede é possível expor portas dos containers para todosos ativos com acesso ao docker host.

None

Essa rede tem como objetivo isolar o container para comuni-cações externas. A rede não recebe qualquer interface paracomunicação externa. A única interface de rede IP será alocalhost.

Essa rede, normalmente, é utilizada para containers quemani-pulam apenas arquivos, sem necessidade de enviá-los via redepara outro local. (Ex.: container de backup utiliza os volumesde container de banco de dados para realizar o dump e, seráusado no processo de retenção dos dados).

Page 60: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 54

Exemplo de uso da rede none

Em caso de dúvida sobre utilização de volumes no dockervisite esse artigo56 e entenda mais sobre armazenamento dodocker.

Host

Essa rede tem como objetivo entregar para o container todasas interfaces existentes no docker host. De certa forma, podeagilizar a entrega dos pacotes, uma vez que não há bridgeno caminho das mensagens. Mas normalmente esse overheadé mínimo e o uso de uma brigde pode ser importante parasegurança e gerencia do seu tráfego.

Redes definidas pelo usuário

O docker possibilita que o usuário crie redes. Essas redes sãoassociadas ao elemento que o docker chama de driver de rede.

Cada rede criada por usuário deve estar associada a umdeterminado driver. E, caso você não crie seu próprio driver,deve escolher entre os drivers disponibilizados pelo docker:

56http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/

Page 61: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 55

Bridge

Essa é o driver de rede mais simples de utilizar, pois demandapouca configuração. A rede criada por usuário utilizando odriver bridge assemelha-se bastante à rede padrão do dockerdenominada “bridge”.

Mais um ponto quemerece atenção: o docker temuma rede padrão chamada “bridge” que utilizaum driver também chamado de “bridge“. Talvez,por conta disso, a confusão só aumente. Mas éimportante deixar claro que são distintas.

As redes criadas pelo usuário com o driver bridge tem todasas funcionalidades descritas na rede padrão, chamada bridge.Porém, com funcionalidades adicionais.

Dentre uma das funcionalidades: a rede criada pelo usuárionão precisa mais utilizar a opção antiga “–link”. Pois, todarede criada pelo usuário com o driver bridge poderá utilizar oDNS interno do Docker que, associa, automaticamente, todosos nomes de containers dessa rede para seus respectivos IPsda rede IP correspondente.

Para deixar mais claro: todos os containers que estiveremutilizando a rede padrão bridge não poderão usufruir da fun-cionalidade de DNS interno do Docker. Caso utilize essa rede,é preciso especificar a opção legada “–link” para tradução dosnomes em endereços IPs dinamicamente alocados no docker.

Para exemplificar a utilização de rede criada por usuáriovamos criar a rede chamada isolated_nw com o driver bridge:

Page 62: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 56

1 docker network create --driver bridge isolated_nw

Agora verificamos a rede:

1 docker network list

O resultado deve ser:

Agora iniciamos um container na rede isolated_nw:

1 docker container run -itd --net isolated_nw alpin\

2 e sh

Rede isolada

Page 63: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 57

Vale salientar: um container que está em determinada redenão acessa outro container que está em outra rede.Mesmo quevocê conheça o IP de destino. Para que um container acesseoutro container de outra rede, é necessário que a origem estejapresente nas duas redes que deseja alcançar.

Os containers que estão na rede isolated_nw podem exporsuas portas no docker host e essas portas podem ser acessadastanto por containers externos a rede, chamada isolated_nw,como máquinas externas com acesso ao docker host.

Rede isolada publicando portas

Para descobrir quais containers estão associados a uma deter-minada rede, execute o comando abaixo:

Page 64: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 58

1 docker network inspect isolated_nw

O resultado deve ser:

Dentro da sessão “Containers” é possível verificar quais con-tainers fazem parte dessa rede. Todos os containers que esti-verem na mesma rede poderão se comunicar utilizando ape-nas seus respectivos nomes. Como podemos ver no exemploacima, caso um container novo acesse a rede isolated_nw, elepoderá acessar o container amazing_noyce utilizando apenasseu nome.

Overlay

O driver overlay permite comunicação entre hosts docker,utilizando-o os containers de um determinado host docker po-derão acessar, nativamente, containers de um outro ambientedocker.

Esse driver demanda configuração mais complexa, sendoassim, trataremos do detalhamento em outra oportunidade.

Page 65: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Entendendo a rede no Docker 59

Utilizando redes no docker compose

O assunto merece um artigo exclusivo. Então, apenas in-formaremos um link interessante57 para referência sobre oassunto.

Conclusão

Percebemos que a utilização de redes definidas por usuáriotorna obsoleta a utilização da opção “–link”, bem como viabi-liza novo serviço de DNS interno do docker, o que facilita paraquem se propõe a manter uma infraestrutura docker grandee complexa, assim como viabilizar o isolamento de rede dosseus serviços.

Conhecer e utilizar bem as tecnologias novas é uma boaprática que evita problemas futuros e facilita a construção emanutenção de projetos grandes e complexos.

57https://docs.docker.com/compose/networking/

Page 66: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker emmúltiplos ambientesDocker host é o nome do ativo responsável por gerenciar am-bientes Docker, nesse capítulo mostraremos como é possívelcriá-los e gerenciá-los em infraestruturas distintas, tais comomáquina virtual, nuvem e máquina física.

Docker machine58 é a ferramenta usada para essa gerênciadistribuída, permite a instalação e gerência de docker hostsde forma fácil e direta.

Essa ferramenta é muito usada por usuários de sistema ope-racional “não linux”, como demonstraremos ainda, mas suafunção não limita-se a esse fim, pois também é bastante usadapara provisionar e gerenciar infraestrutura Docker na nuvem,tal como AWS, Digital Ocean e Openstack.

58https://docs.docker.com/machine/

Page 67: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 61

Como funciona

Antes de explicar como utilizar o docker machine, precisamosreforçar o conhecimento sobre a arquitetura do Docker.

Como demonstra a imagem acima, a utilização do Dockerdivide-se em dois serviços: o que roda em modo daemon,

Page 68: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 62

em background, chamado de Docker Host, responsável pelaviabilização dos containers no kernel Linux; e, o cliente,que chamaremos de Docker client, responsável por recebercomandos do usuário e traduzir em gerência doDocker Host.

Cada Docker client é configurado para se conectar a deter-minado Docker host e nesse momento o Docker machineentra em ação, pois viabiliza a automatização da escolha deconfiguração de acesso do Docker client a distintos Dockerhost.

O Docker machine possibilita utilizar diversos ambientesdistintos apenas modificando a configuração do cliente parao Docker host desejado: basicamente modificar algumasvariáveis de ambiente. Segue exemplo:

1 export DOCKER_TLS_VERIFY="1"

2 export DOCKER_HOST="tcp://192.168.99.100:2376"

3 export DOCKER_CERT_PATH="/Users/gomex/.docker/mac\

4 hine/machines/default"

5 export DOCKER_MACHINE_NAME="default"

Modificando essas quatro variáveis, o Docker client poderáutilizar um ambiente diferente rapidamente e sem precisarreiniciar qualquer serviço.

Criando ambiente

ODocker machine serve principalmente para criar ambientes,futuramente geridos por ele na troca automatizada de con-texto de configuração, através da mudança de variáveis deambiente, como explicado anteriormente.

Page 69: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 63

Para criar o ambiente é necessário verificar se a infraestruturaque deseja criar tem algum driver com suporte a esse processo.Segue a lista de drivers disponíveis59.

Máquina virtual

Para esse exemplo, usaremos o driver mais utilizado, o virtu-albox60, ou seja, precisamos de um virtualbox61 instalado nanossa estação para que esse driver funcione adequadamente.

Antes de criar o ambiente vamos entender como funciona ocomando de criação do docker machine:

docker-machine create –driver=<nome do driver> <nome doambiente>

Para o driver virtualbox temos alguns parâmetros que podemser utilizados:

Parâmetro Explicação

–virtualbox-memory Especifica a quantidadede memória RAM que oambiente pode utilizar. Ovalor padrão é 1024MB.(Sempre em MB)

–virtualbox-cpu-count Especifica a quantidadede núcleos de CPU queesse ambiente podeutilizar. O valor padrão é1

59https://docs.docker.com/machine/drivers/60https://docs.docker.com/machine/drivers/virtualbox/61https://www.virtualbox.org/

Page 70: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 64

Parâmetro Explicação

–virtualbox-disk-size Especifica o tamanho dodisco que esse ambientepode utilizar. O valorpadrão é 20000MB(Sempre em MB)

Como teste utilizamos o seguinte comando:

1 docker-machine create --driver=virtualbox --virtu\

2 albox-disk-size 30000 teste-virtualbox

O resultado desse comando é a criação de uma máquinavirtual no virtualbox. A máquina terá 30GB de espaço emdisco, 1 núcleo e 1GB de memória RAM.

Para validar se o processo aconteceu como esperado, bastautilizar o seguinte comando:

1 docker-machine ls

O comando acima é responsável por listar todos os ambientesque podem ser usados a partir da estação cliente.

Pra mudar de cliente basta utilizar o comando:

1 eval $(docker-machine env teste-virtualbox)

Executando o comando ls será possível verificar qual ambi-ente está ativo:

Page 71: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 65

1 docker-machine ls

Inicie um container de teste pra testar o novo ambiente

1 docker container run hello-world

Caso deseje mudar para outro ambiente, basta digitar o co-mando abaixo, usando o nome do ambiente desejado:

1 eval $(docker-machine env <ambiente>)

Caso deseje desligar o ambiente, utilize o comando:

1 docker-machine stop teste-virtualbox

Caso deseje iniciar o ambiente, utilize o comando:

1 docker-machine start teste-virtualbox

Caso deseje remover o ambiente, utilize o comando:

1 docker-machine rm teste-virtualbox

Tratamento de problema conhecido: caso esteja utilizandoDocker-machine no MacOS e por algum motivo a estaçãohiberne quando o ambiente virtualbox tenha iniciado, é pos-sível que, no retorno da hibernação, o Docker host apresenteproblemas na comunicação com a internet. Orientamos a,sempre que passar por problemas de conectividade no Dockerhost com driver virtualbox, desligue o ambiente e reiniciecomo medida de contorno.

Page 72: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 66

Nuvem

Para esse exemplo usamos o driver da nuvem mais utilizada,AWS62. Para tanto, precisamos de uma conta na AWS para queesse driver63 funcione adequadamente.

É necessário que suas credenciais estejamno arquivo∼/.aws/credentialsda seguinte forma:

1 [default]

2 aws_access_key_id = AKID1234567890

3 aws_secret_access_key = MY-SECRET-KEY

Caso não deseje colocar essas informações em arquivo, vocêpode especificar via variáveis de ambiente:

1 export AWS_ACCESS_KEY_ID=AKID1234567890

2 export AWS_SECRET_ACCESS_KEY=MY-SECRET-KEY

Você pode encontrar mais informações sobre credencial AWSnesse artigo64.

Quando criamos um ambiente utilizando o comando docker-machine create, o mesmo é traduzido para AWS na criaçãouma instância EC265 e, em seguida é instalado todos ossoftwares necessários, automaticamente, no novo ambiente.

Os parâmetros mais utilizados na criação desse ambiente são:

62http://aws.amazon.com/63https://docs.docker.com/machine/drivers/aws/64http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-

Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs65https://aws.amazon.com/ec2/

Page 73: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 67

Parâmetro Explicação

–amazonec2-region Informa qual região daAWS é utilizada parahospedar seu ambiente.O valor padrão éus-east-1.

–amazonec2-zone É a letra que representaa zona utilizada. Ovalor padrão é “a”

–amazonec2-subnet-id Informa qual asub-rede utilizada nessainstância EC2. Precisater sido criadapreviamente.

–amazonec2-security-group

Informa qual securitygroup é utilizado nessainstância EC2. Precisater sido criadopreviamente

–amazonec2-use-private-address

Será criada umainterface com IPprivado, pois pordefault, só especificauma interface com IPpúblico

–amazonec2-vpc-id Informa qual o ID doVPC desejado para essainstância EC2. Precisater sido criadopreviamente.

Como exemplo, usamos o seguinte comando de criação doambiente:

Page 74: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 68

1 docker-machine create --driver amazonec2 --amazon\

2 ec2-zone a --amazonec2-subnet-id subnet-5d3dc191 \

3 --amazonec2-security-group docker-host --amazonec\

4 2-use-private-address --amazonec2-vpc-id vpc-c1d3\

5 3dc7 teste-aws

Após executar o comando, basta esperar finalizar, é normaldemorar um pouco.

Para testar o sucesso da ação, execute o comando abaixo:

1 docker-machine ls

Verifique se o ambiente chamado teste-aws existe na lista,caso positivo, utilize o comando abaixo para mudar o ambi-ente:

1 eval $(docker-machine env teste-aws)

Inicie um container de teste pra verificar o novo ambiente

1 docker container run hello-world

Caso deseje desligar o ambiente, utilize o comando:

1 docker-machine stop teste-aws

Caso deseje iniciar o ambiente, utilize o comando:

Page 75: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Utilizando Docker em múltiplos ambientes 69

1 docker-machine start teste-aws

Caso deseje remover o ambiente, utilize o comando:

1 docker-machine rm teste-aws

Após removido do local, automaticamente removerá a instân-cia EC2, provisionada na AWS.

Page 76: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiploscontainers docker comDocker ComposeEsse artigo tem como objetivo explicar de forma detalhada, ecom exemplos, como funciona o processo de gerenciamentode múltiplos containers Docker, pois a medida que sua confi-ança em utilizar Docker aumenta, sua necessidade de utilizarum maior número de containers ao mesmo tempo cresce namesma proporção, e seguir a boa prática de manter apenasum serviço por container comumente resulta em algumademanda extra.

Page 77: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 71

Geralmente com o aumento do número de containers emexecução, fica evidente a necessidade de um melhor geren-ciamento da sua comunicação, pois é ideal que os serviçosconsigam trocar dados entre os containers quando necessário,ou seja, você precisa lidar com a rede desse novo ambiente.

Imagine o trabalho que seria executar algumas dezenas decontainers manualmente na linha de comando, um por ume todos seus parâmetros necessários, suas configurações derede entre containers, volumes e afins. Pode parar de ima-ginar, pois isso não será mais necessário. Para atender essademanda de gerenciamento de múltiplos containers a solução

Page 78: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 72

é o Docker Compose66.

Docker compose é uma ferramenta para definição e execuçãode múltiplos containers Docker. Com ela é possível configurartodos os parâmetros necessários para executar cada containera partir de um arquivo de definição. Dentro desse arquivo,definimos cada container como serviço, ou seja, sempre queesse texto citar serviço de agora em diante, imagine que é adefinição que será usada para iniciar um container, tal comoportas expostas, variáveis de ambiente e afins.

Com o Docker Compose podemos também especificar quaisvolumes e rede serão criados para serem utilizados nosparâmetros dos serviços, ou seja, isso quer dizer que nãopreciso criá-los manualmente para que os serviços utilizemrecursos adicionais de rede e volume.

O arquivo de definição do Docker Compose é o local onde éespecificado todo o ambiente (rede, volume e serviços), ele éescrito seguindo o formato YAML67. Esse arquivo por padrãotem como nome docker-compose.yml68.

Anatomia do docker-compose.yml

O padrão YAML utiliza a indentação como separador dosblocos de códigos das definições, por conta disso o uso daindentação é um fator muito importante, ou seja, caso nãoa utilize corretamente, o docker-compose falhará em suaexecução.

Cada linha desse arquivo pode ser definida com uma chavevalor ou uma lista. Vamos aos exemplos pra ficar mais claro

66https://docs.docker.com/compose/overview/67https://en.wikipedia.org/wiki/YAML68https://docs.docker.com/compose/compose-file/

Page 79: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 73

a explicação:

1 version: '2'

2 services:

3 web:

4 build: .

5 context: ./dir

6 dockerfile: Dockerfile-alternate

7 args:

8 versao: 1

9 ports:

10 - "5000:5000"

11 redis:

12 image: redis

No arquivo acima temos a primeira linha que define a versãodo docker-compose.yml, que no nosso caso usaremos aversão mais atual do momento, caso tenha interesse em sabera diferença entre as versões possíveis, veja esse link69.

1 version: '2'

No mesmo nível de indentação temos services, que define oinício do bloco de serviços que serão definidos logo abaixo.

1 version: '2'

2 services:

No segundo nível de indentação (aqui feito com dois espaços)temos o nome do primeiro serviço desse arquivo, que recebeo nome de web. Ele abre o bloco de definições do serviço,ou seja, a partir do próximo nível de indentação, tudo que fordefinido faz parte desse serviço.

69https://docs.docker.com/compose/compose-file/#versioning

Page 80: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 74

1 version: '2'

2 services:

3 web:

No próximo nível de indentação (feito novamente com maisdois espaços) temos a primeira definição do serviço web,que nesse caso é o build70 que informa que esse serviço serácriado não a partir de uma imagem pronta, mas que seránecessário construir sua imagem antes de sua execução. Seriao equivalente ao comando docker build71. Ele também abreum novo bloco de código para parametrizar o funcionamentodessa construção da imagem.

1 version: '2'

2 services:

3 web:

4 build: .

No próximo nível de indentação (feito novamente com maisdois espaços) temos um parâmetro do build, que nesse casoé o context. Ele é responsável por informar qual contexto dearquivos será usado para construir a imagem em questão, ouseja, apenas arquivos existentes dentro dessa pasta poderãoser usados na construção da imagem. O contexto escolhido foio “./dir”, ou seja, isso indica que uma pasta chamada dir, quese encontra no mesmo nível de sistema de arquivo do docker-compose.yml ou do lugar onde esse comando será executado,será usada como contexto da criação dessa imagem. Quandologo após da chave um valor é fornecido, isso indica quenenhum bloco de código será aberto.

70https://docs.docker.com/compose/reference/build/71https://docs.docker.com/engine/reference/commandline/build/

Page 81: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 75

1 build: .

2 context: ./dir

No mesmo nível de indentação da definição context, ouseja, ainda dentro do bloco de definição do build, temos odockerfile, ele indica o nome do arquivo que será usadopara construção da imagem em questão. Seria o equivalenteao parâmetro “-f”72 do comando docker build. Caso essadefinição não existisse, o docker-compose procuraria porpadrão por um arquivo chamado Dockerfile dentro da pastainformada no context.

1 build: .

2 context: ./dir

3 dockerfile: Dockerfile-alternate

No mesmo nível de indentação da definição dockerfile, ouseja, ainda dentro do bloco de definição do build, temos oargs, ele define os argumentos que serão usados pelo Doc-kerfile, seria o equivalente ao parâmetro “–build-args”73 docomando docker build. Como não foi informado o seu valorna mesma linha, fica evidente que ela abre um novo bloco decódigo.

No próximo nível de indentação (feito novamente com maisdois espaços) temos a chave “versao” e o valor “1”, ou seja,como essa definição faz parte do bloco de código args, essachave valor é o único argumento que será passado para oDockerfile, ou seja, o arquivo Dockerfile em questão deveráestar preparado para receber esse argumento ou ele se perderána construção da imagem.

72https://docs.docker.com/engine/reference/commandline/build/#specify-dockerfile-f73https://docs.docker.com/engine/reference/commandline/build/#set-build-time-

variables-build-arg

Page 82: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 76

1 build: .

2 context: ./dir

3 dockerfile: Dockerfile-alternate

4 args:

5 versao: 1

Voltando dois níveis de indentação (quatro espaços a menosem relação a linha anterior) temos a definição ports, queseria o equivalente ao parâmetro “-p”74 do comando dockercontainer run. Ele define qual porta do container será expostano Docker host. Que no nosso caso será a porta *5000 docontainer, com a 5000 do Docker host.

1 web:

2 build: .

3 ...

4 ports:

5 - "5000:5000"

Voltando um nível de indentação (dois espaços a menos emrelação a linha anterior) saímos do bloco de código do serviçoweb, isso indica que nenhuma definição informada nessalinha será aplicada a esse serviço, ou seja, precisamos iniciarum bloco de código de um serviço novo, que no nosso casoserá com nome de redis.

1 redis:

2 image: redis

74https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port-p-expose

Page 83: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Gerenciando múltiplos containers docker com Docker Compose 77

No próximo nível de indentação (feito novamente com maisdois espaços) temos a primeira definição do serviço redis, quenesse caso é o image que é responsável por informar qualimagem será usada para iniciar esse container. Essa imagemserá obtida do repositório configurado no Docker host, quepor padrão é o hub.docker.com75.

Executando o docker compose

Após entender e criar seu próprio arquivo de definiçãoprecisamos saber como gerenciá-lo e para isso utilizaremos obinário docker-compose, que entre várias opções de uso temosas seguintes mais comuns:

• build : Usada para construir todas as imagens dosserviços que estão descritos com a definição build emseu bloco de código.

• up : Iniciar todos os serviços que estão no arquivodocker-compose.yml

• stop : Parar todos os serviços que estão no arquivodocker-compose.yml

• ps : Listar todos os serviços que foram iniciados a partirdo arquivo docker-compose.yml

Para outras opções visite sua documentação76.

75https://hub.docker.com/76https://docs.docker.com/compose/reference/

Page 84: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker semGNU/LinuxEsse artigo tem como objetivo explicar de forma detalhada,e com exemplos, o uso de Docker em estações MacOS eWindows.

Docker Toolbox

Esse texto é para pessoas que já sabem sobre Docker, masainda não sabem como o Docker pode ser utilizado a partirde uma estação “não linux”.

Page 85: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 79

Como já dissemos, o Docker utiliza recursos específicos dosistema operacional hospedeiro. Hoje temos suporte para ossistemas operacionais Windows e GNU/Linux. Significa quenão é possível iniciar containers Docker em estação MacOS,por exemplo.

Mas não se preocupe, caso você não utilize GNU/Linux, ouWindows, como sistema operacional, ainda é possível fazeruso dessa tecnologia, sem, necessariamente, executá-la em seucomputador.

Vale salientar que containers e imagens Docker criados noWindows, não funcionarão em um GNU/Linux, por contada dependência do sistema operacional mencionado anteri-ormente.

É possível utilizar o Docker no MacOS e Windows a partir deduas maneiras:

• Toolbox• Docker For Mac/Windows

Por ser mais complexa, e assim demandar de um contextomaior, trataremos nesse capítulo apenas sobre a instalação econfiguração doDocker Toolbox77. Essa solução, é na verdade,uma abstração para instalação de todo ambiente necessáriopara uso do Docker a partir de uma estação MacOS ouWindows.

A instalação é simples: tanto no Windows, como no Ma-cOS, basta baixar o instalador correspondente nesse site78 eexecutá-lo seguindo os passos descritos nas telas.

77https://www.docker.com/products/docker-toolbox78https://www.docker.com/products/docker-toolbox

Page 86: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 80

Os softwares instalados na estação - MacOS ou Windows - apartir do pacote Docker Toolbox são:

• Virtualbox79

• Docker machine80

• Docker client81

• Docker compose82

• Kitematic83

Docker Machine é a ferramenta que possibilita criar e manterambientes Docker emmáquinas virtuais, ambientes de nuveme, até mesmo, em máquina física. Mas nesse tópico, abordare-mos apenas máquina virtual com virtualbox.

Após instalar o Docker Toolbox é muito simples criar umambiente Docker com máquina virtual usando o DockerMachine.

Primeiro verificamos se não existem máquinas virtuais comDocker instaladas em seu ambiente:

1 docker-machine ls

O comando acima mostra apenas ambientes criados e manti-dos por seu Docker Machine. É possível que, após instalar oDocker Toolbox, você não encontre máquina alguma criada.Nesses casos, utilizamos o comando abaixo para criar a má-quina:

79https://www.virtualbox.org/80https://docs.docker.com/machine/overview/81https://docs.docker.com/82https://docs.docker.com/compose/overview/83https://docs.docker.com/kitematic/userguide/

Page 87: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 81

1 docker-machine create --driver virtualbox default

Arquitetura do Docker Toolbox

O comando cria um ambiente denominado “default”. Naverdade é uma máquina virtual (“Linux VM” que aparecena imagem) criada no virtualbox. Com o comando abaixo épossível visualizar a máquina criada:

1 docker-machine ls

O retorno deve ser algo parecido com isto:

Umamáquina virtual foi criada, dentro dela temos um sistemaoperacional GNU/Linux com Docker Host instalado. Esseserviço Docker está escutando na porta TCP 2376 do endereço192.168.99.100. Essa interface utiliza uma rede específica entreseu computador e as máquinas do virtualbox.

Para desligar a máquina virtual, basta executar o comandoabaixo:

Page 88: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 82

1 docker-machine stop default

Para iniciar, novamente, a máquina, basta executar o co-mando:

1 docker-machine start default

O comando “start” é responsável apenas por iniciar a má-quina. É necessário fazer com que os aplicativos de controle doDocker, instalados na estação, possam se conectar à máquinavirtual criada no virtualbox com o comando “docker-machinecreate”.

Os aplicativos de controle (Docker e Docker-compose) fazemuso de variáveis de ambiente para configurar qual DockerHost será utilizado. O comando abaixo facilita o trabalho deaplicar todas as variáveis corretamente:

1 docker-machine env default

O resultado desse comando no MacOS é:

Como vemos, informa o que pode ser feito para configurartodas as variáveis. Você pode copiar as quatros primeiraslinhas, que começam com “export”, e colar no terminal ou,pegar apenas a última linha sem o “#” do início e executar nalinha de comando:

Page 89: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 83

1 eval $(docker-machine env default)

Agora os aplicativos de controle (Docker e Docker-Compose)estão aptos a utilizar o Docker Host a partir da conexão feitano serviço do IP 192.168.99.100 - máquina criada com o co-mando “docker-machine create” mencionados anteriormente.

Para testar, listamos os containers em execução nesse DockerHost com o comando:

1 docker ps

Executado na linha de comando do MacOS ouWindows, essecliente do Docker se conecta à máquina virtual que, aquichamamos de “Linux VM”, e solicita a lista de containers emexecução no Docker Host remoto.

Iniciamos um container com o comando abaixo:

1 docker container run -itd alpine sh

Agora, verificamos novamente, a lista de containers em exe-cução:

1 docker ps

Podemos ver que o container criado a partir da imagem“alpine” está em execução. Vale salientar que esse processoé executado no Docker Host, na máquina criada dentro dovirtualbox que, nesse exemplo, tem o ip 192.168.99.100.

Para verificar o endereço IP da máquina, basta executar ocomando abaixo:

Page 90: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 84

1 docker-machine ip

Caso o container exponha alguma porta para o Docker Host,seja via parâmetro “-p” do comando “docker container run-p porta_host:porta_container” ou via parâmetro “ports” dodocker-compose.yml, vale lembrar que o IP para acessar oserviço exposto é o endereço IP do Docker Host que, noexemplo, é “192.168.99.100”.

Nesse momento, você deve estar se perguntando: como épossível mapear uma pasta da estação “não-linux” para dentrode um container? Aqui entra um novo artíficio doDocker paracontornar esse problema.

Toda máquina criada com o driver “virtualbox”, automatica-mente, cria um mapeamento do tipo “pastas compartilhadasdo virtualbox” da pasta de usuários para a raiz do DockerHost.

Para visualizar esse mapeamento, acessamos a máquina vir-tual que acabamos de criar nos passos anteriores:

1 docker-machine ssh default

No console da máquina GNU/Linux digite os seguintes co-mandos:

1 sudo su

2 mount | grep vboxsf

O vboxsf84 é um sistema de arquivo usado pelo virtualboxpara montar volumes compartilhados da estação usada para

84https://help.ubuntu.com/community/VirtualBox/SharedFolders

Page 91: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 85

instalar o virtualbox. Ou seja, utilizando o recurso de pastacompartilhada, é possível montar a pasta /Users do MacOSna pasta /Users da máquina virtual do Docker Host.

Todo conteúdo existente na pasta /Users/SeuUsuario do Ma-cOS, será acessível na pasta /Users/SeuUsuario da máquinaGNU/Linux que atua como Docker Host no exemplo apresen-tado. Caso efetue a montagem da pasta /Users/SeuUsuario/-MeuCodigo para dentro do container, o dado a ser montado éo mesmo da estação e nada precisa ser feito para replicar essecódigo para dentro do Docker Host.

Vamos testar. Crie um arquivo dentro da pasta de usuário:

1 touch teste

Iniciamos um container e mapeamos a pasta atual dentro dele:

1 docker container run -itd -v "$PWD:/tmp" --name t\

2 este alpine sh

No comando acima, iniciamos um container que será nome-ado como “teste” e terá mapeado a pasta atual (a variávelPWD indica o endereço atual no MacOS) na pasta /tmp,dentro do container.

Verificamos se o arquivo que acabamos de criar está dentrodo container:

1 docker container exec teste ls /tmp/teste

A linha acima executou o comando “ls /tmp/teste” dentro docontainer nomeado “teste”, criado no passo anterior.

Agora acesse o Docker Host com o comando abaixo, e verifi-que se o arquivo teste se encontra na pasta de usuário:

Page 92: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Como usar Docker sem GNU/Linux 86

1 docker-machine ssh default

Tudo pode ser feito automaticamente? Claro que sim!

Agora que já sabe como fazer manualmente, se precisarinstalar o Docker Toolbox em uma máquina nova e nãolembrar os comandos para criar a nova máquina ou, simples-mente como aprontar o ambiente para uso, basta executar oprograma “Docker Quickstart Terminal”. Ele fará o trabalhoautomaticamente. Caso não exista máquina criada, ele criauma chamada “default”. Caso a máquina já tenha sido cri-ada, automaticamente configura suas variáveis de ambientee deixa apto para utilizar o Docker Host remoto a partir dosaplicativos de controle (Docker e Docker-Compose).

Page 93: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Transformando suaaplicação em containerEvoluímos continuamente para entregar aplicações cada vezmelhores, em menor tempo, replicáveis e escaláveis. Entre-tanto, os esforços e aprendizados para atingir esse nível dematuridade muitas vezes não são simples de serem alcança-dos.

Atualmente, notamos o surgimento de várias opções de pla-taformas para facilitar a implantação, configuração e esca-labilidade das aplicações que desenvolvemos. Porém, paramelhorar nossa maturidade, não podemos depender apenasda plataforma, precisamos construir nossa aplicação seguindoboas práticas.

Visando sugerir uma série de boas práticas comuns a apli-cações web modernas, alguns desenvolvedores do Heroku85

escreveram o 12Factor app86, baseado na larga experiência emdesenvolvimento desse tipo de aplicação.

85https://www.heroku.com/86http://12factor.net/pt_br/

Page 94: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Transformando sua aplicação em container 88

“The Twelve-Factor app” (12factor) é um manifesto com umasérie de boas práticas para construção de software utilizandoformatos declarativos de automação, maximizando portabi-lidade e minimizando divergências entre ambientes de exe-cução, permitindo a implantação em plataformas de nuvemmodernas e facilitando a escalabilidade. Assim, aplicaçõessão construídas sem manter estado (stateless) e conectadasa qualquer combinação de serviços de infraestrutura pararetenção de dados (banco de dados, fila, memória cache eafins).

Nesse capítulo, falaremos sobre criação de aplicações comimagens Docker baseados no 12factor app. A ideia é demons-trar as melhores práticas para realizar a criação de infraes-trutura para suportar, empacotar e disponibilizar a aplicaçãocom alto nível de maturidade e agilidade.

O uso do 12factor com Docker é uma combinação perfeita,pois muitos dos recursos do Docker são melhores aproveita-dos caso a aplicação tenha sido pensada para tal. Dessa forma,daremos uma ideia de como aproveitar todo potencial da suasolução.

Como aplicação exemplo, teremos um serviço HTTP, escritoem python, que exibe quantas vezes foi acessada. Essa in-formação é armazenada através de contador numa instânciaRedis.

Agora vamos às boas práticas!

Page 95: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Base de códigoComo objetivo de facilitar o controle dasmudanças de código,viabilizando a rastreabilidade das alterações, essa boa práticaindica que cada aplicação deve ter apenas uma base de códigoe, partindo dessa, ser implantada em distintos ambientes. Valesalientar que essa prática também é parte das práticas deContinuous Integration (CI87). Tradicionalmente, a maioriados sistemas de integração contínua tem, como ponto de par-tida, uma base de código que é construída e, posteriormente,implantada em desenvolvimento, teste e produção.

Para essa explicação, usamos o sistema de controle de versãoGit e o serviço de hospedagem Github. Criamos e disponibi-lizamos um repositório88 de exemplo.

Perceba que todo código está dentro do repositório, organi-zado por prática em cada pasta, para facilitar a reprodução.Lembre-se de entrar na pasta correspondente a cada boaprática apresentada.

O Docker tem possibilidade de utilizar variável de ambientepara parametrização da infraestrutura. Sendo assim, a mesmaaplicação terá comportamento distinto com base no valor dasvariáveis de ambiente.

Aqui usamos o Docker Compose para realizar a composiçãode diferentes serviços pertinentes para a aplicação em tempode execução. Desse modo, devemos definir a configuraçãodesses distintos serviços e a forma como se comunicam.

87https://www.thoughtworks.com/continuous-integration88https://github.com/gomex/exemplo-12factor-docker.git

Page 96: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Base de código 90

Posteriormente, mais precisamente na terceira boa prática,chamadaConfiguração, desse compêndio de sugestões, trata-remos com mais detalhes sobre parametrização da aplicação.Por ora, apenas aplicamos opções via variável de ambientepara a arquitetura, ao invés de, utilizar internamente nocódigo da aplicação.

Para configurar o ambiente de desenvolvimento para o exem-plo apresentado, criamos o arquivo docker-compose.yml:

Page 97: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Base de código 91

1 version: '2'

2 services:

3 web:

4 build: .

5 ports:

6 - "5000:5000"

7 volumes:

8 - .:/code

9 labels:

10 - 'app.environment=${ENV_APP}'

11 redis:

12 image: redis

13 volumes:

14 - dados_${ENV_APP}:/data

15 labels:

16 - 'app.environment=${ENV_APP}'

Podemos notar que o serviço “redis” é utilizado a partir daimagem oficial “redis”, sem modificação. E o serviço web égerado a partir da construção de uma imagem Docker.

Para a contrução da imagem Docker do serviço web, criamoso seguinte Dockerfile, usando como base a imagem oficial dopython 2.7:

1 FROM python:2.7

2 COPY requirements.txt requirements.txt

3 RUN pip install -r requirements.txt

4 ADD . /code

5 WORKDIR /code

6 CMD python app.py

De posse de todos os arquivos na mesma pasta, iniciamos oambiente com o seguinte comando:

Page 98: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Base de código 92

1 export ENV_APP=devel ; docker-compose -p $ENV_APP\

2 up -d

Como podemos perceber no exemplo desse capítulo, a variá-vel de ambiente ENV_APP define qual volume é usado parapersistir os dados que são enviados pela aplicação web. Ouseja, com base na mudança dessa opção, teremos o serviçorodando com comportamento diferente, mas sempre a partirdo mesmo código. Dessa forma, segue o conceito da primeiraboa prática.

Page 99: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

DependênciaSeguindo a lista do modelo 12factor89, logo após a base decódigo que tratamos nesse artigo90, temos a “Dependência”como segunda boa prática.

Essa boa prática sugere a declaração de todas as dependênciasnecessárias para executar o código. Você não deve assumirque algum componente já está previamente instalado no ativoresponsável por hospedar a aplicação.

89http://12factor.net/90http://techfree.com.br/2016/06/dockerizando-aplicacoes-base-de-codigo/

Page 100: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dependência 94

Para viabilizar o “sonho” da portabilidade, precisamos geren-ciar corretamente as dependências da aplicação em questão,isso indica que devemos, também, evitar a necessidade de tra-balho manual na preparação da infraestrutura que dá suporteà aplicação.

Automatizar o processo de instalação de dependência é ogrande segredo do sucesso para atender essa boa prática. Casoa instalação da infraestrutura não seja, suficientemente, auto-mática para viabilizar a inicialização sem erros, o atendimentoda boa prática fica prejudicado.

Esses procedimentos, automatizados, colaboram com amanu-tenção da integridade do processo, pois, o nome dos pacotesde dependências e respectivas versões, estão especificados noarquivo localizado no mesmo repositório do código que, porsua vez, é rastreado emum sistema de controle de versão. Comisso, podemos concluir que nada é modificado sem o devidoregistro.

O Docker se encaixa perfeitamente na boa prática. É possívelentregar um perfil mínimo de infraestrutura para a aplicação.Por sua vez, a declaração explícita das dependências, para quea aplicação funcione no ambiente, faz-se necessária.

A aplicação do exemplo, escrita em Python, como verificamosem parte do código abaixo, necessita de duas bibliotecas parafuncionar corretamente:

1 from flask import Flask

2 from redis import Redis

Essas duas dependências estão especificadas no arquivo requi-rements.txt e, esse arquivo é usado como parâmetro do PIP.

Page 101: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dependência 95

“O PIP é um sistema de gerenciamento de pacotes usado parainstalar e gerenciar pacotes de software escritos na linguagemde programação Python”. (Wikipedia)

O comando PIP é usado, junto ao arquivo requirements.txt,na criação da imagem, como demonstrado no Dockerfile daboa prática anterior (codebase):

1 FROM python:2.7

2 ADD requirements.txt requirements.txt

3 RUN pip install -r requirements.txt

4 ADD . /code

5 WORKDIR /code

6 CMD python app.py

Perceba que um dos passos do Dockerfile é instalar as depen-dências descritas no arquivo requirements.txt com o gerenci-ador de pacotes PIP do Python. Veja o conteúdo do arquivorequirements.txt:

1 flask==0.11.1

2 redis==2.10.5

É importante salientar a necessidade de especificar as versõesde cada dependência, pois, como no modelo de contêiner,as imagens podem ser construídas a qualquer momento. Éimportante saber qual versão específica a aplicação precisa.Caso contrário, podemos encontrar problemas com compati-bilidade se uma das dependências atualizar e não permaneercompatível com a composição completa das outras dependên-cias e a aplicação que a utiliza.

Page 102: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dependência 96

Para acessar o código descrito aqui, baixe o repositório91 eacesse a pasta “factor2“.

Outro resultado positivo do uso da boa prática é a simplifica-ção da utilização do código por outro desenvolvedor. Um novoprogramador pode verificar, nos arquivos de dependências,quais os pré-requisitos para a aplicação executar, assim comoexecutar o ambiente sem necessidade de seguir a extensadocumentação que, raramente, é atualizada.

Usando o Docker é possível configurar, automaticamente, onecessário para rodar o código da aplicação, seguindo a boaprática perfeitamente.

91https://github.com/gomex/exemplo-12factor-docker

Page 103: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

ConfiguraçõesSeguindo a lista do modelo 12factor92, “Configurações” éterceira boa prática.

Quando estamos criando um software, aplicamos determi-nado comportamento dentro do código e normalmente ele nãoé parametrizável. Para que a aplicação se comporte de formadiferente, será necessário mudar parte do código.

A necessidade de modificar o código para trocar o compor-tamento da aplicação, inviabiliza que, a mesma seja executana máquina (desenvolvimento) da mesma forma que é usadapara atender os usuários (produção). E, com isso, acabamoscom a possibilidade de portabilidade. E, sem portabilidade,qual a vantagem de se usar contêineres, certo?

O objetivo da boa prática é viabilizar a configuração daaplicação sem a necessidade de modificar o código. Já que,o comportamento da aplicação varia de acordo com o ambi-ente onde é executada, as configurações devem considerar oambiente.

Seguem alguns exemplo:

• Configuração de banco de dados que, normalmente, sãodiferentes entre ambientes

• Credenciais para acesso a serviços remotos (Ex.: DigitalOcean ou Twitter)

92http://12factor.net/

Page 104: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Configurações 98

• Qual nome de DNS será usado pela aplicação

Como já mencionamos, quando a configuração está estati-camente explícita no código, é necessário modificar manual-mente e efetuar novo build dos binários a cada reconfiguraçãodo sistema.

Como demonstramos na boa prática codebase, usamos umavariável de ambiente para modificar o volume que usaremosno redis. De certa forma, já estamos seguindo a boa prática,mas podemos ir além e mudarmos não somente o comporta-mento da infraestrutura, mas sim algo inerente ao código emsi.

Segue a aplicação modificada:

1 from flask import Flask

2 from redis import Redis

3 import os

4 host_run=os.environ.get('HOST_RUN', '0.0.0.0')

5 debug=os.environ.get('DEBUG', 'True')

6 app = Flask(__name__)

7 redis = Redis(host='redis', port=6379)

8 @app.route('/')

9 def hello():

10 redis.incr('hits')

11 return 'Hello World! %s times.' % redis.get('h\

12 its')

13 if __name__ == "__main__":

14 app.run(host=host_run, debug=debug)

Lembrando! Para acessar o código da prática, basta clonar esserepositório93 e acessar a pasta “factor3“.

93https://github.com/gomex/exemplo-12factor-docker

Page 105: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Configurações 99

Como podemos notar, adicionamos alguns parâmetros naconfiguração do endereço usado para iniciar a aplicação webque será parametrizada com base no valor da variável deambiente “HOST_RUN”. E, a possibilidade de efetuar, ou não,o debug da aplicação com a variável de ambiente “DEBUG“.

Vale salientar: nesse caso a variável de ambiente precisa serpassada para o contêiner, não basta ter a variável no DockerHost. É preciso enviá-la para o contêiner usando o parâmetro“-e”, caso utilize o comando “docker container run” ou, ainstrução “environment” no docker-compose.yml:

1 version: "2"

2 services:

3 web:

4 build: .

5 ports:

6 - "5000:5000"

7 volumes:

8 - .:/code

9 labels:

10 - 'app.environment=${ENV_APP}'

11 environment:

12 - HOST_RUN=${HOST_RUN}

13 - DEBUG=${DEBUG}

14 redis:

15 image: redis:3.2.1

16 volumes:

17 - dados:/data

18 labels:

19 - 'app.environment=${ENV_APP}'

20 volumes:

21 dados:

Page 106: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Configurações 100

22 external: false

Para executar o Docker-Compose, deveríamos fazer da se-guinte maneira:

1 export HOST_RUN="0.0.0.0"; export DEBUG=True ; do\

2 cker-compose up -d

No comando acima, usamos as variáveis de ambiente “HOST_-RUN” e “DEBUG” do Docker Host para enviar às variáveisde ambiente com os mesmos nomes dentro do contêinerque, por sua vez, é consumido pelo código Python. Casonão haja parâmetros, o contêiner assume os valores padrõesestipulados no código.

Essa boa prática é seguida com ajuda do Docker, pois o códigoé o mesmo e, a configuração, um anexo da solução que podeser parametrizada de maneira distinta com base no que forconfigurado nas variáveis de ambiente.

Se a aplicação crescer, as variáveis podem ser carregadasem arquivos e parametrizadas no docker-compose.yml coma opção “env_file”.

Page 107: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Serviços de ApoioSeguindo a lista do modelo 12factor94, temos “Serviços deApoio” como quarta boa prática.

Para contextualizar, “serviços de apoio” é qualquer aplicaçãoque seu código consome para operar corretamente (Ex.: bancode dados, serviço de mensagens e afins).

Com objetivo de evitar que o código seja demasiadamente de-pendente de determinada infraestrutura, a boa prática indicaque você, no momento da escrita do software, não faça dis-tinção entre serviço interno ou externo. Ou seja, o aplicativodeve estar pronto para receber parâmetros que configuremo serviço corretamente e, assim, possibilitem o consumo deaplicações necessárias à solução proposta.

94http://12factor.net/pt_br

Page 108: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Serviços de Apoio 102

A aplicação exemplo sofreu modificações para suportar a boaprática:

1 from flask import Flask

2 from redis import Redis

3 import os

4 host_run=os.environ.get('HOST_RUN', '0.0.0.0')

5 debug=os.environ.get('DEBUG', 'True')

6 host_redis=os.environ.get('HOST_REDIS', 'redis')

7 port_redis=os.environ.get('PORT_REDIS', '6379')

8 app = Flask(__name__)

9 redis = Redis(host=host_redis, port=port_redis)

10 @app.route('/')

11 def hello():

12 redis.incr('hits')

13 return 'Hello World! %s times.' % redis.get('h\

14 its')

15 if __name__ == "__main__":

16 app.run(host=host_run, debug=True)

Como pode perceber no código acima, a aplicação agorarecebe variáveis de ambiente para configurar o hostname ea porta do serviço Redis. Nesse caso, é possível configurar ohost e a porta da Redis que deseja conectar. E isso pode e deveser especificado no docker-compose.yml que também passoupor mudança para se adequar a nova boa prática:

Page 109: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Serviços de Apoio 103

1 version: "2"

2 services:

3 web:

4 build: .

5 ports:

6 - "5000:5000"

7 volumes:

8 - .:/code

9 labels:

10 - 'app.environment=${ENV_APP}'

11 environment:

12 - HOST_RUN=${HOST_RUN}

13 - DEBUG=${DEBUG}

14 - PORT_REDIS=6379

15 - HOST_REDIS=redis

16 redis:

17 image: redis:3.2.1

18 volumes:

19 - dados:/data

20 labels:

21 - 'app.environment=${ENV_APP}'

22 volumes:

23 dados:

24 external: false

Como observamos nos códigos já tratados, a vantagem daboa prática passa pela possibilidade de mudança de compor-tamento sem mudança do código. Mais uma vez é possívelviabilizar que, o mesmo código construído em um momento,possa ser reutilizado de forma semelhante, tanto no notebookdo desenvolvedor como no servidor de produção.

Fique atento para armazenamento de segredos dentro do

Page 110: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Serviços de Apoio 104

docker-compose.yml, pois esse arquivo é enviado para orepositório de controle de versão e é importante pensar outraestratégia de manutenção de segredos.

Uma estratégia possível é a manutenção de variáveis deambiente no Docker Host. Dessa forma, você precisa usarvariáveis do tipo ${variavel} dentro do docker-compose.ymlpara repassar a configuração ou, utilizar outro recurso maisavançado de gerenciamento de segredos.

Page 111: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Construa, lance,executeO próximo item da lista do modelo 12factor95, “Construa,lance, execute” é a quinta boa prática..

No processo de automatização de infraestrutura de implan-tação de software precisamos cuidado para que o compor-tamento do processo esteja dentro das expectativas e erroshumanos causem baixo impacto no processo completo dodesenvolvimento, do lançamento à produção.

Visando organizar, dividir responsabilidade e tornar o pro-cesso mais claro, o 12factor indica que o código base, para sercolocado em produção, deva passar por três fases:

• Construa - converter código do repositório em pacoteexecutável. Nesse processo se obtém as dependências,compila-se o binário e os ativos do código.

95http://12factor.net/pt_br/

Page 112: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Construa, lance, execute 106

• Lance - pacote produzido na fase construir é combi-nado com a configuração. O resultado é o ambientecompleto, configurado e pronto para ser colocado emexecução.

• Execute (também conhecido como “runtime”) - iniciaa execução do lançamento (aplicação + configuraçãodaquele ambiente), com base nas configurações especí-ficas do ambiente requerido.

A boa prática indica que a aplicação tenha separações explí-citas nas fases de Construa, Lance e Execute. Assim, cadamudança no código da aplicação, é construída apenas umavez na etapa de Construa. Mudanças da configuração nãonecessitam nova construção, sendo necessário, apenas, asetapas de lançar e executar.

De tal forma, é possível criar controles e processos claros emcada etapa. Caso algo ocorra na construção do código, umamedida pode ser tomada ou mesmo se cancela o lançamento,para que o código em produção não seja comprometido porconta do possível erro.

Com a separação das responsabilidades é possível saber emqual etapa o problema aconteceu e atuar manualmente, casonecessário.

Os artefatos produzidos devem ter um identificador de lan-çamento único. Pode ser o timestamp (como 2011-04-06-20:32:17) ou um número incremental (como v100). Com oartefato único é possível garantir o uso de versão antiga,seja para plano de retorno ou, até mesmo, para compararcomportamentos após mudanças no código.

Para atendermos a boa prática precisamos construir a imagemDocker com a aplicação dentro. Ela será nosso artefato.

Page 113: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Construa, lance, execute 107

Teremos um script novo, aqui chamado build.sh, com o se-guinte conteúdo:

1 #!/bin/bash

2

3 USER="gomex"

4 TIMESTAMP=$(date "+%Y.%m.%d-%H.%M")

5

6 echo "Construindo a imagem ${USER}/app:${TIMESTAM\

7 P}"

8 docker build -t ${USER}/app:${TIMESTAMP} .

9

10 echo "Marcando a tag latest também"

11 docker tag ${USER}/app:${TIMESTAMP} ${USER}/app:l\

12 atest

13

14 echo "Enviando a imagem para nuvem docker"

15 docker push ${USER}/app:${TIMESTAMP}

16 docker push ${USER}/app:latest

Além de construir a imagem, a envia para o repositório96 deimagem do Docker.

Lembre-se que, o código acima e os demais da boa prática,estão no repositório97 na pasta “factor5“.

O envio da imagem para o repositório é parte importante daboa prática em questão, pois isola o processo. Caso a imagemnão seja enviada para o repositório, permanece apenas noservidor que executou o processo de construção, sendo assim,a próxima etapa precisa, necessariamente, ser executada nomesmo servidor, pois tal etapa precisa da imagem disponível.

96http://hub.docker.com/97https://github.com/gomex/exemplo-12factor-docker

Page 114: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Construa, lance, execute 108

No modelo proposto, a imagem no repositório central ficadisponível para ser baixada no servidor. Caso utilize uma fer-ramenta de pipeline, é importante - ao invés de utilizar a datapara tornar o artefato único - usar variáveis do produto paragarantir que a imagem a ser consumida na etapa Executar,seja a mesma construída na etapa Lançar. Exemplo no GoCD:variáveis GO_PIPELINE_NAME e GO_PIPELINE_COUN-TER podem ser usadas em conjunto como garantia.

Com a geração da imagem podemos garantir que a etapaConstruir foi atendida perfeitamente, pois, agora temos umartefato construído e pronto para ser reunido à configuração.

A etapa de Lançamento é o arquivo docker-compose.ymlem si, pois o mesmo recebe as configurações devidas para oambiente no qual se deseja colocar a aplicação. Sendo assim, oarquivo docker-compose.ymlmuda um pouco e deixa de fazera construção da imagem, já que, agora, será utilizado apenaspara Lançamento e Execução (posteriormente):

1 version: "2"

2 services:

3 web:

4 image: gomex/app:latest

5 ports:

6 - "5000:5000"

7 volumes:

8 - .:/code

9 labels:

10 - 'app.environment=${ENV_APP}'

11 environment:

12 - HOST_RUN=${HOST_RUN}

13 - DEBUG=${DEBUG}

14 - PORT_REDIS=6379

Page 115: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Construa, lance, execute 109

15 - HOST_REDIS=redis

16 redis:

17 image: redis:3.2.1

18 volumes:

19 - dados:/data

20 labels:

21 - 'app.environment=${ENV_APP}'

22 volumes:

23 dados:

24 external: false

No exemplo docker-compose.yml acima, usamos a tag latestpara garantir que busque sempre a última imagem construídano processo. Mas como já mencionamos, caso utilize algumaferramenta de entrega contínua (como GoCD, por exemplo)faça uso das variáveis, para garantir a imagem criada naexecução específica do pipeline.

Dessa forma, lançamento e execução utilizarão o mesmoartefato: a imagem Docker, construída na fase de construção.

A etapa de execução, basicamente, executa oDocker-Composecom o comando abaixo:

1 docker-compose up -d

Page 116: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

ProcessosSeguindo a lista do modelo 12factor98, temos “Processos”como sexta boa prática.

Com o advento da automatização e devida inteligência namanutenção das aplicações, hoje, é esperado que a aplicaçãopossa atender a picos de demandas com inicialização automá-tica de novos processos, sem afetar seu comportamento.

A boa prática indica que processos de aplicações 12factor sãostateless (não armazenam estado) e share-nothing. Quaisquerdados que precisem persistir devem ser armazenados emserviço de apoio stateful (armazena o estado), normalmenteé usado uma base de dados.

O objetivo final dessa prática não faz distinção se a aplicaçãoé executada na máquina do desenvolvedor ou em produção,pois, nesse caso, o que muda é a quantidade de processosiniciados para atender as respectivas demandas. Na máquina

98http://12factor.net/pt_br

Page 117: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos 111

do desenvolvedor pode ser apenas um e, em produção, umnúmero maior.

O 12factor indica que o espaço de memória ou sistema dearquivos do servidor pode ser usado brevemente como cachede transação única. Por exemplo, o download de um arquivogrande, operando sobre ele e armazenando os resultados nobanco de dados.

Vale salientar que, um estado nunca deve ser armazenadoentre requisições, não importando o estado do processamentoda próxima requisição.

É importante salientar: ao seguir a prática, uma aplicaçãonão assume que, qualquer item armazenado em cache dememória ou no disco, estará disponível em futura solicitaçãoou job – com muitos processos de cada tipo rodando, sãoaltas as chances de futura solicitação ser servida por processodiferente, até mesmo em servidor diferente. Mesmo quando,rodando em apenas um processo, um restart (desencadeadopelo deploy de um código, mudança de configuração, ou oambiente de execução realocando o processo para localizaçãofísica diferente) geralmente vai acabar com o estado local(memória e sistema de arquivos, por exemplo).

Algumas aplicações demandam de sessões persistentes paraarmazenar informações da sessão de usuários e afins. Taissessões são usadas em futuras requisições domesmo visitante.Ou seja, se armazenado junto ao processo, é clara violaçãoda boa prática. Nesse caso, é aconselhável usar serviço deapoio, tal como redis, memcached ou afins para esse tipode trabalho externo ao processo. Com isso, é possível queo próximo processo, independente de onde esteja, consegueobter as informações atualizadas.

A aplicação que estamos trabalhando não guarda dado local e

Page 118: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos 112

tudo o que precisa é armazenado no Redis. Não precisamos fa-zer adequação alguma nesse código para seguir a boa prática,como vemos abaixo:

1 from flask import Flask

2 from redis import Redis

3 import os

4 host_redis=os.environ.get('HOST_REDIS', 'redis')

5 port_redis=os.environ.get('PORT_REDIS', '6379')

6 app = Flask(__name__)

7 redis = Redis(host=host_redis, port=port_redis)

8 @app.route('/')

9 def hello():

10 redis.incr('hits')

11 return 'Hello World! %s times.' % redis.get('hit\

12 s')

13 if __name__ == "__main__":

14 app.run(host="0.0.0.0", debug=True)

Para acessar o código da prática, acesse o repositório99 e apasta “factor6“.

99https://github.com/gomex/exemplo-12factor-docker

Page 119: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Vínculo de portasDe acordo com a lista do modelo 12factor100, a sétima boaprática é “Vínculo de portas”.

É comum encontrar aplicações executadas dentro de contêi-neres de servidores web, tal como Tomcat, ou Jboss, por exem-plo. Normalmente, essas aplicações são implantadas dentrodos serviços para que possam ser acessadas pelos usuáriosexternamente.

100http://12factor.net/pt_br

Page 120: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Vínculo de portas 114

A boa prática sugere que o aplicativo em questão seja auto-contido e dependa de um servidor de aplicação, tal comoJboss, Tomcat e afins. O software deve exportar um serviçoHTTP e lidar com as requisições que chegam por ele. Significaque, qualquer aplicação adicional é desnecessária para ocódigo estar disponível à comunicação externa.

Tradicionalmente, a implantação de artefato em servidor deaplicação, tal como Tomcat e Jboss, exige a geração de umartefato e, esse, é enviado para o serviço web em questão. Masno modelo de contêiner Docker, a idéia é que o artefato doprocesso de implantação seja o próprio contêiner.

O processo antigo de implantação do artefato em servidor de

Page 121: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Vínculo de portas 115

aplicação, normalmente, não tinha retorno rápido, o que au-mentava demasiadamente o processo de implantação de umserviço, pois, cada alteração demandava enviar o artefato parao serviço de aplicação web; e, esse tinha a responsabilidade deimportar, ler e executar o novo artefato.

Usando Docker, facilmente, a aplicação torna-se auto-contida.Já construímos um Dockerfile que descreve o que a aplicaçãoprecisa:

1 FROM python:2.7

2 ADD requirements.txt requirements.txt

3 RUN pip install -r requirements.txt

4 ADD . /code

5 WORKDIR /code

6 CMD python app.py

7 EXPOSE 5000

As dependências estão descritas no arquivo requirements.txt eos dados que devem ser persistidos são geridos por um serviçoexterno (serviços de apoio) à aplicação.

Outro detalhe da boa prática: a aplicação deve exportar oserviço através da vinculação a uma única porta. Como vemosno código exemplo, a porta padrão do python (5000) é iniciada,mas você pode escolher outra, se julgar necessário. Segue orecorte do código que trata do assunto:

1 if __name__ == "__main__":

2 app.run(host="0.0.0.0", debug=True)

A porta 5000 pode ser utilizada para servir dados localmenteem ambiente de desenvolvimento ou, através de proxy re-verso, quando for migrada para produção, com nome dedomínio adequado a aplicação em questão.

Page 122: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Vínculo de portas 116

Utilizar o modelo de vinculação de portas torna o processode atualização de aplicação mais fluído, uma vez que, na uti-lização de um proxy reverso inteligente, é possível adicionarnovos nós gradativamente, com a nova versão, e remover osantigos à medida que as versões atualizadas são executadasem paralelo.

Convém salientar: mesmo que o Docker permita a utilizaçãode mais de uma porta por contêineres, a boa prática enfatizaque você só deve utilizar uma porta vinculada por aplicação.

Page 123: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

ConcorrênciaA oitava boa prática da lista do modelo 12factor101, é “Con-corrência”.

Durante o processo de desenvolvimento de uma aplicaçãoé difícil imaginar o volume de requisição que ela terá nomomento que for colocada em produção. Por outro lado, umserviço que suporte grandes volumes de uso é esperado nassoluções modernas. Nada é mais frustante que solicitar acessoa uma aplicação e ela não estar disponível. Sugere falta decuidado e profissionalismo, na maioria dos casos.

Quando a aplicação é colocada em produção, normalmenteé dimensionada para determinada carga esperada, porém éimportante que o serviço esteja pronto para escalar. A soluçãodeve ser capaz de iniciar novos processo da mesma aplicação,caso necessário, sem afetar o produto. A figura abaixo, apre-senta gráfico de escalabilidade de serviços.

101http://12factor.net/pt_br

Page 124: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 118

Com objetivo de evitar qualquer problema na escalabilidadedo serviço, a boa prática indica que as aplicações devem su-portar execuções concorrentes e, quando um processo está emexecução, instanciar outro em paralelo e o serviço atendido,sem perda alguma.

Para tal, é importante dividir as tarefas corretamente. É inte-ressante o processo se ater aos objetivos, caso seja necessárioexecutar alguma atividade em backend e, depois retornar umapágina para o navegador, é salutar que haja dois serviços tra-tando as duas atividades, de forma separada. O Docker tornaessa tarefa mais simples, pois, nesse modelo, basta especificarum container para cada função e configurar corretamente arede entre eles.

Para exemplificar a boa prática, usaremos a arquitetura de-monstrada na figura abaixo:

Page 125: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 119

O serviço web é responsável por receber a requisição e balan-cear entre os workers, os quais são responsáveis por processara requisição, conectar ao redis e retornar a tela de “HelloWorld” informando quantas vezes foi obtida e qual nomede worker está respondendo a requisição (para ter certezaque está balanceando a carga), como podemos ver na figuraabaixo:

O arquivo docker-compose.yml exemplifica a boa prática:

1 version: "2"

2 services:

3 web:

4 container_name: web

5 build: web

6 networks:

7 - backend

8 ports:

9 - "80:80"

10

11 worker:

12 build: worker

13 networks:

Page 126: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 120

14 backend:

15 aliases:

16 - apps

17 expose:

18 - 80

19 depends_on:

20 - web

21

22 redis:

23 image: redis

24 networks:

25 - backend

26

27 networks:

28 backend:

29 driver: bridge

Para efetuar a construção do balanceador de carga, temos odiretório web contendo arquivos Dockerfile (responsável porcriar a imagem utilizada) e nginx.conf (arquivo de configura-ção do balanceador de carga utilizado).

Segue o conteúdo DockerFile do web:

1 FROM nginx:1.9

2

3 COPY nginx.conf /etc/nginx/nginx.conf

4 EXPOSE 80

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

E, o conteúdo do arquivo nginx.conf:

Page 127: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 121

1 user nginx;

2 worker_processes 2;

3

4 events {

5 worker_connections 1024;

6 }

7

8 http {

9 access_log /var/log/nginx/access.log;

10 error_log /var/log/nginx/error.log;

11

12 resolver 127.0.0.11 valid=1s;

13

14 server {

15 listen 80;

16 set $alias "apps";

17

18 location / {

19 proxy_pass http://$alias;

20 }

21 }

22 }

No arquivo de configuração acima, foram introduzidas algu-mas novidades. A primeira, “resolver 127.0.0.11“, é o serviçoDNS interno do Docker. Usando essa abordagem é possívelefetuar o balanceamento de carga via nome, usando recursointerno do Docker. Para mais detalhes sobre o funciona-mento do DNS interno do Docker, veja esse documento(https://docs.docker.com/engine/userguide/networking/configure-dns/102) (apenas em inglês).

102https://docs.docker.com/engine/userguide/networking/configure-dns/

Page 128: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 122

A segunda novidade, função set $alias “apps”;, responsávelpor especificar o nome “apps” usado na configuração doproxy reverso, em seguida “proxy_pass http://$alias;“. Valesalientar, o “apps” é o nome da rede especificada dentro doarquivo docker-compose.yml. Nesse caso, o balanceamentoé feito para a rede, todo novo contêiner que entra nessa redeé automaticamente adicionado ao balanceamento de carga.

Para efetuar a construção do worker temos o diretório wor-ker contendo os arquivos Dockerfile (responsável por criara imagem utilizada), app.py (aplicação usada em todos oscapítulos) e requirements.txt (descreve as dependências doapp.py).

Segue abaixo o conteúdo do arquivo app.py modificado paraa prática:

1 from flask import Flask

2 from redis import Redis

3 import os

4 import socket

5 print(socket.gethostname())

6 host_redis=os.environ.get('HOST_REDIS', 'redis')

7 port_redis=os.environ.get('PORT_REDIS', '6379')

8

9 app = Flask(__name__)

10 redis = Redis(host=host_redis, port=port_redis)

11

12 @app.route('/')

13 def hello():

14 redis.incr('hits')

15 return 'Hello World I am %s! %s times.' % (soc\

16 ket.gethostname(), redis.get('hits'))

Page 129: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 123

17 if __name__ == "__main__":

18 app.run(host="0.0.0.0", debug=True)

Segue o conteúdo do requirements.txt:

1 flask==0.11.1

2 redis==2.10.5

E por fim, o Dockerfile do worker tem o seguinte conteúdo:

1 FROM python:2.7

2 COPY requirements.txt requirements.txt

3 RUN pip install -r requirements.txt

4 COPY . /code

5 WORKDIR /code

6 CMD python app.py

No serviço redis não há construção da imagem, usaremos aimagem oficial para efeitos de exemplificação.

Para testar o que foi apresentado até então, realize o clonedo repositório (https://github.com/gomex/exemplo-12factor-docker103) e acesse a pasta factor8, executando o comando,abaixo, para iniciar os contêineres:

1 docker-compose up -d

Acesse os contêineres através do navegador na porta 80 doendereço localhost. Atualize a página e veja que apenas umnome aparece.

103https://github.com/gomex/exemplo-12factor-docker

Page 130: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Concorrência 124

Por padrão, o Docker-Compose executa apenas uma instânciade cada serviço explicitado no docker-compose.yml. Paraaumentar a quantidade de contêineres “worker”, de um paradois, execute o comando abaixo:

1 docker-compose scale worker=2

Atualize a página no navegador e veja que o nome do hostalterna entre duas possibilidades, ou seja, as requisições estãosendo balanceadas para ambos contêineres.

Nessa nova proposta de ambiente, o serviçoweb se encarregade receber as requisições HTTP e fazer o balanceamentode carga. Então, o worker é responsável por processar asrequisições, basicamente obter o nome de host, acessar o redise a contagem de quantas vezes o serviço foi requisitado e,então, gerar o retorno para devolvê-lo ao serviço web que,por sua vez, responde ao usuário. Como podemos perceber,cada instância do ambiente tem função definida e, com isso,é mais fácil escalá-lo.

Aproveitamos para dar os créditos ao capitão Marcosnils104,que nos mostrou como é possível balancear carga pelo nomeda rede docker.

104https://twitter.com/marcosnils

Page 131: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

DescartabilidadeNa nona posição da lista do modelo 12factor105, a “Descarta-bilidade”.

Quando falamos de aplicações web, espera-se que mais deum processo atenda a todo tráfego requisitado para o serviço.Porém, tão importante quanto a habilidade de iniciar novosprocessos, a capacidade de um processo defeituoso terminarna mesma velocidade que iniciou, pois um processo quedemora para finalizar pode comprometer toda solução, umavez que ela pode ainda estar atendemos requisições de formadefeituosa.

Em resumo, podemos dizer que aplicações web deveriam sercapazes de remover rapidamente processos defeituosos.

Com objetivo de evitar que o serviço prestado seja dependentedas instâncias que o servem, a boa prática indica que as

105http://12factor.net/pt_br

Page 132: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Descartabilidade 126

aplicações devem ser descartáveis, ou seja, desligar uma desuas instâncias não deve afetar a solução como um todo.

O Docker tem a opção de descartar automaticamente umcontêiner após o uso - no docker container run utilize aopção –rm. Vale salientar que essa opção não funciona emmodo daemon (-d), portanto, só faz sentido utilizar no modointerativo (-i).

Outro detalhe importante na boa prática é viabilizar que ocódigo desligue “graciosamente” e reinicie sem erros. Assim,ao escutar um SIGTERM, o código deve terminar qualquerrequisição em andamento e então desligar o processo semproblemas e de forma rápida, permitindo, também, que sejarapidamente atendido por outro processo.

Entendemos como desligamento “gracioso” uma aplicaçãocapaz de auto finalizar sem danos à solução; ao recebersinal para desligar, imediatamente recusa novas requisiçõese apenas finaliza as tarefas pendentes em execução naquelemomento. Implícito nesse modelo: as requisições HTTP sãocurtas (não mais que poucos segundos) e, nos casos de co-nexões longas, o cliente pode se reconectar automaticamentecaso a conexão seja perdida.

A aplicação sofreu a seguinte mudança para atender a espe-cificação:

Page 133: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Descartabilidade 127

1 from flask import Flask

2 from redis import Redis

3 from multiprocessing import Process

4 import signal, os

5

6 host_redis=os.environ.get('HOST_REDIS', 'redis')

7 port_redis=os.environ.get('PORT_REDIS', '6379')

8

9 app = Flask(__name__)

10 redis = Redis(host=host_redis, port=port_redis)

11

12 @app.route('/')

13 def hello():

14 redis.incr('hits')

15 return 'Hello World! %s times.' % redis.get('\

16 hits')

17

18 if __name__ == "__main__":

19 def server_handler(signum, frame):

20 print 'Signal handler called with signal'\

21 , signum

22 server.terminate()

23 server.join()

24

25 signal.signal(signal.SIGTERM, server_handler)

26

27 def run_server():

28 app.run(host="0.0.0.0", debug=True)

29

30 server = Process(target=run_server)

31 server.start()

No código acima, adicionamos tratamento para quando rece-

Page 134: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Descartabilidade 128

ber um sinal de SIGTERM, finalizar rapidamente o processo.Sem o tratamento, o código demora mais para ser desligado.Dessa forma, concluímos que a solução é descartável o su-ficiente. Podemos desligar e reiniciar os containers em outroDocker Host e a mudança não causará impacto na integridadedos dados.

Para fins de entendimento sobre o que trabalhamos aqui,cabe esclarecimento, de acordo com oWikipedia, sinal é: “(…)notificação assíncrona enviada a processos com o objetivo denotificar a ocorrência de um evento.” E, o SIGTERM: “(…)nome de um sinal conhecido por um processo informáticoem sistemas operativos POSIX. Este é o sinal padrão enviadopelos comandos kill e killall. Ele causa o término do processo,como em SIGKILL, porém pode ser interpretado ou ignoradopelo processo. Com isso, SIGTERM realiza um encerramentomais amigável, permitindo a liberação de memória e o fecha-mento dos arquivos.”

Para realizar o teste do que foi apresentado até então, realizeo clone do repositório (https://github.com/gomex/exemplo-12factor-docker106) e acesse a pasta factor8 (isso mesmo, anúmero 8, vamos demonstrar a diferença pra o factor9),executando o comando abaixo para iniciar os contêineres:

1 docker-compose up -d

Depois, execute o comando abaixo para finalizar os contêine-res:

106https://github.com/gomex/exemplo-12factor-docker

Page 135: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Descartabilidade 129

1 time docker-compose stop

Você verá que a finalização do worker demora cerca de 11segundos, isso porque o comportamento do Docker-Compose,para finalizar, primeiro faz um SIGTERM e espera por 10segundos que a aplicação finalize sozinha, caso contrário,envia um SIGKILL que finaliza o processo bruscamente. Essetimeout é configurável. Caso deseje modificar, basta usar oparâmetro “-t” ou “–timeout“. Veja um exemplo:

1 docker-compose stop -t 5

Obs: O valor informado, após o parâmetro, é considerado emsegundos.

Agora, para testar o código modificado, mude para a pastafactor9 e execute o seguinte comando:

1 docker-compose up -d

Depois, solicite o término:

1 time docker-compose stop

Veja que o processo worker finalizou mais rápido, pois re-cebeu o sinal SIGTERM. A aplicação fez o serviço de autofinalização e não precisou receber um sinal SIGKILL para ser,de fato, finalizado.

Page 136: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Paridade entre desen-volvimento/produçãoSeguindo a lista domodelo 12factor107, temos “Paridade entredesenvolvimento/produção” como décima boa prática.

Infelizmente, na maioria dos ambientes de trabalho comsoftware, existe grande abismo entre desenvolvimento e pro-dução. Não é mero acaso ou falta de sorte, existe por contadas diferenças entre as equipes de desenvolvimento e as deinfraestrutura. E, de acordo com o 12factor, manifestam-senos seguintes âmbitos:

• Tempo: o desenvolvedor pode trabalhar um código quedemora dias, semanas ou até meses para ser transferidoà produção.

• Pessoal: desenvolvedores escrevem código, engenhei-ros de operação fazem o deploy do código.

• Ferramentas: desenvolvedores podem usar conjuntoscomo Nginx, SQLite e OS X, enquanto o app em pro-dução, usa Apache, MySQL e Linux.

107http://12factor.net/pt_br

Page 137: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Paridade entre desenvolvimento/produção 131

O 12factor pretende colaborar para reduzir o abismo entre asequipes e equalizar os ambientes. Com relação aos âmbitosapresentados, seguem as respectivas propostas:

• Tempo: desenvolvedor pode escrever código e ter odeploy concluído em horas ou até mesmo minutosdepois.

• Pessoal: desenvolvedores que escrevem código estãoproximamente envolvidos em realizar o deploy e acom-panhar o comportamento na produção.

• Ferramentas: manter desenvolvimento e produção omais similares possível.

A solução de contêiner tem como um dos principais objetivoscolaborar com a portabilidade entre ambiente de desenvolvi-mento e produção. A ideia é que a imagem seja construída eapenas seu status modifique para ser posta em produção. Ocódigo atual já está pronto para esse comportamento, assim,não há muito a ser modificado para garantir a boa prática. Écomo um bônus pela adoção do Docker e o seguimento dasoutras boas práticas do 12factor.

Page 138: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

LogsA décima primeira boa prática, na lista do modelo 12factor108,é “Logs”.

No desenvolvimento de código, gerar dados para efeitos delog é algo bastante consolidado. Não acreditamos que existamsoftwares em desenvolvimento sem essa preocupação. Porém,o uso correto do log vai além de, apenas, gerar dados.

Para efeito de contextualização, de acordo com o 12factor,o log é: “(…) fluxo de eventos agregados e ordenados por

108http://12factor.net/pt_br

Page 139: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Logs 133

tempo coletados dos fluxos de saída de todos os processos emexecução e serviços de apoio.”

Logs, normalmente, são armazenados em arquivos, com even-tos por linha (pilhas de exceção podem ocupar várias linhas).Mas essa prática não é indicada, ao menos não na perspectivada aplicação. Isso quer dizer que, a aplicação não deveria sepreocupar em qual arquivo guardar os logs.

Especificar arquivos, implica informar o diretório corretodesse arquivo, que, por sua vez, resulta em configuraçãoprévia do ambiente. Isso impacta, negativamente, na porta-bilidade da aplicação, pois é necessário que, o ambiente quereceberá a solução, siga uma série de requisitos técnicos parasuportar a aplicação, enterrando, assim, a possibilidade do“Construa uma vez, rode em qualquer lugar”.

A boa prática indica que as aplicações não devem gerenciarou rotear arquivos de log, mas devem ser depositados semqualquer esquema de buffer na saída padrão (STDOUT).Assim, uma infraestrutura externa à aplicação - plataforma -deve gerenciar, coletar e formatar a saída dos logs para futuraleitura. Isso é realmente importante quando a aplicação estárodando em várias instâncias.

Com o Docker, tal tarefa se torna fácil, pois o Docker já coletalogs da saída padrão e encaminha para algum dos váriosdrivers de log. O driver pode ser configurado na inicializaçãodo container de forma a centralizar os logs no serviço remotode logs, por exemplo syslog.

O código exemplo no repositório(https://github.com/gomex/exemplo-12factor-docker109), na pasta factor11, está pronto para testara boa prática, pois já envia todas as saídas de dados para

109https://github.com/gomex/exemplo-12factor-docker

Page 140: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Logs 134

STDOUT e você pode conferir iniciando o serviço com ocomando abaixo:

1 docker-compose up

Depois de iniciar, acesse o navegador e verifique as requi-sições da aplicação que aparecem na console do Docker-Compose.

Page 141: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos deadministraçãoDécima segunda e última boa prática da lista do modelo12factor110: “Processos de administração”.

110http://12factor.net/pt_br

Page 142: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos de administração 136

Toda aplicação demanda administração. Isso quer dizer que,uma vez implantada, é possível que a aplicação precise receberdeterminados comandos para corrigir possíveis problemasou simplesmente mudar de comportamento. Como exemplostemos migrações de banco de dados, execução de scriptsdiversos como backup e, também, execução de um consolepara inspeção do serviço.

A boa prática recomenda processos de administração exe-

Page 143: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos de administração 137

cutados em ambientes idênticos ao utilizado no código emexecução, seguindo todas as práticas apresentadas até então.

Usando Docker é possível rodar os processos utilizando amesma imagem base no ambiente de execução que desejar.Com isso, podemos nos beneficiar da comunicação entre oscontêineres e do uso de volumes que forem necessários e afins.

Para exemplificar a boa prática criamos o arquivo reset.py:

1 from redis import Redis

2 import signal, os

3

4 host_redis=os.environ.get('HOST_REDIS', 'redis')

5 port_redis=os.environ.get('PORT_REDIS', '6379')

6

7 redis = Redis(host=host_redis, port=port_redis)

8

9 redis.set('hits', 0)

Responsável por reinicializar o contador de visitas do Redis,o comando é dado usando um contêiner diferente a partir damesma imagemDocker. Primeiro iniciamos o ambiente, baixeo repositório e acesse a pasta factor12 e execute o comando:

1 docker-compose up

Acesse a aplicação pelo navegador. Caso esteja usando GNU/-Linux ou Docker For MAC e Windows, acesse o endereço127.0.0.1. Você verá a seguinte frase:

Page 144: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Processos de administração 138

1 “Hello World! 1 times.”

Acesse a aplicação mais algumas vezes para o marcadoraumentar.

Depois, execute o comando de administração a partir doserviço worker:

1 docker-compose exec worker python reset.py

O comando “python reset.py” será executado dentro de umnovo contêiner, mas usando a mesma imagem de um workerregular.

Acesse novamente a aplicação e verifique se o marcadoriniciou a partir de 1 novamente.

Page 145: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso doDockerSe você leu a primeira parte do livro já sabe o básico sobreDocker, mas agora que pretende começar a usar com maisfrequência, alguns desconfortos podem surgir, pois, comoqualquer ferramenta, o Docker tem seu próprio conjunto deboas práticas e dicas.

O objetivo dessse texto é apresentar algumas dicas para o bomuso do Docker. Isso não quer dizer que, a forma que vocêexecuta é, necessariamente, errada.

Toda ferramenta demanda algumas melhores práticas paratornar o uso mais efetivo e com menor possibilidade deproblemas futuros.

Esse capítulo foi separado em duas seções: dicas para rodar(docker container run) e boas práticas de construção deimagens (docker build/Dockerfile).

Dicas para Rodar

Lembre-se, cada comando docker container run cria novocontêiner com base em uma imagem específica e inicia umprocesso dentro dele, a partir de um comando (CMD especifi-cado no Dockerfile).

Page 146: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 140

Contêiners descartáveis

É esperado que os contêiners executados possam ser des-cartados sem qualquer problema. Sendo assim, é importanteutilizar contêiners verdadeiramente efêmeros.

Para tal, utilize o argumento --rm. Isso faz com que todos oscontêiners, e seus dados, sejam removidos após o termino daexecução, evitando consumir disco desnecessariamente.

Em geral, pode-se utilizar o comando run como no exemplo:

1 docker container run --rm -it debian /bin/bash

Note aqui que -it significa --interactive --tty. É usadopara fixar a linha de comando com o contêiner, assim, apósesse docker container run, todos os comandos são executa-dos pelo bash de dentro do contêiner. Para sair use exit oupressione Control-d. Esses parâmetros são muito úteis paraexecutar um contêiner em primeiro plano.

Verifique variáveis de ambiente

Às vezes faz-se necessário verificar qual metadados são de-finidos como variáveis de ambiente em uma imagem. Use ocomando env para obter essa informação:

1 docker container run --rm -it debian env

Para verificar as variáveis de ambientes passados de umcontêiner já criado:

Page 147: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 141

1 docker inspect --format '{{.Config.Env}}' <contai\

2 ner>

Para outros metadados, use variações do comando docker

inspect.

Logs

Docker captura logs da saída padrão (STDOUT) e saída de erros(STDERR).

Esses registros podem ser roteados para diferentes sistemas(syslog, fluentd, …) que, podem ser especificados através daconfiguração de driver111 --log-driver=VALUE no comandodocker container run.

Quando utilizado o driver padrão json-file (e também jour-

nald), pode-se utilizar o seguinte comando para recuperar oslogs:

1 docker logs -f <container_name>

Observe também o argumento -f para acompanhar as pró-ximas mensagens de log de forma interativa. Quando quiserparar, pressione Ctrl-c .

Backup

Dados em contêiners Docker são expostos e compartilhadosatravés de argumentos de volumes utilizados ao criar e iniciaro contêiner. Esses volumes não seguem as regras doUnion File

111https://docs.docker.com/engine/admin/logging/overview/

Page 148: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 142

System112, pois os dados persistemmesmo quando o contêineré removido.

Para criar um volume em determinado contêiner, execute daseguinte forma:

1 docker container run --rm -v /usr/share/nginx/htm\

2 l --name nginx_teste nginx

Com a execução desse container, teremos serviço Nginx queusa o volume criado para persistir seus dados; os dadospersistirão mesmo após o contêiner ser removido.

É boa prática de administração de sistema fazer cópias desegurança (backups) periodicas e, para executar essa atividade(extrair dados), use o comando:

1 docker container run --rm -v /tmp:/backup --volum\

2 es-from nginx-teste busybox tar -cvf /backup/back\

3 up_nginx.tar /usr/share/nginx/html

Após a execução do comando, temos um arquivo backup_-

nginx.tar dentro da pasta /tmp do Docker host.

Para restaurar esse backup utlize:

1 docker container run --rm -v /tmp:/backup --volum\

2 es-from nginx-teste busybox tar -xvf /backup/back\

3 up.tar /usr/share/nginx/html

112https://docs.docker.com/engine/reference/glossary/#union-file-system

Page 149: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 143

Mais informação também podem ser encontradas na res-posta113, onde é possível encontrar alguns aliases para es-ses dois comandos. Esses aliases também estão disponíveisabaixo, na seção Aliases.

Outras fontes são:

• Documentação oficial do Docker sobre Backup, restau-ração ou migração de dados (em inglês)114

• Uma ferramenta de backup (atualmente deprecada):docker-infra/docker-backup115

Use docker container exec para “entrarem um contêiner”

Eventualmente, é necessário entrar em um contêiner emexecução afim de verificar algum problema, efetuar testes ousimplemente depurar (debug). Nunca instale o daemon SSHem um contêiner Docker. Use docker container exec paraentrar em um contêiner e rodar comandos:

1 docker container exec -it <nome do container em e\

2 xecução> bash

A funcionalidade é útil em desenvolvimento local e experi-mentações. Mas evite utilizar o contêiner em produção ouautomatizar ferramentas em volta dele.

Verifique a documentação116.

113http://stackoverflow.com/a/34776997/1046584114https://docs.docker.com/engine/userguide/containers/dockervolumes/#backup-

restore-or-migrate-data-volumes115https://github.com/docker-infra/docker-backup116https://docs.docker.com/engine/reference/commandline/exec/

Page 150: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 144

Sem espaço em disco do Docker Host

Ao executar contêiners e construir imagens várias vezes, oespaço em disco pode se tornar escasso. Quando isso acontece,é necessário limpar alguns contêiners, imagens e logs.

Uma maneira rápida de limpar contêiners e imagens é utilizaro seguinte comando:

1 docker system prune

Com esse comando você removerá:

• Todos os contêiners que não estão em uso no momento• Todos os volumes que não estão em uso por ao menosum contêiner

• Todas as redes que não estão em uso por ao menos umcontêiner

• Todas as imagens dangling

Obs: Pra não aprofundar muito no conceito baixo nível doDocker, podemos dizer que imagens dangling são simples-mente sem ponteiros e assim desnecessárias para o uso con-vencional.

Dependendo do tipo de aplicação, logs também podem servolumosos. O gerenciamento depende muito de qual driver117

é utilizado. No driver padrão (json-file) a limpeza podese dar através da execução do seguinte comando dentro doDocker Host:

117https://docs.docker.com/engine/admin/logging/overview/

Page 151: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 145

1 echo "" > $(docker inspect --format='{{.LogPath}}\

2 ' <container_name_or_id>)

• A proposta de funcionalidade de limpar o históricode logs foi, na verdade, rejeitada. Mais informação:https://github.com/docker/compose/issues/1083118

• Considere especificar a opção max-size para o driverde log ao executar docker container run: https://docs.docker.com/engine/reference/logging/overview/#json-file-options119

Aliases

Com alias é possível transformar comandos grandes em me-nores. Temos algumas novas opções para executar tarefasmais complexas.

Utilize esses aliases no seu .zshrc ou .bashrc para limparimagens e contêiners, fazer backup e restauração, etc.

1 # runs docker container exec in the latest contai\

2 ner

3 function docker-exec-last {

4 docker container exec -ti $( docker ps -a -q -l\

5 ) /bin/bash

6 }

7

8 function docker-get-ip {

9 # Usage: docker-get-ip (name or sha)

10 [ -n "$1" ] && docker inspect --format "{{ .Net\

11 workSettings.IPAddress }}" $1

118https://github.com/docker/compose/issues/1083119https://docs.docker.com/engine/reference/logging/overview/#json-file-options

Page 152: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 146

12 }

13

14 function docker-get-id {

15 # Usage: docker-get-id (friendly-name)

16 [ -n "$1" ] && docker inspect --format "{{ .ID \

17 }}" "$1"

18 }

19

20 function docker-get-image {

21 # Usage: docker-get-image (friendly-name)

22 [ -n "$1" ] && docker inspect --format "{{ .Ima\

23 ge }}" "$1"

24 }

25

26 function docker-get-state {

27 # Usage: docker-get-state (friendly-name)

28 [ -n "$1" ] && docker inspect --format "{{ .Sta\

29 te.Running }}" "$1"

30 }

31

32 function docker-memory {

33 for line in `docker ps | awk '{print $1}' | gre\

34 p -v CONTAINER`; do docker ps | grep $line | awk \

35 '{printf $NF" "}' && echo $(( `cat /sys/fs/cgroup\

36 /memory/docker/$line*/memory.usage_in_bytes` / 10\

37 24 / 1024 ))MB ; done

38 }

39 # keeps the commmand history when running a conta\

40 iner

41 function basher() {

42 if [[ $1 = 'run' ]]

43 then

Page 153: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 147

44 shift

45 docker container run -e HIST_FILE=/root/.\

46 bash_history -v $HOME/.bash_history:/root/.bash_h\

47 istory "$@"

48 else

49 docker "$@"

50 fi

51 }

52 # backup files from a docker volume into /tmp/bac\

53 kup.tar.gz

54 function docker-volume-backup-compressed() {

55 docker container run --rm -v /tmp:/backup --vol\

56 umes-from "$1" debian:jessie tar -czvf /backup/ba\

57 ckup.tar.gz "${@:2}"

58 }

59 # restore files from /tmp/backup.tar.gz into a do\

60 cker volume

61 function docker-volume-restore-compressed() {

62 docker container run --rm -v /tmp:/backup --vol\

63 umes-from "$1" debian:jessie tar -xzvf /backup/ba\

64 ckup.tar.gz "${@:2}"

65 echo "Double checking files..."

66 docker container run --rm -v /tmp:/backup --vol\

67 umes-from "$1" debian:jessie ls -lh "${@:2}"

68 }

69 # backup files from a docker volume into /tmp/bac\

70 kup.tar

71 function docker-volume-backup() {

72 docker container run --rm -v /tmp:/backup --vol\

73 umes-from "$1" busybox tar -cvf /backup/backup.ta\

74 r "${@:2}"

75 }

Page 154: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 148

76 # restore files from /tmp/backup.tar into a docke\

77 r volume

78 function docker-volume-restore() {

79 docker container run --rm -v /tmp:/backup --vol\

80 umes-from "$1" busybox tar -xvf /backup/backup.ta\

81 r "${@:2}"

82 echo "Double checking files..."

83 docker container run --rm -v /tmp:/backup --vol\

84 umes-from "$1" busybox ls -lh "${@:2}"

85 }

Fontes:

• https://zwischenzugs.wordpress.com/2015/06/14/my-fa-vourite-docker-tip/120

• https://website-humblec.rhcloud.com/docker-tips-and-tricks/121

Boas práticas para construção deimagens

Em Docker, as imagens são tradicionalmente construídasusando um arquivo Dockerfile. Existem alguns bons guiassobre as melhores práticas para construir imagens Docker.Recomendamos dar uma olhada:

• Documentação oficial122

120https://zwischenzugs.wordpress.com/2015/06/14/my-favourite-docker-tip/121https://website-humblec.rhcloud.com/docker-tips-and-tricks/122https://docs.docker.com/engine/articles/dockerfile_best-practices/

Page 155: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 149

• Guia do projeto Atomic123

• Melhores práticas do Michael Crosby Parte 1124

• Melhores práticas do Michael Crosby Parte 2125

Use um “linter”

“Linter” é uma ferramenta que fornece dicas e avisos sobrealgum código fonte. Para Dockerfile existem opções simples,mas é, ainda, um espaço novo em evolução.

Muitas opções foram discutidas aqui126.

Desde janeiro de 2016, o mais completo parece ser hadolint127,disponível em duas versões: on-line e terminal. O interessantedessa ferramenta é que usa o maduro Shell Check128 paravalidar os comandos shell.

O básico

O contêiner produzido pela imagem do Dockerfile deve sero mais efêmero possível. Significa que deve ser possível para-lo, destruí-lo e substituí-lo por um novo contêiner construídocom o minimo de esforço.

É comum colocar outros arquivos, como documentação, nodiretório junto ao Dockerfile; para melhorar a performance

123http://www.projectatomic.io/docs/docker-image-author-guidance/124http://crosbymichael.com/dockerfile-best-practices.html125http://crosbymichael.com/dockerfile-best-practices.html126https://stackoverflow.com/questions/28182047/is-there-a-way-to-lint-the-

dockerfile127http://hadolint.lukasmartinelli.ch/128http://www.shellcheck.net/about.html

Page 156: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 150

de construção, exclua arquivos e diretórios criando um ar-quivo dockerignore129 no mesmo diretório. Esse arquivo fun-ciona de maneira semelhante ao .gitignore. Usá-lo ajuda aminimizar o contexto de construção enviado -completa coma versão correta- docker host a cada docker build.

Evite adicionar pacotes e dependências extras não necessáriasà aplicação e minimize a complexidade, tamanho da imagem,tempo de contrução e superfície de ataque.

Minimize também o número de camadas: sempre que possívelagrupe vários comandos. Porém, também leve em conta avolatilidade e manutenção dessas camadas.

Na maioria dos casos, rode apenas um único processo porcontêiner. Desacoplar aplicações em vários contêiners faci-lita a escalabilidade horizontal, reuso e monitoramento doscontêiners.

Prefira COPY ao invés de ADD

O comando ADD existe desde o início do Docker. É versátile permite truques além de simplesmente copiar arquivos docontexto de construção, o que o torna mágico e difícil deentender. Permite baixar arquivos de urls e, automaticamente,extrair arquivos de formatos conhecidos (tar, gzip, bzip2, etc.).

Por outro lado, COPY é um comando mais simples para inserirarquivos e pastas do caminho de construção para dentro daimagem Docker. Assim, favoreça COPY a menos que tenhacerteza absoluta que ADD é necessário. Para mais detalhes vejaaqui130.

129https://docs.docker.com/engine/reference/builder/130https://labs.ctl.io/dockerfile-add-vs-copy/

Page 157: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 151

Execute um “checksum” depois debaixar e antes de usar o arquivo

Em vez de usar ADD para baixar e adicionar arquivos àimagem, favoreça a utilização de curl131 e a verificação atravésde um checksum após o download. Isso garante que o arquivoé o esperado e não poderá variar ao longo do tempo. Se oarquivo que a URL aponta mudar, o checksum irá mudare a construção da imagem falhará. Isso é importante, pois,favorece a reproducibilidade e a segurança na construção deimagens.

Bom exemplo para inspiração é o Dockerfile oficial do Jen-kins132:

1 ENV JENKINS_VERSION 1.625.3

2 ENV JENKINS_SHA 537d910f541c25a23499b222ccd37ca25\

3 e074a0c

4

5 RUN curl -fL http://mirrors.jenkins-ci.org/war-st\

6 able/$JENKINS_VERSION/jenkins.war -o /usr/share/j\

7 enkins/jenkins.war \

8 && echo "$JENKINS_SHA /usr/share/jenkins/jenkin\

9 s.war" | sha1sum -c -

Use uma imagem de base mínima

Sempre que possível, utilize imagens oficiais como base parasua imagem. Você pode usar a imagem debian133, por exem-plo, que é muito bem controlada e mantida mínima (por volta

131https://curl.haxx.se/132https://github.com/jenkinsci/docker/blob/83ce6f6070f1670563a00d0f61d04edd62b78f4f/

Dockerfile#L36133https://hub.docker.com/_/debian/

Page 158: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 152

de 150 mb). Lembre-se também usar tags específicas, porexemplo, debian:jessie.

Se mais ferramentas e dependências são necessárias, olhe porimagens como buildpack-deps134.

Porém, caso debian ainda seja muito grande, existem imagensminimalistas como alpine135 ou mesmo busybox136. Evite al-pine se DNS é necessário, existem alguns problemas a seremresolvidos137. Além disso, evite-o para linguagens que usamo GCC, como Ruby, Node, Python, etc, isso é porque alpineutiliza libc MUSL que pode produzir binários diferentes.

Evite imagens gigantes como phusion/baseimage138. Essaimagem é muito grande, foge da filosofia de processo porcontêiner e muito do que a compõe não é essencial paracontêiners Docker, veja mais aqui139 .

Outras fontes140

Use o cache de construção de camadas

Outra funcionalidade útil que o uso de Dockerfile propor-ciona é a reconstrução rápida usando o cache de camadas. Afim de aproveitar o recurso, insira ferramentas e dependênciasque mudem com menos frequência no topo do Dockerfile.

Por exemplo, considere instalar as dependências de códigoantes de adicionar o código. No caso de NodeJS:

134https://hub.docker.com/_/buildpack-deps/135https://hub.docker.com/r/gliderlabs/alpine/136https://hub.docker.com/r/gliderlabs/alpine/137https://github.com/gliderlabs/docker-alpine/blob/master/docs/caveats.md138https://hub.docker.com/r/phusion/baseimage/139https://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/140http://www.iron.io/microcontainers-tiny-portable-containers/

Page 159: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 153

1 COPY package.json /app/

2 RUN npm install

3 COPY . /app

Para ler mais sobre isso, veja esse link141.

Limpe na mesma camada

Ao usar um gerenciador de pacotes para instalar algum soft-ware, é uma boa prática limpar o cache gerado pelo gerenci-ador de pacotes logo após a instalação das dependências. Porexemplo, ao usar apt-get:

1 RUN apt-get update && \

2 apt-get install -y curl python-pip && \

3 pip install requests && \

4 apt-get remove -y python-pip curl && \

5 rm -rf /var/lib/apt/lists/*

Em geral, deve-se limpar o cache do apt (gerado por apt-

get update) através da remoção de /var/lib/apt/lists.Isso ajuda a manter reduzido o tamanho da imagem. Alémdisso, observe que, pip e curl também são removidos umavez que são desnecessários para a aplicação de produção.Lembre-se que a limpeza precisa ser feita na mesma camada(comando RUN). Caso contrário, os dados serão persistidosnessa camada e removê-los mais tarde não terá efeito notamanho da imagem final.

141http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/

Page 160: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 154

Note que, segundo a documentação142, as imagens oficiais deDebian e Ubuntu rodam automaticamente apt-get clean.Logo, a invocação explícita não é necessária.

Evite rodar apt-get upgrade ou dist-upgrade, pois, váriospacotes da imagem base não vão atualizar dentro de um con-têiner desprovido de privilégios. Se há um pacote específicoa ser atualizado, simplesmete use apt-get install -y foo

para atualizá-lo automaticamente.

Para ler mais sobre o assunto, veja o link143 e esse outro144.

Use um script “wrapper” comoENTRYPOINT, às vezes

Um script wrapper pode ajudar ao tomar a configuraçãodo ambiente e definir a configuração do aplicativo. Pode,até mesmo, definir configurações padrões quando não estãodisponíveis.

Ótimo exemplo é o fornecido no artigo de Kelsey Hightower:12 Fracturated Apps145:

142https://github.com/docker/docker/blob/03e2923e42446dbb830c654d0eec323a0b4ef02a/contrib/mkimage/debootstrap#L82-L105

143http://blog.replicated.com/2016/02/05/refactoring-a-dockerfile-for-image-size/144https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-

practices/#apt-get145https://medium.com/@kelseyhightower/12-fractured-apps-1080c73d481c#

.xn2cylwnk

Page 161: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 155

1 #!/bin/sh

2 set -e

3 datadir=${APP_DATADIR:="/var/lib/data"}

4 host=${APP_HOST:="127.0.0.1"}

5 port=${APP_PORT:="3306"}

6 username=${APP_USERNAME:=""}

7 password=${APP_PASSWORD:=""}

8 database=${APP_DATABASE:=""}

9 cat <<EOF > /etc/config.json

10 {

11 "datadir": "${datadir}",

12 "host": "${host}",

13 "port": "${port}",

14 "username": "${username}",

15 "password": "${password}",

16 "database": "${database}"

17 }

18 EOF

19 mkdir -p ${APP_DATADIR}

20 exec "/app"

Note, sempre use exec em scripts shell que envolvem aaplicação. Desta forma, a aplicação pode receber sinais Unix.

Considere também usar um sistema de inicialização simples(e.g. dumb init146) como a CMD base, assim, os sinais do Unixpodem ser devidamente tratados. Leia mais aqui147.

Log para stdout

Aplicações dentro de Docker devem emitir logs para stdout.Porém, algumas aplicações escrevem os logs em arquivos.

146https://github.com/Yelp/dumb-init147http://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html

Page 162: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 156

Nestes casos, a solução é criar um symlink do arquivo parastdout.

Exemplo: Dockerfile do nginx148:

1 # forward request and error logs to docker log co\

2 llector

3 RUN ln -sf /dev/stdout /var/log/nginx/access.log

4 RUN ln -sf /dev/stderr /var/log/nginx/error.log

Para ler mais, veja esse link149.

Cuidado ao adicionar dados em umvolume no Dockerfile

Lembre-se de usar a instrução VOLUME para expor dados debancos de dados, configuração ou arquivos e pastas criadospelo contêiner. Use para qualquer dado mutável e partesservidas ao usuário do serviço para qual a imagem foi criada.

Evite adicionar muitos dados em uma pasta e, em seguida,transformá-lo em VOLUME apenas na inicialização do contêi-ner, pois, nesse momento, pode tornar o carregamento maislento. Ao criar contêiner, os dados serão copiados da imagempara o volume montado. Como dito antes, use VOLUME nacriação da imagem.

Além disso, ainda em tempo de criação da imagem (build),não adicione dados para caminhos previamente declaradoscomo VOLUME. Isso não funciona, os dados não serão persisti-dos, pois, dados em volumes não são comitados em imagens.

148https://github.com/nginxinc/docker-nginx/blob/master/Dockerfile149https://serverfault.com/questions/599103/make-a-docker-application-write-to-

stdout

Page 163: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Dicas para uso do Docker 157

Leia mais na explicação de Jérôme Petazzoni150.

EXPOSE de portas

ODocker favorece reproducibilidade e portabilidade. Imagensdevem ser capazes de rodar em qualquer servidor e quantasvezes forem necessárias. Dessa forma, nunca exponha portaspúblicas. Porém, exponha, de maneira privada, as portaspadrões da aplicação.

1 # mapeamento público e privado, evite

2 EXPOSE 80:8080

3

4 # apenas privado

5 EXPOSE 80

150https://jpetazzo.github.io/2015/01/19/dockerfile-and-data-in-volumes/

Page 164: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

ApêndiceContainer ou máquina virtual?

Após o sucesso repentino do Docker - virtualização combase em contêiners - muitas pessoas têm se questionadosobre possível migração do modelo de máquina virtual paracontêiners.

Respondemos tranquilamente: Os dois!

Ambos são métodos de virtualização, mas atuam em “cama-das” distintas. Vale a pena detalhar cada solução para deixarclaro que, não são, necessariamente, concorrentes.

Page 165: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 159

Máquina virtual

Conceito antigo, oriundo dosMainframes emmeados de 1960.Cada operador tinha a visão de estar acessando uma máquinadedicada, mas na verdade, todo recurso do Mainframe, eracompartilhado para todos os operadores.

O objetivo do modelo é compartilhar recursos físicos entrevários ambientes isolados, sendo que, cada um deles tem sobtutela umamáquina inteira: commemória, disco, processador,rede e outros periféricos, todos entregues via abstração devirtualização.

É como se dentro da máquina física, se criasse máquinas me-nores e independentes entre sí. Cadamáquina tem seu própriosistema operacional completo que, por sua vez, interage comos hardwares virtuais que lhe foram entregues pelo modelode virtualização a nível de máquina.

Vale ressaltar: o sistema operacional instalado dentro damáquina virtual fará interação com os hardwares virtuais enão com o hardware real.

Page 166: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 160

Com a evolução dessemodelo, os softwares que implementama solução, puderam oferecer mais funcionalidades, tais comomelhor interface para gerência de ambientes virtuais e altadisponibilidade utilizando vários hosts físicos.

Com as novas funcionalidades de gerência de ambientes demáquinas virtuais é possível especificar quanto recurso físicocada ambiente virtual usa e, até mesmo, aumentar gradual-mente em caso de necessidade pontual.

Atualmente, as máquinas virtuais são realidade para qualquerorganização que necessite de ambiente de TI, pois facilita agerência das máquinas físicas e o compartilhamento entre osdiversos ambientes necessários para a infraestrutura básica.

Page 167: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 161

Contêiner

Esse modelo de virtualização está no nível de sistema opera-cional, ou seja, ao contrário da máquina virtual, um contêinernão tem visão da máquina inteira, é apenas processo emexecução em um kernel compartilhado entre todos os outroscontêiners.

Utiliza o namespace para prover o devido isolamento dememória RAM, processamento, disco e acesso à rede. Mesmocompartilhando o mesmo kernel, esse processo em execuçãotem a visão de estar usando um sistema operacional dedicado.

É um modelo de virtualização relativamente antigo. Em mea-dos de 1982, o chroot já fazia algo que podemos considerarvirtualização a nível de sistema operacional e, em 2008, oLXC já fazia algo relativamente parecido ao Docker, hoje.Inclusive, no início, o Docker usava o LXC, mas hoje teminterface própria para acessar o namespace, cgroup e afins.

Page 168: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 162

Como solução inovadora o Docker traz diversos serviços enovas facilidades que deixam o modelo muito mais atrativo.

A configuração de ambiente LXC não era tarefa simples; eranecessário algum conhecimento técnico médio para criar emanter um ambiente com ele. Com o advento do Docker,esse processo ficou bemmais simples. Basta instalar o binário,baixar as imagens e executá-las.

Outra novidade do Docker foi a criação do conceito de “ima-gens”. Grosseiramente podemos descrever as imagens comodefinições estáticas daquilo que os contêiners devem ser nainicialização. São como fotografias do ambiente. Uma vezinstanciadas e, colocadas em execução, assumem a função decontêiners; saem da abstração de definição e se transformamem processos em execução, dentro de um contexto isolado.Enxergam um sistema operacional dedicado para sí, mas naverdade compartilham o mesmo kernel.

Junto à facilidade de uso dos contêiners, o Docker agregouo conceito de nuvem, que dispõe de serviço para carregar e“baixar” imagens Docker. Trata-se de aplicação web que dis-ponibiliza repositório de ambientes prontos, onde viabilizouum nível absurdo de compartilhamento de ambientes.

Com o uso do serviço de nuvem do Docker, podemos perceberque a adoção do modelo de contêiners ultrapassa a questãotécnica e adentra assuntos de processo, gerência e atualizaçãodo ambiente; onde, agora é possível compartilhar facilmenteas mudanças e viabilizar uma gestão centralizada das defini-ções de ambiente.

Utilizando a nuvem Docker agora, é possível disponibilizarambientes de teste mais leves, permitindo que, em plenareunião com o chefe, você pode baixar a solução para umproblema que ele descreve e mostrar antes que ele saia da

Page 169: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 163

sala. Permite também que você consiga disponibilizar padrãodemelhores práticas para determinado serviço e compartilharcom todos da sua empresa e além, onde pode receber críticase executar modificações com o passar do tempo.

Conclusão

Com os dados apresentados, percebemos que o ponto deconflito entre as soluções é baixo. Podem e, normalmente, sãoadotadas em conjunto. Você pode provisionar uma máquinafísica com um servidor de máquinas virtuais, onde serãocriadas máquinas virtuais hospedes, que por sua vez terãoo docker instalado em cada máquina. Nesse docker serãodisponibilizados os ambientes com seus respectivos serviçossegregados, cada um em um contêiner.

Percebam que teremos vários níveis de isolamento. No pri-meiro, a máquina física, que foi repartida em várias má-quinas virtuais, ou seja, já temos nossa camada de sistemasoperacionais interagindo com hardwares virtuais distintos,como placas de rede virtuais, discos, processo e memória.Nesse ambiente, teríamos apenas o sistema operacional básicoinstalado e o Docker.

No segundo nível de isolamento, temos o Docker baixando asimagens prontas e provisionamento contêiners em execuçãoque, por sua vez, criam novos ambientes isolados, a nível deprocessamento, memória, disco e rede. Nesse caso, podemoster na mesma máquina virtual um ambiente de aplicaçãoweb e banco de dados. Mas em contêiners diferentes e, issonão seria nenhum problema de boas práticas de gerência deserviços, muito menos de segurança.

Page 170: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 164

Caso esses contêiners sejam replicados entre as máquinas vir-tuais, seria possível prover alta disponibilidade sem grandescustos, ou seja, usando um balanceador externo e viabilizandoo cluster dos dados persistidos pelos bancos de dados.

Toda essa facilidade com poucos comandos, recursos e conhe-cimento, basta um pouco de tempo para mudar o paradigmade gerência dos ativos e paciência para lidar com os novosproblemas inerentes do modelo.

Comandos úteis

Seguem alguns comandos úteis e simples abaixo:

• Remover todos os containers sem usodocker container prune

• Parar todos os containersdocker stop $(docker ps -q)

• Remover todas as imagens locaisdocker image prune

Page 171: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 165

• Remove volumes “órfãos”docker volume prune

• Mostra uso de recursos dos containers rodandodocker stats $(docker ps --format {{.Names}})

Posso rodar aplicações GUI?

Com certeza, é plenamente possível rodar aplicações GUI (ouX11) em containers, o que significa que todas as vantagens deutilizar o Docker se aplicam também a aplicações gráficas.

Além disso é possível fazer a aplicação funcionar emmultiplossistemas (Linux, Windows e macOS) apenas construindo elapara Linux.

Como?

Antes de mais nada… Em 99% dos casos é preciso liberar ,oacesso ao X: xhost local (essa liberação ficará vigente atédesligar/reinicar o host)

Comandomais simples o possível, monta o socket X11 do hostno container e define o display (note que vamos “evoluindo” ocomando aos poucos, mas pode usar apenas as flags que acharnecessário - as únicas obrigatórias são a montagem de volumedo /tmp/.X11-unix e a variável de ambiente DISPLAY):

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 imagem [comando]

Page 172: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 166

Em alguns casos a variável DISPLAY tem de ser DISPLAY=unix$DISPLAY(mas pra ser sincero até agora eu não sei bem o motivo,somente que era o indicado pela pessoa que fez a imagem).

Para utilizar o suporte a aceleração 3D por hardware:

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 imagem [comando]

Adicionando audio:

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 --device /dev/snd \

6 imagem [comando]

Adicionando webcam:

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 --device /dev/snd \

6 --device /dev/video0 \

7 imagem [comando]

Usando a mesma data/hora do host:

Page 173: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 167

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 --device /dev/snd \

6 --device /dev/video0 \

7 -v /etc/localtime:/etc/localtime:ro \

8 imagem [comando]

Atenção: dependendo da distribuição, não há um /etc/local-time, tem de averiguar como ela define o timezone e “replicar”no container.

Mantendo as configurações do aplicativo:

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 --device /dev/snd \

6 --device /dev/video0 \

7 -v /etc/localtime:/etc/localtime:ro \

8 -v $HOME/.config/app:/root/.config/app \

9 imagem [comando]

Obs: o caminho é apenas um exemplo.

Bônus: Controle do video-game (na verdade qualquer dispo-sitivo de entrada):

Page 174: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 168

1 docker container run [--rm [-it]|-d] \

2 -v /tmp/.X11-unix:/tmp/.X11-unix \

3 -e DISPLAY \

4 --device /dev/dri \

5 --device /dev/snd \

6 --device /dev/video0 \

7 -v /etc/localtime:/etc/localtime:ro \

8 -v $HOME/.config/app:/root/.config/app \

9 --device /dev/input \

10 imagem [comando]

E o docker-compose?

Funciona normalmente… Basta montar o socket X11 e definira variável de ambiente no docker-compose.yml e será possíveliniciar multiplos aplicativos com apenas um comando.

No Windows e macOS

Mac OS X

Instalar o Docker for Mac

Page 175: Docker para desenvolvedores - tcxsproject.com.br Livros Hacker Gorpo Orko... · TweetSobreEsseLivro! PorfavorajudeRafaelGomesadivulgaresselivrono Twitter! Ahashtagsugeridaparaesselivroé

Apêndice 169

1 brew install socat

2 brew cask install xquartz

3 open -a XQuartz

4

5 socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\

6 \"$DISPLAY\"

7 docker container run -e DISPLAY=hostip:0 [...] im\

8 age OU DISPLAY=hostip:0 docker-compose up [-d]

#### Windows151

Instalar o xmingInstalar o Docker for Windows

1 xming :0 -ac -clipboard -multiwindow

2 docker container run -e DISPLAY=hostip:0 [...] im\

3 age OU DISPLAY=hostip:0 docker-compose up [-d]

Obs: No caso de utilizar o Docker Toolbox colocar o ip da VM(docker-machine ip default irá informá-lo)

151https://github.com/docker/docker/issues/8710#issuecomment-135109677