Você está na página 1de 177

Docker para

desenvolvedores
Rafael Gomes
Esse livro est venda em
http://leanpub.com/dockerparadesenvolvedores

Essa verso foi publicada em 2017-03-07

This is a Leanpub book. Leanpub empowers authors and


publishers with the Lean Publishing process. Lean
Publishing is the act of publishing an in-progress ebook
using lightweight tools and many iterations to get reader
feedback, pivot until you have the right book and build
traction once you do.

This work is licensed under a Creative Commons


Attribution 4.0 International License
Tweet Sobre Esse Livro!
Por favor ajude Rafael Gomes a divulgar esse livro no
Twitter!
A hashtag sugerida para esse livro
#docker-para-desenvolvedores.
Descubra o que as outras pessoas esto falando sobre esse
livro clicando nesse link para buscar a hashtag no Twitter:
https://twitter.com/search?q=#docker-para-desenvolvedores
Contedo

Prefcio . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Abraos, . . . . . . . . . . . . . . . . . . . . . . . 2

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

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

Introduo . . . . . . . . . . . . . . . . . . . . . . . . 8

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

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

Instalao . . . . . . . . . . . . . . . . . . . . . . . . . 21
Instalando no GNU/Linux . . . . . . . . . . . . . . 21
Instalando no MacOS . . . . . . . . . . . . . . . . 25
Instalando no Windows . . . . . . . . . . . . . . . 28

Comandos bsicos . . . . . . . . . . . . . . . . . . . . 32
Executando um container . . . . . . . . . . . . . . 32
Verificando a lista de containers . . . . . . . . . . 36
Gerenciamento de containers . . . . . . . . . . . . 37

Criando sua prpria imagem no Docker . . . . . . . 39

Entendendo armazenamento no Docker . . . . . . . 47


CONTEDO

Entendendo a rede no Docker . . . . . . . . . . . . . 53

Utilizando Docker em mltiplos ambientes . . . . . . 63

Gerenciando mltiplos containers docker com Doc-


ker Compose . . . . . . . . . . . . . . . . . . . . . 73

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

Transformando sua aplicao em container . . . . . 89

Base de cdigo . . . . . . . . . . . . . . . . . . . . . . 91

Dependncia . . . . . . . . . . . . . . . . . . . . . . . 95

Configuraes . . . . . . . . . . . . . . . . . . . . . . 99

Servios de Apoio . . . . . . . . . . . . . . . . . . . . 103

Construa, lance, execute . . . . . . . . . . . . . . . . 107

Processos . . . . . . . . . . . . . . . . . . . . . . . . . 112

Vnculo de portas . . . . . . . . . . . . . . . . . . . . 115

Concorrncia . . . . . . . . . . . . . . . . . . . . . . . 119

Descartabilidade . . . . . . . . . . . . . . . . . . . . . 127

Paridade entre desenvolvimento/produo . . . . . . 132

Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Processos de administrao . . . . . . . . . . . . . . 137

Dicas para uso do Docker . . . . . . . . . . . . . . . . 141


Dicas para Rodar . . . . . . . . . . . . . . . . . . . 141
Boas prticas para construo de imagens . . . . . 150
CONTEDO

Apndice . . . . . . . . . . . . . . . . . . . . . . . . . 160
Container ou mquina virtual? . . . . . . . . . . . 160
Comandos teis . . . . . . . . . . . . . . . . . . . 166
Posso rodar aplicaes GUI? . . . . . . . . . . . . 167
Prefcio
No desenvolvimento de software comum criar-se boas prti-
cas a padres. Em especfico a aplicaes web, certos conceitos
e prticas como DevOps, infraestrutura em Nuvem, phoenix,
imutvel e 12 factor apps so teorias bem aceitas que ajudam
na produtividade e manuteno dos sistemas. Por serem con-
ceitos no to novos, so muitas as ferramentas e sistemas
que podem auxiliar na implantao desses. Mas Docker uma
das primeiras e mais comentadas ferramentas e plataformas
que combina tantos desses conceitos de maneira coesa e
relativamente simples de usar. Como qualquer ferramenta,
Docker um investimento que oferece melhor retorno quando
se entende seu propsito e como usa-lo apropriadamente.
Existem vrias apresentaes, artigos e documentaes sobre
Docker. Porm existia a oportunidade de um livro ligando
a teoria com a prtica da ferramenta. Em que o leitor pode
entender as motivaes de Docker e tambm como organizar
sua aplicao para extrair o maior proveito da ferramenta.
Estou muito alegre que o Rafael escreveu este livro, que
acredito ser uma contribuio importante para nossa rea. O
Rafael extremamente engajado na comunidade de Docker
e Devops pelo Brasil, alm disso entende o que as pessoas
buscam de conhecimento na rea. Nesse livro voc vai poder
entender o bsico sobre Docker com uma liguagem simples e
vrios exemplos prticos. Espero que esse livro seja mais um
passo para impulsionar sua jornada. Desejo-lhe sucesso e tudo
de melhor.
Prefcio 2

Abraos,
Lus Armando Bianchin
Como ler esse livro
Esse material foi dividido em duas grandes partes. A primeira
trata das questes mais bsicas do Docker. exatamente o
mnimo necessrio que um desenvolvedor precisa saber para
utilizar essa tecnologia com propriedade, ou seja, ciente do
que exatamente acontece ao executar cada comando.
Nessa primeira parte tentaremos no abordar questes de
baixo nvel do Docker, pois so de maior apelo para a equipe
responsvel pela infraestrutura.
Caso voc no saiba nada sobre Docker, aconselhamos muito
a leitura dessa primeira parte, pois assim conseguir aprovei-
tar a segunda parte, focada na construo de uma aplicao
web no Docker seguindo as melhores prticas, sem pausas.
Neste livro, adotamos as prticas do 12factor.
O 12factor ser detalhado no incio da segunda parte, mas
podemos adiantar que o consideramos os 12 mandamentos
para aplicaes web no Docker, ou seja, uma vez que sua
aplicao siga todas as boas prticas apresentadas neste docu-
mento, voc possivelmente estar usando todo potencial que
o Docker tem a lhe proporcionar.
Essa segunda parte dividida por cada boa prtica do 12fac-
tor. Dessa forma, apresentamos um cdigo de exemplo no
primeiro captulo, que ser evoludo ao longo do desenvol-
vimento do livro. A ideia que voc possa exercitar com um
cdigo de verdade e, assim, assimilar o contedo de forma
https://12factor.net/pt_br/
Como ler esse livro 4

prtica. Tambm organizamos alguns apndices com assuntos


extras importantes, mas que no se encaixaram nos captulos.
Agradecimentos
Meu primeiro agradecimento vai para a pessoa que me deu a
chance de estar aqui e poder escrever esse livro: minha me.
A famosa Cigana, ou Dona Arlete, pessoa maravilhosa, que
pra mim um exemplo de ser humano.
Quero agradecer tambm a minha segunda me, Dona Maria,
que tanto cuidou de mim quando eu era criana, enquanto
Dona Arlete tomava conta dos outros dois filhos e um sobri-
nho. Me sinto sortudo por ter duas, enquanto muitos no tem
ao menos uma me.
Aproveito para agradecer a pessoa que me apresentou o
Docker, Robinho, tambm conhecido como Robson Peixoto.
Em uma conversa informal no evento Lingugil, em Salvador
(BA), ele me falou: Estude Docker! E, aqui estou eu termi-
nando um livro que transformou a minha vida. Obrigado de
verdade Robinho!
Obrigado a Lus Armando Bianchin, que comeou como autor
junto comigo, mas depois por fora do destino acabou no
podendo continuar. Fica aqui meu agradecimento, pois foi
com seu feedback constante que pude continuar a fazer o
livro.
Obrigado a Paulo Caroli que tanto me incentivou a escrever
o livro e indicou a plataforma Leanpub pra fazer isso. Se no
fosse ele, o livro no teria sado to rpido.
https://twitter.com/robinhopeixoto
Agradecimentos 6

Obrigada a fantstica Emma Pinheiro, pela belssima capa.


Quero agradecer muito as pessoas incrveis do Raul Hacker
Club que tanto me incentivaram em todo esse tempo.
Quero agradecer a me do meu filho, Eriane Soares, hoje
minha grande amiga que tanto me incentivou a escrever o
livro enquanto morvamos juntos!
Como todo produto de conhecimento aberto, esse livro no
seria possvel sem ajuda dessa vibrante comunidade Docker
Brasil. Para alguns membros darei destaque pelo empenho ao
ler diversos captulos inmeras vezes e dedicar seu precioso
tempo sugerindo melhorias:

Gjuniioor gjuniioor@protonmail.ch
Marco Antonio Martins Junior - Escreveu os captulos
Posso rodar aplicaes GUI e Comandos teis.
Jorge Flvio Costa
Glesio Paiva
Bruno Emanuel Silva
George Moura
Felipe de Morais
Waldemar Neto
Igor Garcia
https://twitter.com/n3k00n3
http://raulhc.cc/
https://twitter.com/somatorio
https://twitter.com/JFCostta
https://twitter.com/glesio
https://twitter.com/jwalker_pe
https://twitter.com/georgemoura
https://twitter.com/felipedemorais_
https://twitter.com/waldemarnt
Agradecimentos 7

Diogo Fernandes

bem possvel que eu tenha esquecido o nome de pessoas


aqui, mas a medida que for resgatando meus logs, vou atua-
lizar.
https://twitter.com/diogocfernandes
Introduo
Essa parte do livro direcionada a quem no tem conhe-
cimento bsico do Docker. Caso voc j saiba usar, fique
vontade para pular. Entretanto, mesmo que voc j conhea
o Docker, apresentamos explicaes sobre vrios recursos
disponveis e como funcionam.
Mesmo que voc j use o Docker, ler essa parte do livro, em
algum momento da sua vida, pode ser importante para saber
de forma mais consistente o que acontece com cada comando
executado.
Por que usar Docker?
Docker tem sido um assunto bem comentado ultimamente,
muitos artigos foram escritos, geralmente tratando sobre como
us-lo, ferramentas auxiliares, integraes e afins, mas muitas
pessoas ainda fazem a pergunta mais bsica quando se trata
da possibilidade de utilizar qualquer nova tecnologia: Por
que devo usar isso? Ou seria: O que isso tem a me oferecer
diferente do que j tenho hoje?

normal que ainda duvidem do potencial do Docker, alguns


at acham que se trata de um hype. Mas nesse captulo
http://techfree.com.br/2015/06/sera-que-esse-modelo-de-containers-e-um-hype/
Por que usar Docker? 10

pretendemos demonstrar alguns bons motivos para se utilizar


Docker.
Vale frisar que o Docker no uma bala de prata - ele no se
prope a resolver todos problemas, muito menos ser a soluo
nica para as mais variadas situaes.
Abaixo alguns bons motivos para se utilizar Docker:

1 Ambientes semelhantes
Uma vez que sua aplicao seja transformada em uma ima-
gem Docker, ela pode ser instanciada como container em
qualquer ambiente que desejar. Isso significa que poder uti-
lizar sua aplicao no notebook do desenvolvedor da mesma
forma que seria executada no servidor de produo.
A imagem Docker aceita parmetros durante o incio do
container, isso indica que a mesma imagem pode se comportar
de formas diferentes entre distintos ambientes. Esse container
pode conectar-se a seu banco de dados local para testes,
usando as credenciais e base de dados de teste. Mas quando
o container, criado a partir da mesma imagem, receber par-
metros do ambiente de produo, acessar a base de dados
em uma infraestrutura mais robusta, com suas respectivas
credenciais e base de dados de produo, por exemplo.
As imagens Docker podem ser consideradas como implan-
taes atmicas - o que proporciona maior previsibilidade
comparado a outras ferramentas como Puppet, Chef, Ansible,
etc - impactando positivamente na anlise de erros, assim
como na confiabilidade do processo de entrega contnua,
que se baseia fortemente na criao de um nico artefato que
https://www.thoughtworks.com/continuous-delivery
Por que usar Docker? 11

migra entre ambientes. No caso do Docker, o artefato seria a


prpria imagem com todas as dependncias requeridas para
executar seu cdigo, seja ele compilado ou dinmico.

2 Aplicao como pacote completo


Utilizando as imagens Docker possvel empacotar toda
sua aplicao e dependncias, facilitando a distribuio, pois
no ser mais necessrio enviar uma extensa documentao
explicando como configurar a infraestrutura necessria para
permitir a execuo, basta disponibilizar a imagem em repo-
sitrio e liberar o acesso para o usurio e, ele mesmo pode
baixar o pacote, que ser executado sem problemas.
A atualizao tambm positivamente afetada, pois a es-
trutura de camadas do Docker viabiliza que, em caso de
mudana, apenas a parte modificada seja transferida e assim o
ambiente pode ser alterado de forma mais rpida e simples. O
usurio precisa executar apenas um comando para atualizar
a imagem da aplicao, que ser refletida no container em
execuo apenas no momento desejado. As imagens Docker
podem utilizar tags e, assim, viabilizar o armazenamento de
mltiplas verses da mesma aplicao. Isso significa que em
caso de problema na atualizao, o plano de retorno ser
basicamente utilizar a imagem com a tag anterior.

3 Padronizao e replicao
Como as imagens Docker so construdas atravs de arquivos
de definio, possvel garantir que determinado padro
http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/
https://docs.docker.com/engine/reference/builder/
Por que usar Docker? 12

seja seguido, aumentando a confiana na replicao. Basta


que as imagens sigam as melhores prticas de construo
para que seja vivel escalarmos a estrutura rapidamente.
Caso a equipe receba uma nova pessoa para trabalhar no
desenvolvimento, essa poder receber o ambiente de trabalho
com alguns comandos. Esse processo durar o tempo do
download das imagens a serem utilizadas, assim como os
arquivos de definies da orquestrao das mesmas. Isso
facilita a introduo de um novo membro no processo de
desenvolvimento da aplicao, que poder reproduzir rapida-
mente o ambiente em sua estao e assim desenvolver cdigos
seguindo o padro da equipe.
Na necessidade de se testar nova verso de determinada parte
da soluo, usando imagens Docker, normalmente basta a
mudana de um ou mais parmetros do arquivo de definio
para iniciar um ambiente modificado com a verso requerida
para avaliao. Ou seja: criar e modificar a infraestrutura
ficou bem mais fcil e rpido.

4 Idioma comum entre Infraestrutura


e desenvolvimento
A sintaxe usada para parametrizar as imagens e ambientes
Docker pode ser considerada um idioma comum entre reas
que costumeiramente no dialogavam bem. Agora possvel
ambos os setores apresentarem propostas e contra propostas
com base em um documento comum.
A infraestrutura requerida estar presente no cdigo do de-
senvolvedor e a rea de infraestrutura poder analisar o
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
https://pt.wikipedia.org/wiki/Escalabilidade
Por que usar Docker? 13

documento, sugerindo mudanas para adequao de padres


do seu setor ou no. Tudo isso em comentrios e aceitao
de merge ou pull request do sistema de controle de verso de
cdigos.

5 Comunidade
Assim como possvel acessar o github ou gitlab procura
de exemplos de cdigo, usando o repositrio de imagens do
Docker possvel conseguir bons modelos de infraestrutura
de aplicaes ou servios prontos para integraes complexas.
Um exemplo o nginx como proxy reverso e mysql como
banco de dados. Caso a aplicao necessite desses dois recur-
sos, voc no precisa perder tempo instalando e configurando
totalmente esses servios. Basta utilizar as imagens do reposi-
trio, configurando parmetros mnimos para adequao com
o ambiente. Normalmente as imagens oficiais seguem as boas
prticas de uso dos servios oferecidos.
Utilizar essas imagens no significa ficar refm da confi-
gurao trazida com elas, pois possvel enviar sua prpria
configurao para os ambientes e evitar apenas o trabalho da
instalao bsica.

Dvidas
Algumas pessoas enviaram dvidas relacionadas s vanta-
gens que explicitamos nesse texto. Assim, ao invs de respond-
http://github.com/
https://about.gitlab.com/
http://hub.docker.com/
https://hub.docker.com/_/nginx/
https://hub.docker.com/_/mysql/
Por que usar Docker? 14

las pontualmente, resolvemos publicar as perguntas e as res-


pectivas respostas aqui.

Qual a diferena entre imagem Docker e


definies criadas por ferramenta de
automao de infraestrutura?

Como exemplo de ferramentas de automao de infraestru-


tura temos o Puppet, Ansible e Chef. Elas podem garantir
ambientes parecidos, uma vez que faz parte do seu papel
manter determinada configurao no ativo desejado.
A diferena entre a soluo Docker e gerncia de configurao
pode parecer bem tnue, pois ambas podem suportar a confi-
gurao necessria de toda infraestrutura que uma aplicao
demanda para ser implantada, mas achamos que uma das
distines mais relevante est no seguinte fato: a imagem
uma abstrao completa e no requer qualquer tratamento
para lidar com as mais variadas distribuies GNU/Linux
existentes, j que a imagem Docker carrega em si uma cpia
completa dos arquivos de uma distribuio enxuta.
Carregar em si a cpia de uma distribuio GNU/Linux
no costuma ser problema para o Docker, pois utilizando o
modelo de camadas, economiza bastante recurso, reutilizando
as camadas de base. Leia esse artigo para entender mais
sobre armazenamento do Docker.
Outra vantagem da imagem em relao a gerncia de confi-
gurao que, utilizando a imagem, possvel disponibilizar
o pacote completo da aplicao em um repositrio e, esse
https://puppetlabs.com/
https://www.ansible.com/
https://www.chef.io/chef/
http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/
Por que usar Docker? 15

produto final, ser utilizado facilmente sem necessidade de


configurao completa. Apenas um arquivo de configurao
e um comando custumam ser suficientes para iniciar uma
aplicao criada como imagem Docker.
Ainda sobre o processo de imagem Docker como produto no
repositrio: pode ser usado tambm no processo de atualiza-
o da aplicao, como j explicamos nesse captulo.

O uso da imagem base no Docker de


determinada distribuio no o mesmo que
criar uma definio de gerncia de configurao
para uma distribuio?

No! A diferena est na perspectiva do hospedeiro. No caso


do Docker no importa qual distribuio GNU/Linux utili-
zada no host, pois h uma parte da imagem que carrega todos
os arquivos de uma mini distribuio que ser suficiente para
suportar tudo que a aplicao precisa. Caso seu Docker host
seja Fedora e a aplicao precisar de arquivos do Debian, no
se preocupe, pois a imagem em questo trar arquivos Debian
para suportar o ambiente. E, como j foi dito anteriormente,
isso normalmente no chega a impactar negativamente no
consumo de espao em disco.

Quer dizer ento que agora eu, desenvolvedor,


preciso me preocupar com tudo da
Infraestrutura?

No! Quando citamos que possvel o desenvolvedor especifi-


car a infraestrutura, estamos falando da camada mais prxima
da aplicao e no de toda a arquitetura necessria (Sistema
operacional bsico, regras de firewall, rotas de rede e etc).
Por que usar Docker? 16

A ideia do Docker que os assuntos relevantes e diretamente


ligados a aplicao possam ser configurados pelo desenvol-
vedor. Isso no o obriga a realizar essa atividade. uma
possibilidade que agrada muitos desenvolvedores, mas caso
no seja a situao, pode ficar tranquilo, outra equipe tratar
dessa parte. Apenas o processo de implantao ser pouco
mais lento.

Muitas pessoas falam de Docker para micro


servios. possvel usar o Docker para
aplicaes monolticas?

Sim! Porm, em alguns casos, necessrio pequenas modifica-


es na aplicao, para que ela possa usufruir das facilidades
do Docker. Um exemplo comum o log que, normalmente,
a aplicao envia para determinado arquivo, ou seja, no
modelo Docker as aplicaes que esto nos containers no
devem tentar escrever ou gerir arquivos de logs. Ao invs
disso, cada processo em execuo escreve seu prprio fluxo de
evento, sem buffer, para o stdout, pois o Docker tem drivers
especficos para tratar o log enviado dessa forma. Essa parte
de melhores prticas de gerenciador de logs ser detalhada em
captulos posteriores.
Em alguns momentos voc perceber que o uso do Docker
para sua aplicao demanda muito esforo. Nesses casos,
normalmente, o problema est mais em como a aplicao
trabalha do que na configurao do Docker. Esteja atento.
Tem mais dvidas e/ou bons motivos para utilizar Docker?
Comente aqui.
https://pt.wikipedia.org/wiki/Fluxos_padr%C3%A3o
http://techfree.com.br/2016/03/porque-usar-docker/
O que Docker?
De forma bem resumida, podemos dizer que o Docker
uma plataforma aberta, criada com o objetivo de facilitar o
desenvolvimento, a implantao e a execuo de aplicaes
em ambientes isolados. Foi desenhada especialmente para
disponibilizar uma aplicao da forma mais rpida possvel.

Usando o Docker, voc pode facilmente gerenciar a infra-


estrutura da aplicao, isso agilizar o processo de criao,
manuteno e modificao do seu servio.
Todo processo realizado sem necessidade de qualquer acesso
privilegiado infraestrutura corporativa. Assim, a equipe
responsvel pela aplicao pode participar da especificao do
ambiente junto com a equipe responsvel 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 definies
O que Docker? 18

da infraestrutura necessria e como a aplicao ser disposta


nesse ambiente, em qual porta fornecer seu servio, quais da-
dos de volumes externos sero requisitados e outras possveis
necessidades.
O Docker tambm disponibiliza uma nuvem pblica para
compartilhamento de ambientes prontos, que podem ser uti-
lizados para viabilizar customizaes para ambientes espec-
ficos. possvel obter uma imagem pronta do apache e con-
figurar os mdulos especficos necessrios para a aplicao
e, assim, criar seu prprio ambiente customizado. Tudo com
poucas linhas de descrio.
O Docker utiliza o modelo de container para empacotar
a aplicao que, aps ser transformada em imagem Docker,
pode ser reproduzida em plataforma de qualquer porte; ou
seja, caso a aplicao funcione sem falhas em seu notebook,
funcionar tambm no servidor ou no mainframe. Construa
uma vez, execute onde quiser.
Os containers so isolados a nvel de disco, memria, pro-
cessamento e rede. Essa separao permite grande flexibili-
dade, onde ambientes distintos podem coexistir no mesmo
host, sem causar qualquer problema. Vale salientar que o
overhead nesse processo o mnimo necessrio, pois cada
container normalmente carrega apenas um processo, que
aquele responsvel pela entrega do servio desejado. Em
todo caso, esse container tambm carrega todos os arquivos
necessrios (configurao, biblioteca e afins) para execuo
completamente isolada.
Outro ponto interessante no Docker a velocidade para
viabilizar o ambiente desejado; como basicamente o incio
de um processo e no um sistema operacional inteiro, o tempo
de disponibilizao , normalmente, medido em segundos.
O que Docker? 19

Virtualizao a nvel do sistema


operacional
O modelo de isolamento utilizado no Docker a virtualizao
a nvel do sistema operacional, um mtodo de virtualizao
onde o kernel do sistema operacional permite que mltiplos
processos sejam executados isoladamente no mesmo host.
Esses processos isolados em execuo so denominados no
Docker de container.

Para criar o isolamento necessrio do processo, o Docker usa a


funcionalidade do kernel, denominada de namespaces, que
cria ambientes isolados entre containers: os processos de uma
aplicao em execuo no tero acesso aos recursos de outra.
A menos que seja expressamente liberado na configurao de
cada ambiente.
http://man7.org/linux/man-pages/man7/namespaces.7.html
O que Docker? 20

Para evitar a exausto dos recursos da mquina por apenas


um ambiente isolado, o Docker usa a funcionalidade cgroups
do kernel, responsvel por criar limites de uso do hardware
a disposio. Com isso possvel coexistir no mesmo host
diferentes containers sem que um afete diretamente o outro
por uso exagerado dos recursos compartilhados.
https://en.wikipedia.org/wiki/Cgroups
Instalao
O Docker deixou de ser apenas um software para virar um
conjunto deles: um ecossistema.
Nesse ecossistema temos os seguintes softwares:

Docker Engine: o software base de toda soluo.


tanto o daemon responsvel pelos containers como o
cliente usado para enviar comandos para o daemon.
Docker Compose: a ferramenta responsvel pela
definio e execuo de mltiplos containers com base
em arquivo de definio.
Docker Machine: a ferramenta que possibilita criar e
manter ambientes docker em mquinas virtuais, ambi-
entes de nuvem e at mesmo em mquina fsica.

No citamos o Swarm e outras ferramentas por no estarem


alinhados com o objetivo desse livro: introduo para desen-
volvedores.

Instalando no GNU/Linux
Explicamos a instalao da forma mais genrica possvel,
dessa forma voc poder instalar as ferramentas em qualquer
distribuio GNU/Linux que esteja usando.
https://docs.docker.com/swarm/overview/
Instalao 22

Docker engine no GNU/Linux


Para instalar o docker engine simples. Acesse seu terminal
preferido do GNU/Linux e torne-se usurio root:

1 su - root

ou no caso da utilizao 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 no


seu sistema operacional. Acesse esse link e analise o cdigo
assim que tiver tempo para faz-lo.
Esse procedimento demora um pouco. Aps terminar o teste,
execute o comando abaixo:

1 docker container run hello-world

Tratamento de possveis problemas

Se o acesso a internet da mquina passar por controle de


trfego (aquele que bloqueia o acesso a determinadas pginas)
voc poder encontrar problemas no passo do apt-key. Caso
enfrente esse problema, execute o comando abaixo:
https://get.docker.com/
Instalao 23

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


2 ey add -

Docker compose no GNU/Linux


Acesse o seu terminal preferido do GNU/Linux e torne-se
usurio root:

1 su - root

ou no caso da utilizao de sudo

1 sudo su - root

Execute o comando abaixo:

1 curl -L https://github.com/docker/compose/release\
2 s/download/1.6.2/docker-compose-`uname -s`-`uname\
3 -m` > /usr/local/bin/docker-compose
4 chmod +x /usr/local/bin/docker-compose

Para testar, execute o comando abaixo:

1 docker-compose version

Instalando Docker compose com pip

O pip um gerenciador de pacotes Python e, como o docker-


compose, escrito nessa linguagem, possvel instal-lo da
seguinte forma:
https://en.wikipedia.org/wiki/Pip_(package_manager)
Instalao 24

1 pip install docker-compose

Docker machine no GNU/Linux


Instalar o docker machine simples. Acesse o seu terminal
preferido do GNU/Linux e torne-se usurio root:

1 su - root

ou no caso da utilizao de sudo

1 sudo su - root

Execute o comando abaixo:

1 $ curl -L https://github.com/docker/machine/relea\
2 ses/download/v0.7.0/docker-machine-`uname -s`-`un\
3 ame -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 verso mais recente no


momento desta publicao. Verifique se h alguma verso
atualizada consultando a documentao oficial.
https://docs.docker.com/machine/install-machine/
Instalao 25

Instalando no MacOS
A instalao das ferramentas do Ecossistema Docker no Ma-
cOS realizada atravs de um nico grande pacote chamado
Docker Toolbox.
Voc pode instalar via brew cask com o comando abaixo:

1 brew cask install docker-toolbox

Tambm pode instalar manualmente acessando a pgina de


download do Docker toolbox e baixando o instalador cor-
respondente ao MacOS.
Aps duplo clique no instalador, ver essa tela:

Apenas clique em Continue.


https://www.docker.com/products/docker-toolbox
Instalao 26

Marque todas as opes e clique Install.


Ser solicitado seu usurio e senha para liberar a instalao
dos softwares. Preencha e continue o processo.
Na prxima tela, ser apresentado as ferramentas que podem
ser usadas para facilitar sua utilizao do Docker no MacOS.
Instalao 27

Apenas clique em Continue.


Essa ultima janela que ver no processo de instalao.
Instalao 28

Apenas clique em Close e finalize a instalao.


Para testar, procure e execute o software Docker Quickstart
Terminal, pois ele far todo processo necessrio para comear
a utilizar o Docker.
Nesse novo terminal execute o seguinte comando para teste:

1 docker container run hello-world

Instalando no Windows
A instalao das ferramentas do Ecossistema Docker no Win-
dows realizada atravs de um nico grande pacote, que se
chama Docker Toolbox.
O Docker Toolbox funciona apenas em verses 64bit do
https://support.microsoft.com/en-us/kb/827218
Instalao 29

Windows e soemnte para as verses superiores ao Windows


7.
importante salientar tambm que necessrio habilitar o
suporte de virtualizao. Na verso 8 do Windows, possvel
verificar atravs do Task Manager. Na aba Performance
clique em CPU para visualizar a janela abaixo:

Para verificar o suporte a virtualizao do Windows 7, utilize


esse link para maiores informaes.

Instalando o Docker Toolbox


Acesse a pgina de download do Docker toolbox e baixe o
instalador correspondente ao Windows.
Aps duplo clique no instalador, ver essa tela:
http://www.microsoft.com/en-us/download/details.aspx?id=592
https://www.docker.com/products/docker-toolbox
Instalao 30

Apenas clique em Next.


Instalao 31

Por fim, clique em Finish.


Para testar, procure e execute o software Docker Quickstart
Terminal, pois ele far todo processo necessrio para comear
a utilizar o Docker.
Nesse novo terminal execute o seguinte comando para teste:

1 docker container run hello-world


Comandos bsicos
Para utilizao do Docker necessrio conhecer alguns co-
mandos e entender de forma clara e direta para que servem,
assim como alguns exemplos de uso.
No abordaremos os comandos de criao de imagem e tra-
tamento de problemas (troubleshooting) no Docker, pois tm
captulos especficos para o detalhamento.

Executando um container
Para iniciar um container necessrio saber a partir de
qual imagem ser executado. Para listar as imagens que seu
Docker host tem localmente, execute o comando abaixo:

1 docker image list

As imagens retornadas esto presentes no seu Docker host


e no demandam qualquer download da nuvem pblica do
Docker, a menos que deseje atualiz-la. Para atualizar a
imagem basta executar o comando abaixo:

1 docker image pull python

hub.docker.com
Comandos bsicos 33

Usamos a imagem chamada python como exemplo, mas caso


deseje atualizar qualquer outra imagem, basta colocar seu
nome 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 inspect responsvel por informar todos os


dados referentes imagem.
Agora que temos a imagem atualizada e inspecionada, pode-
mos iniciar o container. Mas antes de simplesmente copiar
e colar o comando, vamos entender como ele realmente
funciona.

1 docker container run <parmetros> <imagem> <CMD> \


2 <argumentos>

Os parmetros mais utilizados na execuo do container so:

Parmetro Explicao
-d Execuo do container em
background
-i Modo interativo. Mantm o STDIN
aberto mesmo sem console anexado
-t Aloca uma pseudo TTY
rm Automaticamente remove o
container aps finalizao (No
funciona com -d)
name Nomear o container

https://docs.docker.com/engine/reference/commandline/inspect/
Comandos bsicos 34

Parmetro Explicao
-v Mapeamento de volume
-p Mapeamento de porta
-m Limitar o uso de memria 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 container


com o nome meu_python, criado a partir da imagem python
e o processo executado nesse container ser o bash.
Vale lembrar que, caso o CMD no seja especificado no
comando docker container run, utilizado o valor padro
definido no Dockerfile da imagem utilizada. No nosso caso
python e seu comando padro executa o binrio python, ou
seja, se no fosse especificado o bash, no final do comando
de exemplo acima, ao invs de um shell bash do GNU/Linux,
seria exibido um shell do python.

Mapeamento de volumes
Para realizar mapeamento de volume basta especificar qual
origem do dado no host e onde deve ser montado dentro do
container.

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


2 er>" python

O uso de armazenamento melhor explicado em captulos


futuros, por isso no detalharemos o uso desse parmetro.
Comandos bsicos 35

Mapeamento de portas
Para realizar o mapeamento de portas basta saber qual porta
ser mapeada no host e qual deve receber essa conexo dentro
do container.

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


2 er>" python

Um exemplo com a porta 80 do host para uma porta 8080


dentro do container tem o seguinte comando:

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

Com o comando acima temos a porta 80 acessvel no Docker


host que repassa todas as conexes para a porta 8080 dentro
do container. Ou seja, no possvel acessar a porta 8080 no
endereo IP do Docker host, pois essa porta est acessvel
apenas dentro do container que isolada a nvel de rede,
como j dito anteriormente.

Gerenciamento dos recursos


Na inicializao dos containers possvel especificar alguns
limites de utilizao dos recursos. Trataremos aqui apenas de
memria RAM e CPU, os mais utilizados.
Para limitar o uso de memria RAM que pode ser utilizada
por esse container, basta executar o comando abaixo:
Comandos bsicos 36

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

Com o comando acima estamos limitando esse container a


utilizar somente 512 MB de RAM.
Para balancear o uso da CPU pelos containers, utilizamos
especificao de pesos para cada container, quanto menor o
peso, menor sua prioridade no uso. Os pesos podem oscilar de
1 a 1024.
Caso no seja especificado o peso do container, ele usar o
maior peso possvel, nesse caso 1024.
Usaremos como exemplo o peso 512:

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

Para entendimento, vamos imaginar que trs containers fo-


ram colocados em execuo. Um deles tem o peso padro 1024
e dois tm o peso 512. Caso os trs processos demandem toda
CPU o tempo de uso deles ser dividido da seguinte maneira:

O processo com peso 1024 usar 50% do tempo de


processamento
Os dois processos com peso 512 usaro 25% do tempo
de processamento, cada.

Verificando a lista de containers


Para visualizar a lista de containers de um determinado
Docker host utilizamos o comando docker ps.
Esse comando responsvel por mostrar todos os containers,
mesmo aqueles no mais em execuo.
https://docs.docker.com/engine/reference/commandline/ps/
Comandos bsicos 37

1 docker container list <parmetros>

Os parmetros mais utilizados na execuo do container so:

Parmetro Explicao
-a Lista todos os containers, inclusive
os 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 utilizao em scripts

Gerenciamento de containers
Uma vez iniciado o container a partir de uma imagem
possvel gerenciar a utilizao com novos comandos.
Caso deseje desligar o container basta utilizar o comando
docker stop. Ele recebe como argumento o ID ou nome do
container. Ambos os dados podem ser obtidos com o docker
ps, explicado no tpico anterior.
Um exemplo de uso:

1 docker container stop meu_python

No comando acima, caso houvesse um container chamado


meu_python em execuo, ele receberia um sinal SIGTERM
https://docs.docker.com/engine/reference/commandline/stop/
Comandos bsicos 38

e, caso no fosse desligado, receberia um SIGKILL depois de


10 segundos.
Caso deseje reiniciar o container que foi desligado e no
iniciar um novo, basta executar o comando docker start:

1 docker container start meu_python

Vale ressaltar que a ideia dos containers a de


serem descartveis. Caso voc use o mesmo con-
tainer por muito tempo sem descart-lo, prova-
velmente est usando o Docker incorretamente.
O Docker no uma mquina, um processo
em execuo. E, como todo processo, deve ser
descartado para que outro possa tomar seu lugar
na reinicializao do mesmo.

https://docs.docker.com/engine/reference/commandline/start/
Criando sua prpria
imagem no Docker
Antes de explicarmos como criar sua imagem, vale a pena
tocarmos em uma questo que normalmente confunde inici-
antes do docker: Imagem ou container?

Qual a diferena entre Imagem e


Container?
Traando um paralelo com o conceito de orientao a objeto,
a imagem a classe e o container o objeto. A imagem
a abstrao da infraestrutura em estado somente leitura, de
onde ser instanciado o container.
Todo container iniciado a partir de uma imagem, dessa
forma podemos concluir que nunca teremos uma imagem em
execuo.
Um container s pode ser iniciado a partir de uma nica
imagem. Caso deseje um comportamento diferente, ser ne-
cessrio customizar a imagem.

Anatomia da imagem
As imagens podem ser oficiais ou no oficiais.
https://pt.wikipedia.org/wiki/Orienta%C3%A7%C3%A3o_a_objetos
Criando sua prpria imagem no Docker 40

Imagens oficiais e no oficiais

As imagens oficiais do docker so aquelas sem usurios em


seus nomes. A imagem ubuntu:16.04 oficial, por ou-
tro lado, a imagem nuagebec/ubuntu no oficial. Essa
segunda imagem mantida pelo usurio nuagebec, que
mantm outras imagens no oficiais.
As imagens oficiais so mantidas pela empresa docker e
disponibilizadas na nuvem docker.
O objetivo das imagens oficiais prover um ambiente bsico
(ex. debian, alpine, ruby, python), um ponto de partida para
criao de imagens pelos usurios, como explicaremos mais
adiante, ainda nesse captulo.
As imagens no oficiais so mantidas pelos usurios que
as criaram. Falaremos sobre envio de imagens para nuvem
docker em outro tpico.
Nome da imagem
O nome de uma imagem oficial composto por duas partes.
A primeira, a documentao chama de repositrio e, a se-
gunda, chamada de tag. No caso da imagem ubuntu:14.04,
ubuntu o repositrio e 14.04 a tag.
Para o docker, o repositrio uma abstrao do conjunto
de imagens. No confunda com o local de armazenamento das
imagens, que detalharemos mais adiante. J a tag, uma
abstrao para criar unidade dentro do conjunto de imagens
definidas no repositrio.
https://hub.docker.com/r/nuagebec/ubuntu/
https://hub.docker.com/u/nuagebec/
https://hub.docker.com/explore/
https://docs.docker.com/engine/userguide/containers/dockerimages/
Criando sua prpria imagem no Docker 41

Um repositrio pode conter mais de uma tag e cada


conjunto repositrio:tag representa uma imagem diferente.
Execute o comando abaixo para visualizar todas as imagens
que se encontram localmente na sua estao, nesse momento:

1 docker image list

Como criar imagens


H duas formas de criar imagens customizadas: com commit
e com Dockerfile.

Criando imagens com commit

possvel criar imagens executando o comando commit,


relacionado a um container. Esse comando usa o status atual
do 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:


https://docs.docker.com/engine/reference/commandline/images/
https://docs.docker.com/engine/reference/commandline/commit/
Criando sua prpria imagem no Docker 42

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 nome


do container criado e modificado nos passos anteriores; o
nome meuubuntu:nginx a imagem resultante do commit;
o estado do containercriado armazenado em uma imagem
chamada meuubuntu:nginx que, nesse caso, a nica modifi-
cao que temos da imagem oficial do ubuntu na verso 16.04
o pacote nginx instalado.
Para visualizar a lista de imagens e encontrar a que acabou de
criar, execute novamente o comando abaixo:

1 docker image list

Para testar sua nova imagem, vamos criar um container a


partir 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:
Criando sua prpria imagem no Docker 43

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


2 l nginx

Vale salientar que o mtodo commit no a


melhor opo para criar imagens, pois, como
verificamos, o processo de modificao da ima-
gem completamente manual e apresenta certa
dificuldade para rastrear as mudanas efetuadas,
uma vez que, o que foi modificado manualmente
no registrado, automaticamente, na estrutura
do docker.

Criando imagens com Dockerfile

Quando se utiliza Dockerfile para gerar uma imagem, ba-


sicamente, apresentada uma lista de instrues que sero
aplicadas em determinada imagem para que outra imagem
seja gerada com base nas modificaes.

Dockerfile

Podemos resumir que o arquivo Dockerfile, na verdade, re-


presenta a exata diferena 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.
Criando sua prpria imagem no Docker 44

Voltemos ao exemplo da instalao do nginx no ubuntu 16.04.


Primeiro crie um arquivo qualquer para um teste futuro:

1 touch arquivo_teste

Crie um arquivo chamado Dockerfile e dentro dele o seguinte


contedo:

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 instrues:


FROM para informar qual imagem usaremos como base,
nesse caso foi ubuntu:16.04.
RUN para informar quais comandos sero executados nesse
ambiente para efetuar as mudanas necessrias na infraestru-
tura do sistema. So como comandos executados no shell do
ambiente, igual ao modelo por commit, mas nesse caso foi
efetuado automaticamente e, completamente rastrevel, j
que esse Dockerfile ser armazenado no sistema de controle
de verso.
COPY usado para copiar arquivos da estao onde est
executando a construo para dentro da imagem. Usamos um
arquivo de teste apenas para exemplificar essa possibilidade,
mas essa instruo muito utilizada para enviar arquivos de
configurao de ambiente e cdigos para serem executados
em servios de aplicao.
https://docs.docker.com/engine/reference/builder/
Criando sua prpria imagem no Docker 45

CMD para informar qual comando ser executado por pa-


dro, caso nenhum seja informado na inicializao de um
container a partir dessa imagem. No exemplo, colocamos o
comando bash, se essa imagem for usada para iniciar um
container e no informamos o comando, ele executar o bash.
Aps construir seu Dockerfile basta executar o comando
abaixo:

1 docker image build -t meuubuntu:nginx_auto .

Tal comando tem a opo -t, serve para informar o nome da


imagem a ser criada. No caso, ser meuubuntu:nginx_auto
e o . ao final, informa qual contexto deve ser usado nessa
construo de imagem. Todos os arquivos da pasta atual sero
enviados para o servio do docker e apenas eles podem ser
usados para manipulaes do Dockerfile (exemplo do uso do
COPY).

A ordem importa

importante atentar que o arquivo Dockerfile uma sequn-


cia de instrues lidas do topo base e cada linha executada
por vez. Se alguma instruo depender de outra instruo,
essa dependncia deve ser descrita mais acima no documento.
O resultado de cada instruo do arquivo armazenado
em cache local. Caso o Dockerfile no seja modificado na
prxima criao da imagem (build), o processo no demorar,
pois tudo estar no cache. Se houver alteraes, apenas a
instruo modificada e as posteriores sero executadas nova-
mente.
https://docs.docker.com/engine/reference/commandline/build/
Criando sua prpria imagem no Docker 46

A sugesto para melhor aproveitar o cache do Dockerfile


sempre manter as instrues frequentemente ateradas mais
prximas da base do documento. Vale lembrar de atender
tambm as dependncias entre instrues.
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 invs


de instalar o nginx, mudarmos para apache2, a instruo que
faz o update no apt no ser executada novamente, e sim
a instalao do apache2, pois acabou de entrar no arquivo,
assim como o php5 e a cpia do arquivo, pois todos eles so
subsequentes a linha modificada.
Como podemos perceber, de posse do arquivo Dockerfile,
possvel ter a exata noo de quais mudanas foram efetuadas
na imagem e, assim, registrar as modificaes no sistema de
controle de verso.

Enviando sua imagem para nuvem


Entendendo
armazenamento no
Docker
Para entender como o docker gerencia seus volumes, primeiro
precisamos explicar como funciona ao menos um backend
de armazenamento do Docker. Faremos aqui com o AUFS, que
foi o primeiro e ainda padro em boa parte das instalaes
do Docker.

http://searchdatacenter.techtarget.com/definition/back-end
Entendendo armazenamento no Docker 48

Como funciona um backend do Docker


(Ex.: AUFS)
Backend de armazenamento a parte da soluo do Docker
que cuida do gerenciamento dos dados. No Docker temos
vrias possibilidades de backend de armazenamento, mas
nesse texto falaremos apenas do que implementa o AUFS.
AUFS um unification filesystem. responsvel por geren-
ciar mltiplos diretrios, empilh-los uns sobre os outros e
fornecer uma nica e unificada viso, como se todos juntos
fossem apenas um diretrio.
Esse nico diretrio utilizado para apresentar o container e
funciona como se fosse um nico sistema de arquivos comum.
Cada diretrio usado na pilha corresponde a uma camada.
E, dessa forma que o Docker as unifica e proporciona a
reutilizao entre containeres. Pois, o mesmo diretrio cor-
respondente imagem pode ser montado em vrias pilhas de
vrios containeres.
Com exceo da pasta (camada) correspondente ao container,
todas as outras so montadas com permisso de somente
leitura, caso contrrio as mudanas de um container poderiam
interferir em outro. O que, de fato, totalmente contra os
princpios do Linux Container.
Caso seja necessrio modificar um arquivo nas camadas (pas-
tas) referentes s imagens, se utiliza a tecnologia Copy-on-
write (CoW), responsvel por copiar o arquivo para a pasta
(camada) do container e fazer todas as modificaes nesse
nvel. Dessa forma, o arquivo original da camada inferior
https://en.wikipedia.org/wiki/Aufs
https://en.wikipedia.org/wiki/Copy-on-write
Entendendo armazenamento no Docker 49

sobreposto nessa pilha, ou seja, o container em questo


sempre ver apenas os arquivos das camadas mais altas.

Removendo um arquivo

No caso da remoo, o arquivo da camada superior marcado


como whiteout file, viabilizando a visualizao do arquivo de
camadas inferiores.

Problema com performance


O Docker tira proveito da tecnologia Copy-on-write (CoW)
do AUFS para permitir o compartilhamento de imagem e
minimizar o uso de espao em disco. AUFS funciona no
nvel de arquivo. Isto significa que todas as operaes AUFS
CoW copiaro arquivos inteiros, mesmo que, apenas pequena
parte do arquivo esteja sendo modificada. Esse comporta-
mento pode ter impacto notvel no desempenho do container,
especialmente se os arquivos copiados so grandes e esto
localizados abaixo de vrias camadas de imagens. Nesse caso
o procedimento copy-on-write dedicar muito tempo para
uma cpia interna.
Entendendo armazenamento no Docker 50

Volume como soluo para performance


Ao utilizar volumes, o Docker monta essa pasta (camada) no
nvel imediatamente inferior ao do container, o que permite o
acesso rpido de todo dado armazenado nessa camada (pasta),
resolvendo o problema de performance.
O volume tambm resolve questes de persistncia de da-
dos, pois as informaes armazenadas na camada (pasta) do
container so perdidas ao remover o container, ou seja, ao
utilizar volumes temos maior garantia no armazenamento
desses dados.

Usando volumes

Mapeamento de pasta especfica do host

Nesse modelo o usurio escolhe uma pasta especfica do host


(Ex.: /var/lib/container1) e a mapeia em uma pasta interna do
container (Ex.: /var). O que escrito na pasta /var do container
escrito tambm na pasta /var/lib/container1 do host.
Segue o exemplo de comando usado para esse modelo de
mapeamento:

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


2 ubuntu

Esse modelo no portvel. Necessita que o host tenha uma


pasta especfica para que o container funcione adequada-
mente.
Entendendo armazenamento no Docker 51

Mapeamento via container de dados

Nesse modelo criado um container e, dentro desse, nome-


ado um volume a ser consumido por outros containeres. Dessa
forma no preciso criar uma pasta especfica no host para
persistir dados. Essa pasta criada automaticamente dentro
da pasta raiz do Docker daemon. Porm, voc no precisa se
preocupar com essa pasta, pois toda a referncia ser feita para
o container detentor do volume e no 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 a


pasta /dbdata pode ser consumida por outros containeres, ou
seja, o contedo da pasta /dbtada poder ser visualizado e/ou
editado por outros containeres.
Para consumir esse volume do container basta utilizar o
comando:

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


2 ame db2 postgres

Agora o container db2 tem uma pasta /dbdata que a mesma


do container dbdata, tornando esse modelo completamente
portvel.
Uma desvantagem a necessidade de manter um container
apenas para isso, pois em alguns ambientes os containeres so
removidos com certa regularidade e, dessa forma, necessrio
ter cuidado com containeres especiais. O que, de certa forma,
um problema adicional de gerenciamento.
Entendendo armazenamento no Docker 52

Mapeamento de volumes

Na verso 1.9 do Docker foi acrescentada a possibilidade de


criar volumes isolados de containeres. Agora possvel criar
um volume portvel, sem a necessidade de associ-lo a um
container 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 ser


consumido por qualquer container.
A associao do volume ao container acontece de forma
parecida praticada no mapeamento de pasta do host, pois
nesse caso voc precisa associar o volume a uma pasta dentro
do 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 lanamento, pois pro-


porciona portabilidade. No removido facilmente quando o
container deletado e ainda bastante fcil de gerenciar.
Entendendo a rede no
Docker
O que o docker chama de rede, na verdade uma abstrao
criada para facilitar o gerenciamento da comunicao de
dados entre containers e os ns externos ao ambiente docker.
No confunda a rede do docker com a j conhecida rede
utilizada para agrupar os endereos IP (ex: 192.168.10.0/24).
Sendo assim, sempre que mencionarmos esse segundo tipo de
rede, usaremos rede IP.

Redes padres do Docker


O docker disponibilizado com trs redes por padro. Essas
redes oferecem configuraes especficas para gerenciamento
do trfego de dados. Para visualizar essas interfaces, basta
utilizar o comando abaixo:
docker network ls
O retorno ser:
Entendendo a rede no Docker 54

Bridge

Cada container iniciado no docker associado a uma rede


especfica. Essa a rede padro para qualquer container, a
menos que associemos, explicitamente, outra rede a ele. A
rede confere ao container uma interface que faz bridge com
a interface docker0 do docker host. Essa interface recebe,
automaticamente, o prximo endereo disponvel na rede IP
172.17.0.0/16.
Todos os containers que esto nessa rede podero se comuni-
car via protocolo TCP/IP. Se voc souber qual endereo IP do
container deseja conectar, possvel enviar trfego para ele.
Afinal, esto todos na mesma rede IP (172.17.0.0/16).
Um detalhe a se observar: como os IPs so cedidos automati-
camente, no tarefa trivial descobrir qual IP do container de
destino. Para ajudar nessa localizao, o docker disponibiliza,
na inicializao de um container, a opo link.

Vale ressaltar que link uma opo defasada e


seu uso desaconselhado. Explicaremos esta funci-
onalidade apenas para efeito de entendimento do
legado. Essa funo foi substituda por um DNS
embutido no docker e, no funciona para redes
padres do docker, apenas disponvel para redes
criadas pelo usurio.

A opo link responsvel por associar o IP do container


de destino ao seu nome. Caso voc inicie um container a partir
da imagem docker do mysql com nome bd, em seguida inicie
outro com nome app a partir da imagem tutum/apache-
php, voc deseja que esse ltimo container possa conectar
no mysql usando o nome do container bd, basta iniciar da
seguinte forma ambos os containers:
Entendendo a rede no Docker 55

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

Aps 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/16
que o container do mysql obteve na sua inicializao.
Pra testar, utilizaremos a funcionalidade exec para rodar
o comando dentro de um container j existente. Para tal,
usaremos o nome do container como parmetro do comando
abaixo:

1 docker container exec -it app ping db

A ao ser responsvel por executar o comando ping db


dentro do container app, ou seja, o container app enviar
pacotes icmp, normalmente usado para testar conectividade
entre dois hosts, para o endereo db. O nome db tradu-
zido para o IP que o container, iniciado a partir da imagem do
mysql, obteve ao iniciar.
Exemplo: O container db iniciou primeiro e obteve o IP
172.17.0.2. O container app iniciou em seguida e recebeu o
IP 172.17.0.3. Quando o container app executar o comando
ping db, na verdade, ele enviar pacotes icmp para o ende-
reo 172.17.0.2.

Ateno: O nome da opo link causa certa


confuso, pois no cria link de rede IP entre os
Entendendo a rede no Docker 56

containers, uma vez que a comunicao entre eles


j possvel, mesmo sem a opo link ser confi-
gurada. Como esclarecido no pargrafo anterior,
apenas facilita a traduo de nomes para o IP
dinmico obtido na inicializao.

Os containers configurados para essa rede tero a possibi-


lidade de trfego externo utilizando as rotas das redes IP
definidas no docker host. Caso o docker host tenha acesso a
internet, automaticamente, os containers em questo tambm
tero.
Nessa rede possvel expor portas dos containers para todos
os ativos com acesso ao docker host.

None

Essa rede tem como objetivo isolar o container para comuni-


caes externas. A rede no recebe qualquer interface para
comunicao externa. A nica interface de rede IP ser a
localhost.
Essa rede, normalmente, utilizada para containers que mani-
pulam apenas arquivos, sem necessidade de envi-los via rede
para outro local. (Ex.: container de backup utiliza os volumes
de container de banco de dados para realizar o dump e, ser
usado no processo de reteno dos dados).
Entendendo a rede no Docker 57

Exemplo de uso da rede none

Em caso de dvida sobre utilizao de volumes no docker


visite esse artigo e entenda mais sobre armazenamento do
docker.

Host

Essa rede tem como objetivo entregar para o container todas


as interfaces existentes no docker host. De certa forma, pode
agilizar a entrega dos pacotes, uma vez que no h bridge
no caminho das mensagens. Mas normalmente esse overhead
mnimo e o uso de uma brigde pode ser importante para
segurana e gerencia do seu trfego.

Redes definidas pelo usurio


O docker possibilita que o usurio crie redes. Essas redes so
associadas ao elemento que o docker chama de driver de rede.
Cada rede criada por usurio deve estar associada a um
determinado driver. E, caso voc no crie seu prprio driver,
deve escolher entre os drivers disponibilizados pelo docker:
http://techfree.com.br/2015/12/entendendo-armazenamentos-de-dados-no-docker/
Entendendo a rede no Docker 58

Bridge

Essa o driver de rede mais simples de utilizar, pois demanda


pouca configurao. A rede criada por usurio utilizando o
driver bridge assemelha-se bastante rede padro do docker
denominada bridge.

Mais um ponto que merece ateno: o docker tem


uma rede padro chamada bridge que utiliza
um driver tambm chamado de bridge. Talvez,
por conta disso, a confuso s aumente. Mas
importante deixar claro que so distintas.

As redes criadas pelo usurio com o driver bridge tem todas


as funcionalidades descritas na rede padro, chamada bridge.
Porm, com funcionalidades adicionais.
Dentre uma das funcionalidades: a rede criada pelo usurio
no precisa mais utilizar a opo antiga link. Pois, toda
rede criada pelo usurio com o driver bridge poder utilizar o
DNS interno do Docker que, associa, automaticamente, todos
os nomes de containers dessa rede para seus respectivos IPs
da rede IP correspondente.
Para deixar mais claro: todos os containers que estiverem
utilizando a rede padro bridge no podero usufruir da fun-
cionalidade de DNS interno do Docker. Caso utilize essa rede,
preciso especificar a opo legada link para traduo dos
nomes em endereos IPs dinamicamente alocados no docker.
Para exemplificar a utilizao de rede criada por usurio
vamos criar a rede chamada isolated_nw com o driver bridge:
Entendendo a rede no Docker 59

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
Entendendo a rede no Docker 60

Vale salientar: um container que est em determinada rede


no acessa outro container que est em outra rede. Mesmo que
voc conhea o IP de destino. Para que um container acesse
outro container de outra rede, necessrio que a origem esteja
presente nas duas redes que deseja alcanar.
Os containers que esto na rede isolated_nw podem expor
suas portas no docker host e essas portas podem ser acessadas
tanto por containers externos a rede, chamada isolated_nw,
como mquinas externas com acesso ao docker host.

Rede isolada publicando portas

Para descobrir quais containers esto associados a uma deter-


minada rede, execute o comando abaixo:
Entendendo a rede no Docker 61

1 docker network inspect isolated_nw

O resultado deve ser:

Dentro da sesso Containers possvel verificar quais con-


tainers fazem parte dessa rede. Todos os containers que esti-
verem na mesma rede podero se comunicar utilizando ape-
nas seus respectivos nomes. Como podemos ver no exemplo
acima, caso um container novo acesse a rede isolated_nw, ele
poder acessar o container amazing_noyce utilizando apenas
seu nome.

Overlay

O driver overlay permite comunicao entre hosts docker,


utilizando-o os containers de um determinado host docker po-
dero acessar, nativamente, containers de um outro ambiente
docker.
Esse driver demanda configurao mais complexa, sendo
assim, trataremos do detalhamento em outra oportunidade.
Entendendo a rede no Docker 62

Utilizando redes no docker compose


O assunto merece um artigo exclusivo. Ento, apenas in-
formaremos um link interessante para referncia sobre o
assunto.

Concluso
Percebemos que a utilizao de redes definidas por usurio
torna obsoleta a utilizao da opo link, bem como viabi-
liza novo servio de DNS interno do docker, o que facilita para
quem se prope a manter uma infraestrutura docker grande
e complexa, assim como viabilizar o isolamento de rede dos
seus servios.
Conhecer e utilizar bem as tecnologias novas uma boa
prtica que evita problemas futuros e facilita a construo e
manuteno de projetos grandes e complexos.
https://docs.docker.com/compose/networking/
Utilizando Docker em
mltiplos ambientes
Docker host o nome do ativo responsvel por gerenciar am-
bientes Docker, nesse captulo mostraremos como possvel
cri-los e gerenci-los em infraestruturas distintas, tais como
mquina virtual, nuvem e mquina fsica.

Docker machine a ferramenta usada para essa gerncia


distribuda, permite a instalao e gerncia de docker hosts
de forma fcil e direta.
Essa ferramenta muito usada por usurios de sistema ope-
racional no linux, como demonstraremos ainda, mas sua
funo no limita-se a esse fim, pois tambm bastante usada
para provisionar e gerenciar infraestrutura Docker na nuvem,
tal como AWS, Digital Ocean e Openstack.
https://docs.docker.com/machine/
Utilizando Docker em mltiplos ambientes 64

Como funciona
Antes de explicar como utilizar o docker machine, precisamos
reforar o conhecimento sobre a arquitetura do Docker.

Como demonstra a imagem acima, a utilizao do Docker


divide-se em dois servios: o que roda em modo daemon,
Utilizando Docker em mltiplos ambientes 65

em background, chamado de Docker Host, responsvel pela


viabilizao dos containers no kernel Linux; e, o cliente,
que chamaremos de Docker client, responsvel por receber
comandos do usurio e traduzir em gerncia do Docker Host.
Cada Docker client configurado para se conectar a deter-
minado Docker host e nesse momento o Docker machine
entra em ao, pois viabiliza a automatizao da escolha de
configurao de acesso do Docker client a distintos Docker
host.
O Docker machine possibilita utilizar diversos ambientes
distintos apenas modificando a configurao do cliente para
o Docker host desejado: basicamente modificar algumas
variveis 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 variveis, o Docker client poder


utilizar um ambiente diferente rapidamente e sem precisar
reiniciar qualquer servio.

Criando ambiente
O Docker machine serve principalmente para criar ambientes,
futuramente geridos por ele na troca automatizada de con-
texto de configurao, atravs da mudana de variveis de
ambiente, como explicado anteriormente.
Utilizando Docker em mltiplos ambientes 66

Para criar o ambiente necessrio verificar se a infraestrutura


que deseja criar tem algum driver com suporte a esse processo.
Segue a lista de drivers disponveis.

Mquina virtual

Para esse exemplo, usaremos o driver mais utilizado, o virtu-


albox, ou seja, precisamos de um virtualbox instalado na
nossa estao para que esse driver funcione adequadamente.
Antes de criar o ambiente vamos entender como funciona o
comando de criao do docker machine:
docker-machine create driver=<nome do driver> <nome do
ambiente>
Para o driver virtualbox temos alguns parmetros que podem
ser utilizados:
Parmetro Explicao
virtualbox-memory Especifica a quantidade
de memria RAM que o
ambiente pode utilizar. O
valor padro 1024MB.
(Sempre em MB)
virtualbox-cpu-count Especifica a quantidade
de ncleos de CPU que
esse ambiente pode
utilizar. O valor padro
1

https://docs.docker.com/machine/drivers/
https://docs.docker.com/machine/drivers/virtualbox/
https://www.virtualbox.org/
Utilizando Docker em mltiplos ambientes 67

Parmetro Explicao
virtualbox-disk-size Especifica o tamanho do
disco que esse ambiente
pode utilizar. O valor
padro 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 criao de uma mquina


virtual no virtualbox. A mquina ter 30GB de espao em
disco, 1 ncleo e 1GB de memria RAM.
Para validar se o processo aconteceu como esperado, basta
utilizar o seguinte comando:

1 docker-machine ls

O comando acima responsvel por listar todos os ambientes


que podem ser usados a partir da estao cliente.
Pra mudar de cliente basta utilizar o comando:

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

Executando o comando ls ser possvel verificar qual ambi-


ente est ativo:
Utilizando Docker em mltiplos ambientes 68

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 utilizando


Docker-machine no MacOS e por algum motivo a estao
hiberne quando o ambiente virtualbox tenha iniciado, pos-
svel que, no retorno da hibernao, o Docker host apresente
problemas na comunicao com a internet. Orientamos a,
sempre que passar por problemas de conectividade no Docker
host com driver virtualbox, desligue o ambiente e reinicie
como medida de contorno.
Utilizando Docker em mltiplos ambientes 69

Nuvem

Para esse exemplo usamos o driver da nuvem mais utilizada,


AWS. Para tanto, precisamos de uma conta na AWS para que
esse driver funcione adequadamente.
necessrio que suas credenciais estejam no arquivo /.aws/credentials
da seguinte forma:

1 [default]
2 aws_access_key_id = AKID1234567890
3 aws_secret_access_key = MY-SECRET-KEY

Caso no deseje colocar essas informaes em arquivo, voc


pode especificar via variveis de ambiente:

1 export AWS_ACCESS_KEY_ID=AKID1234567890
2 export AWS_SECRET_ACCESS_KEY=MY-SECRET-KEY

Voc pode encontrar mais informaes sobre credencial AWS


nesse artigo.
Quando criamos um ambiente utilizando o comando docker-
machine create, o mesmo traduzido para AWS na criao
uma instncia EC2 e, em seguida instalado todos os
softwares necessrios, automaticamente, no novo ambiente.
Os parmetros mais utilizados na criao desse ambiente so:

http://aws.amazon.com/
https://docs.docker.com/machine/drivers/aws/
http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-
Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs
https://aws.amazon.com/ec2/
Utilizando Docker em mltiplos ambientes 70

Parmetro Explicao
amazonec2-region Informa qual regio da
AWS utilizada para
hospedar seu ambiente.
O valor padro
us-east-1.
amazonec2-zone a letra que representa
a zona utilizada. O
valor padro a
amazonec2-subnet-id Informa qual a
sub-rede utilizada nessa
instncia EC2. Precisa
ter sido criada
previamente.
amazonec2-security- Informa qual security
group group utilizado nessa
instncia EC2. Precisa
ter sido criado
previamente
amazonec2-use- Ser criada uma
private-address interface com IP
privado, pois por
default, s especifica
uma interface com IP
pblico
amazonec2-vpc-id Informa qual o ID do
VPC desejado para essa
instncia EC2. Precisa
ter sido criado
previamente.

Como exemplo, usamos o seguinte comando de criao do


ambiente:
Utilizando Docker em mltiplos ambientes 71

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

Aps executar o comando, basta esperar finalizar, normal


demorar um pouco.
Para testar o sucesso da ao, 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:


Utilizando Docker em mltiplos ambientes 72

1 docker-machine start teste-aws

Caso deseje remover o ambiente, utilize o comando:

1 docker-machine rm teste-aws

Aps removido do local, automaticamente remover a instn-


cia EC2, provisionada na AWS.
Gerenciando mltiplos
containers docker com
Docker Compose
Esse artigo tem como objetivo explicar de forma detalhada, e
com exemplos, como funciona o processo de gerenciamento
de mltiplos containers Docker, pois a medida que sua confi-
ana em utilizar Docker aumenta, sua necessidade de utilizar
um maior nmero de containers ao mesmo tempo cresce na
mesma proporo, e seguir a boa prtica de manter apenas
um servio por container comumente resulta em alguma
demanda extra.
Gerenciando mltiplos containers docker com Docker Compose 74

Geralmente com o aumento do nmero de containers em


execuo, fica evidente a necessidade de um melhor geren-
ciamento da sua comunicao, pois ideal que os servios
consigam trocar dados entre os containers quando necessrio,
ou seja, voc precisa lidar com a rede desse novo ambiente.
Imagine o trabalho que seria executar algumas dezenas de
containers manualmente na linha de comando, um por um
e todos seus parmetros necessrios, suas configuraes de
rede entre containers, volumes e afins. Pode parar de ima-
ginar, pois isso no ser mais necessrio. Para atender essa
demanda de gerenciamento de mltiplos containers a soluo
Gerenciando mltiplos containers docker com Docker Compose 75

o Docker Compose.
Docker compose uma ferramenta para definio e execuo
de mltiplos containers Docker. Com ela possvel configurar
todos os parmetros necessrios para executar cada container
a partir de um arquivo de definio. Dentro desse arquivo,
definimos cada container como servio, ou seja, sempre que
esse texto citar servio de agora em diante, imagine que a
definio que ser usada para iniciar um container, tal como
portas expostas, variveis de ambiente e afins.
Com o Docker Compose podemos tambm especificar quais
volumes e rede sero criados para serem utilizados nos
parmetros dos servios, ou seja, isso quer dizer que no
preciso cri-los manualmente para que os servios utilizem
recursos adicionais de rede e volume.
O arquivo de definio do Docker Compose o local onde
especificado todo o ambiente (rede, volume e servios), ele
escrito seguindo o formato YAML. Esse arquivo por padro
tem como nome docker-compose.yml.

Anatomia do docker-compose.yml
O padro YAML utiliza a indentao como separador dos
blocos de cdigos das definies, por conta disso o uso da
indentao um fator muito importante, ou seja, caso no
a utilize corretamente, o docker-compose falhar em sua
execuo.
Cada linha desse arquivo pode ser definida com uma chave
valor ou uma lista. Vamos aos exemplos pra ficar mais claro
https://docs.docker.com/compose/overview/
https://en.wikipedia.org/wiki/YAML
https://docs.docker.com/compose/compose-file/
Gerenciando mltiplos containers docker com Docker Compose 76

a explicao:

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 verso


do docker-compose.yml, que no nosso caso usaremos a
verso mais atual do momento, caso tenha interesse em saber
a diferena entre as verses possveis, veja esse link.

1 version: '2'

No mesmo nvel de indentao temos services, que define o


incio do bloco de servios que sero definidos logo abaixo.

1 version: '2'
2 services:

No segundo nvel de indentao (aqui feito com dois espaos)


temos o nome do primeiro servio desse arquivo, que recebe
o nome de web. Ele abre o bloco de definies do servio,
ou seja, a partir do prximo nvel de indentao, tudo que for
definido faz parte desse servio.
https://docs.docker.com/compose/compose-file/#versioning
Gerenciando mltiplos containers docker com Docker Compose 77

1 version: '2'
2 services:
3 web:

No prximo nvel de indentao (feito novamente com mais


dois espaos) temos a primeira definio do servio web,
que nesse caso o build que informa que esse servio ser
criado no a partir de uma imagem pronta, mas que ser
necessrio construir sua imagem antes de sua execuo. Seria
o equivalente ao comando docker build. Ele tambm abre
um novo bloco de cdigo para parametrizar o funcionamento
dessa construo da imagem.

1 version: '2'
2 services:
3 web:
4 build: .

No prximo nvel de indentao (feito novamente com mais


dois espaos) temos um parmetro do build, que nesse caso
o context. Ele responsvel por informar qual contexto de
arquivos ser usado para construir a imagem em questo, ou
seja, apenas arquivos existentes dentro dessa pasta podero
ser usados na construo da imagem. O contexto escolhido foi
o ./dir, ou seja, isso indica que uma pasta chamada dir, que
se encontra no mesmo nvel de sistema de arquivo do docker-
compose.yml ou do lugar onde esse comando ser executado,
ser usada como contexto da criao dessa imagem. Quando
logo aps da chave um valor fornecido, isso indica que
nenhum bloco de cdigo ser aberto.
https://docs.docker.com/compose/reference/build/
https://docs.docker.com/engine/reference/commandline/build/
Gerenciando mltiplos containers docker com Docker Compose 78

1 build: .
2 context: ./dir

No mesmo nvel de indentao da definio context, ou


seja, ainda dentro do bloco de definio do build, temos o
dockerfile, ele indica o nome do arquivo que ser usado
para construo da imagem em questo. Seria o equivalente
ao parmetro -f do comando docker build. Caso essa
definio no existisse, o docker-compose procuraria por
padro por um arquivo chamado Dockerfile dentro da pasta
informada no context.

1 build: .
2 context: ./dir
3 dockerfile: Dockerfile-alternate

No mesmo nvel de indentao da definio dockerfile, ou


seja, ainda dentro do bloco de definio do build, temos o
args, ele define os argumentos que sero usados pelo Doc-
kerfile, seria o equivalente ao parmetro build-args do
comando docker build. Como no foi informado o seu valor
na mesma linha, fica evidente que ela abre um novo bloco de
cdigo.
No prximo nvel de indentao (feito novamente com mais
dois espaos) temos a chave versao e o valor 1, ou seja,
como essa definio faz parte do bloco de cdigo args, essa
chave valor o nico argumento que ser passado para o
Dockerfile, ou seja, o arquivo Dockerfile em questo dever
estar preparado para receber esse argumento ou ele se perder
na construo da imagem.
https://docs.docker.com/engine/reference/commandline/build/#specify-dockerfile-f
https://docs.docker.com/engine/reference/commandline/build/#set-build-time-
variables-build-arg
Gerenciando mltiplos containers docker com Docker Compose 79

1 build: .
2 context: ./dir
3 dockerfile: Dockerfile-alternate
4 args:
5 versao: 1

Voltando dois nveis de indentao (quatro espaos a menos


em relao a linha anterior) temos a definio ports, que
seria o equivalente ao parmetro -p do comando docker
container run. Ele define qual porta do container ser exposta
no Docker host. Que no nosso caso ser a porta *5000 do
container, com a 5000 do Docker host.

1 web:
2 build: .
3 ...
4 ports:
5 - "5000:5000"

Voltando um nvel de indentao (dois espaos a menos em


relao a linha anterior) samos do bloco de cdigo do servio
web, isso indica que nenhuma definio informada nessa
linha ser aplicada a esse servio, ou seja, precisamos iniciar
um bloco de cdigo de um servio novo, que no nosso caso
ser com nome de redis.

1 redis:
2 image: redis

https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-
port-p-expose
Gerenciando mltiplos containers docker com Docker Compose 80

No prximo nvel de indentao (feito novamente com mais


dois espaos) temos a primeira definio do servio redis, que
nesse caso o image que responsvel por informar qual
imagem ser usada para iniciar esse container. Essa imagem
ser obtida do repositrio configurado no Docker host, que
por padro o hub.docker.com.

Executando o docker compose


Aps entender e criar seu prprio arquivo de definio
precisamos saber como gerenci-lo e para isso utilizaremos o
binrio docker-compose, que entre vrias opes de uso temos
as seguintes mais comuns:

build : Usada para construir todas as imagens dos


servios que esto descritos com a definio build em
seu bloco de cdigo.
up : Iniciar todos os servios que esto no arquivo
docker-compose.yml
stop : Parar todos os servios que esto no arquivo
docker-compose.yml
ps : Listar todos os servios que foram iniciados a partir
do arquivo docker-compose.yml

Para outras opes visite sua documentao.


https://hub.docker.com/
https://docs.docker.com/compose/reference/
Como usar Docker sem
GNU/Linux
Esse artigo tem como objetivo explicar de forma detalhada,
e com exemplos, o uso de Docker em estaes MacOS e
Windows.

Docker Toolbox

Esse texto para pessoas que j sabem sobre Docker, mas


ainda no sabem como o Docker pode ser utilizado a partir
de uma estao no linux.
Como usar Docker sem GNU/Linux 82

Como j dissemos, o Docker utiliza recursos especficos do


kernel hospedeiro e o GNU/Linux o nico sistema ope-
racional que o suporta de forma estvel. Significa que no
possvel iniciar containers Docker em estao MacOS e
Windows, por exemplo.
Mas no se preocupe, caso voc no utilize GNU/Linux como
sistema operacional, ainda possvel fazer uso dessa tecnolo-
gia, sem, necessariamente, execut-la em seu computador.
Um dos produtos da sute Docker o Docker Toolbox. Essa
soluo, na verdade, uma abstrao para instalao de todo
ambiente necessrio para uso do Docker a partir de uma
estao MacOS ou Windows.
A instalao simples: tanto no Windows, como no Ma-
cOS, basta baixar o instalador correspondente nesse site e
execut-lo seguindo os passos descritos nas telas.
Os softwares instalados na estao - MacOS ou Windows - a
partir do pacote Docker Toolbox so:

Virtualbox
Docker machine
Docker client
Docker compose
Kitematic
https://www.docker.com/products/docker-toolbox
https://www.docker.com/products/docker-toolbox
https://www.virtualbox.org/
https://docs.docker.com/machine/overview/
https://docs.docker.com/
https://docs.docker.com/compose/overview/
https://docs.docker.com/kitematic/userguide/
Como usar Docker sem GNU/Linux 83

Docker Machine a ferramenta que possibilita criar e manter


ambientes Docker em mquinas virtuais, ambientes de nuvem
e, at mesmo, em mquina fsica. Mas nesse tpico, abordare-
mos apenas mquina virtual com virtualbox.
Aps instalar o Docker Toolbox muito simples criar um
ambiente Docker com mquina virtual usando o Docker
Machine.
Primeiro verificamos se no existem mquinas virtuais com
Docker instaladas em seu ambiente:

1 docker-machine ls

O comando acima mostra apenas ambientes criados e manti-


dos por seu Docker Machine. possvel que, aps instalar o
Docker Toolbox, voc no encontre mquina alguma criada.
Nesses casos, utilizamos o comando abaixo para criar a m-
quina:

1 docker-machine create --driver virtualbox default

Arquitetura do Docker Toolbox


Como usar Docker sem GNU/Linux 84

O comando cria um ambiente denominado default. Na


verdade uma mquina virtual (Linux VM que aparece
na imagem) criada no virtualbox. Com o comando abaixo
possvel visualizar a mquina criada:

1 docker-machine ls

O retorno deve ser algo parecido com isto:

Uma mquina virtual foi criada, dentro dela temos um sistema


operacional GNU/Linux com Docker Host instalado. Esse
servio Docker est escutando na porta TCP 2376 do endereo
192.168.99.100. Essa interface utiliza uma rede especfica entre
seu computador e as mquinas do virtualbox.
Para desligar a mquina virtual, basta executar o comando
abaixo:

1 docker-machine stop default

Para iniciar, novamente, a mquina, basta executar o co-


mando:

1 docker-machine start default

O comando start responsvel apenas por iniciar a m-


quina. necessrio fazer com que os aplicativos de controle do
Docker, instalados na estao, possam se conectar mquina
virtual criada no virtualbox com o comando docker-machine
create.
Como usar Docker sem GNU/Linux 85

Os aplicativos de controle (Docker e Docker-compose) fazem


uso de variveis de ambiente para configurar qual Docker
Host ser utilizado. O comando abaixo facilita o trabalho de
aplicar todas as variveis corretamente:

1 docker-machine env default

O resultado desse comando no MacOS :

Como vemos, informa o que pode ser feito para configurar


todas as variveis. Voc pode copiar as quatros primeiras
linhas, que comeam com export, e colar no terminal ou,
pegar apenas a ltima linha sem o # do incio e executar na
linha de comando:

1 eval $(docker-machine env default)

Agora os aplicativos de controle (Docker e Docker-Compose)


esto aptos a utilizar o Docker Host a partir da conexo feita
no servio do IP 192.168.99.100 - mquina criada com o co-
mando docker-machine create mencionados anteriormente.
Para testar, listamos os containers em execuo nesse Docker
Host com o comando:

1 docker ps
Como usar Docker sem GNU/Linux 86

Executado na linha de comando do MacOS ou Windows, esse


cliente do Docker se conecta mquina virtual que, aqui
chamamos de Linux VM, e solicita a lista de containers em
execuo 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-


cuo:

1 docker ps

Podemos ver que o container criado a partir da imagem


alpine est em execuo. Vale salientar que esse processo
executado no Docker Host, na mquina criada dentro do
virtualbox que, nesse exemplo, tem o ip 192.168.99.100.
Para verificar o endereo IP da mquina, basta executar o
comando abaixo:

1 docker-machine ip

Caso o container exponha alguma porta para o Docker Host,


seja via parmetro -p do comando docker container run
-p porta_host:porta_container ou via parmetro ports do
docker-compose.yml, vale lembrar que o IP para acessar o
servio exposto o endereo IP do Docker Host que, no
exemplo, 192.168.99.100.
Nesse momento, voc deve estar se perguntando: como
possvel mapear uma pasta da estao no-linux para dentro
Como usar Docker sem GNU/Linux 87

de um container? Aqui entra um novo artficio do Docker para


contornar esse problema.
Toda mquina criada com o driver virtualbox, automatica-
mente, cria um mapeamento do tipo pastas compartilhadas
do virtualbox da pasta de usurios para a raiz do Docker
Host.
Para visualizar esse mapeamento, acessamos a mquina vir-
tual que acabamos de criar nos passos anteriores:

1 docker-machine ssh default

No console da mquina GNU/Linux digite os seguintes co-


mandos:

1 sudo su
2 mount | grep vboxsf

O vboxsf um sistema de arquivo usado pelo virtualbox


para montar volumes compartilhados da estao usada para
instalar o virtualbox. Ou seja, utilizando o recurso de pasta
compartilhada, possvel montar a pasta /Users do MacOS
na pasta /Users da mquina virtual do Docker Host.
Todo contedo existente na pasta /Users/SeuUsuario do Ma-
cOS, ser acessvel na pasta /Users/SeuUsuario da mquina
GNU/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 estao e nada precisa ser feito para replicar esse
cdigo para dentro do Docker Host.
Vamos testar. Crie um arquivo dentro da pasta de usurio:
https://help.ubuntu.com/community/VirtualBox/SharedFolders
Como usar Docker sem GNU/Linux 88

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 varivel
PWD indica o endereo atual no MacOS) na pasta /tmp,
dentro do container.
Verificamos se o arquivo que acabamos de criar est dentro
do container:

1 docker container exec teste ls /tmp/teste

A linha acima executou o comando ls /tmp/teste dentro do


container 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 usurio:

1 docker-machine ssh default

Tudo pode ser feito automaticamente? Claro que sim!


Agora que j sabe como fazer manualmente, se precisar
instalar o Docker Toolbox em uma mquina nova e no
lembrar os comandos para criar a nova mquina ou, simples-
mente como aprontar o ambiente para uso, basta executar o
programa Docker Quickstart Terminal. Ele far o trabalho
automaticamente. Caso no exista mquina criada, ele cria
uma chamada default. Caso a mquina j tenha sido cri-
ada, automaticamente configura suas variveis de ambiente
e deixa apto para utilizar o Docker Host remoto a partir dos
aplicativos de controle (Docker e Docker-Compose).
Transformando sua
aplicao em container
Evolumos continuamente para entregar aplicaes cada vez
melhores, em menor tempo, replicveis e escalveis. Entre-
tanto, os esforos e aprendizados para atingir esse nvel de
maturidade muitas vezes no so simples de serem alcana-
dos.
Atualmente, notamos o surgimento de vrias opes de pla-
taformas para facilitar a implantao, configurao e esca-
labilidade das aplicaes que desenvolvemos. Porm, para
melhorar nossa maturidade, no podemos depender apenas
da plataforma, precisamos construir nossa aplicao seguindo
boas prticas.
Visando sugerir uma srie de boas prticas comuns a apli-
caes web modernas, alguns desenvolvedores do Heroku
escreveram o 12Factor app, baseado na larga experincia em
desenvolvimento desse tipo de aplicao.

https://www.heroku.com/
http://12factor.net/pt_br/
Transformando sua aplicao em container 90

The Twelve-Factor app (12factor) um manifesto com uma


srie de boas prticas para construo de software utilizando
formatos declarativos de automao, maximizando portabi-
lidade e minimizando divergncias entre ambientes de exe-
cuo, permitindo a implantao em plataformas de nuvem
modernas e facilitando a escalabilidade. Assim, aplicaes
so construdas sem manter estado (stateless) e conectadas
a qualquer combinao de servios de infraestrutura para
reteno de dados (banco de dados, fila, memria cache e
afins).
Nesse captulo, falaremos sobre criao de aplicaes com
imagens Docker baseados no 12factor app. A ideia demons-
trar as melhores prticas para realizar a criao de infraes-
trutura para suportar, empacotar e disponibilizar a aplicao
com alto nvel de maturidade e agilidade.
O uso do 12factor com Docker uma combinao perfeita,
pois muitos dos recursos do Docker so melhores aproveita-
dos caso a aplicao tenha sido pensada para tal. Dessa forma,
daremos uma ideia de como aproveitar todo potencial da sua
soluo.
Como aplicao exemplo, teremos um servio HTTP, escrito
em python, que exibe quantas vezes foi acessada. Essa in-
formao armazenada atravs de contador numa instncia
Redis.
Agora vamos s boas prticas!
Base de cdigo
Com o objetivo de facilitar o controle das mudanas de cdigo,
viabilizando a rastreabilidade das alteraes, essa boa prtica
indica que cada aplicao deve ter apenas uma base de cdigo
e, partindo dessa, ser implantada em distintos ambientes. Vale
salientar que essa prtica tambm parte das prticas de
Continuous Integration (CI). Tradicionalmente, a maioria
dos sistemas de integrao contnua tem, como ponto de par-
tida, uma base de cdigo que construda e, posteriormente,
implantada em desenvolvimento, teste e produo.
Para essa explicao, usamos o sistema de controle de verso
Git e o servio de hospedagem Github. Criamos e disponibi-
lizamos um repositrio de exemplo.
Perceba que todo cdigo est dentro do repositrio, organi-
zado por prtica em cada pasta, para facilitar a reproduo.
Lembre-se de entrar na pasta correspondente a cada boa
prtica apresentada.
O Docker tem possibilidade de utilizar varivel de ambiente
para parametrizao da infraestrutura. Sendo assim, a mesma
aplicao ter comportamento distinto com base no valor das
variveis de ambiente.
Aqui usamos o Docker Compose para realizar a composio
de diferentes servios pertinentes para a aplicao em tempo
de execuo. Desse modo, devemos definir a configurao
desses distintos servios e a forma como se comunicam.
https://www.thoughtworks.com/continuous-integration
https://github.com/gomex/exemplo-12factor-docker.git
Base de cdigo 92

Posteriormente, mais precisamente na terceira boa prtica,


chamada Configurao, desse compndio de sugestes, trata-
remos com mais detalhes sobre parametrizao da aplicao.
Por ora, apenas aplicamos opes via varivel de ambiente
para a arquitetura, ao invs de, utilizar internamente no
cdigo da aplicao.
Para configurar o ambiente de desenvolvimento para o exem-
plo apresentado, criamos o arquivo docker-compose.yml:
Base de cdigo 93

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 servio redis utilizado a partir da


imagem oficial redis, sem modificao. E o servio web
gerado a partir da construo de uma imagem Docker.
Para a contruo da imagem Docker do servio web, criamos
o seguinte Dockerfile, usando como base a imagem oficial do
python 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 o


ambiente com o seguinte comando:
Base de cdigo 94

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


2 up -d

Como podemos perceber no exemplo desse captulo, a vari-


vel de ambiente ENV_APP define qual volume usado para
persistir os dados que so enviados pela aplicao web. Ou
seja, com base na mudana dessa opo, teremos o servio
rodando com comportamento diferente, mas sempre a partir
do mesmo cdigo. Dessa forma, segue o conceito da primeira
boa prtica.
Dependncia
Seguindo a lista do modelo 12factor, logo aps a base de
cdigo que tratamos nesse artigo, temos a Dependncia
como segunda boa prtica.

Essa boa prtica sugere a declarao de todas as dependncias


necessrias para executar o cdigo. Voc no deve assumir
que algum componente j est previamente instalado no ativo
responsvel por hospedar a aplicao.
http://12factor.net/
http://techfree.com.br/2016/06/dockerizando-aplicacoes-base-de-codigo/
Dependncia 96

Para viabilizar o sonho da portabilidade, precisamos geren-


ciar corretamente as dependncias da aplicao em questo,
isso indica que devemos, tambm, evitar a necessidade de tra-
balho manual na preparao da infraestrutura que d suporte
aplicao.
Automatizar o processo de instalao de dependncia o
grande segredo do sucesso para atender essa boa prtica. Caso
a instalao da infraestrutura no seja, suficientemente, auto-
mtica para viabilizar a inicializao sem erros, o atendimento
da boa prtica fica prejudicado.
Esses procedimentos, automatizados, colaboram com a manu-
teno da integridade do processo, pois, o nome dos pacotes
de dependncias e respectivas verses, esto especificados no
arquivo localizado no mesmo repositrio do cdigo que, por
sua vez, rastreado em um sistema de controle de verso. Com
isso, podemos concluir que nada modificado sem o devido
registro.
O Docker se encaixa perfeitamente na boa prtica. possvel
entregar um perfil mnimo de infraestrutura para a aplicao.
Por sua vez, a declarao explcita das dependncias, para que
a aplicao funcione no ambiente, faz-se necessria.
A aplicao do exemplo, escrita em Python, como verificamos
em parte do cdigo abaixo, necessita de duas bibliotecas para
funcionar corretamente:

1 from flask import Flask


2 from redis import Redis

Essas duas dependncias esto especificadas no arquivo requi-


rements.txt e, esse arquivo usado como parmetro do PIP.
Dependncia 97

O PIP um sistema de gerenciamento de pacotes usado para


instalar e gerenciar pacotes de software escritos na linguagem
de programao Python. (Wikipedia)
O comando PIP usado, junto ao arquivo requirements.txt,
na criao da imagem, como demonstrado no Dockerfile da
boa prtica 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-


dncias descritas no arquivo requirements.txt com o gerenci-
ador de pacotes PIP do Python. Veja o contedo do arquivo
requirements.txt:

1 flask==0.11.1
2 redis==2.10.5

importante salientar a necessidade de especificar as verses


de cada dependncia, pois, como no modelo de continer,
as imagens podem ser construdas a qualquer momento.
importante saber qual verso especfica a aplicao precisa.
Caso contrrio, podemos encontrar problemas com compati-
bilidade se uma das dependncias atualizar e no permaneer
compatvel com a composio completa das outras dependn-
cias e a aplicao que a utiliza.
Dependncia 98

Para acessar o cdigo descrito aqui, baixe o repositrio e


acesse a pasta factor2.
Outro resultado positivo do uso da boa prtica a simplifica-
o da utilizao do cdigo por outro desenvolvedor. Um novo
programador pode verificar, nos arquivos de dependncias,
quais os pr-requisitos para a aplicao executar, assim como
executar o ambiente sem necessidade de seguir a extensa
documentao que, raramente, atualizada.
Usando o Docker possvel configurar, automaticamente, o
necessrio para rodar o cdigo da aplicao, seguindo a boa
prtica perfeitamente.
https://github.com/gomex/exemplo-12factor-docker
Configuraes
Seguindo a lista do modelo 12factor, Configuraes
terceira boa prtica.
Quando estamos criando um software, aplicamos determi-
nado comportamento dentro do cdigo e normalmente ele no
parametrizvel. Para que a aplicao se comporte de forma
diferente, ser necessrio mudar parte do cdigo.
A necessidade de modificar o cdigo para trocar o compor-
tamento da aplicao, inviabiliza que, a mesma seja executa
na mquina (desenvolvimento) da mesma forma que usada
para atender os usurios (produo). E, com isso, acabamos
com a possibilidade de portabilidade. E, sem portabilidade,
qual a vantagem de se usar contineres, certo?
O objetivo da boa prtica viabilizar a configurao da
aplicao sem a necessidade de modificar o cdigo. J que,
o comportamento da aplicao varia de acordo com o ambi-
ente onde executada, as configuraes devem considerar o
ambiente.
Seguem alguns exemplo:

Configurao de banco de dados que, normalmente, so


diferentes entre ambientes
Credenciais para acesso a servios remotos (Ex.: Digital
Ocean ou Twitter)
http://12factor.net/
Configuraes 100

Qual nome de DNS ser usado pela aplicao

Como j mencionamos, quando a configurao est estati-


camente explcita no cdigo, necessrio modificar manual-
mente e efetuar novo build dos binrios a cada reconfigurao
do sistema.
Como demonstramos na boa prtica codebase, usamos uma
varivel de ambiente para modificar o volume que usaremos
no redis. De certa forma, j estamos seguindo a boa prtica,
mas podemos ir alm e mudarmos no somente o comporta-
mento da infraestrutura, mas sim algo inerente ao cdigo em
si.
Segue a aplicao 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 cdigo da prtica, basta clonar esse


repositrio e acessar a pasta factor3.
https://github.com/gomex/exemplo-12factor-docker
Configuraes 101

Como podemos notar, adicionamos alguns parmetros na


configurao do endereo usado para iniciar a aplicao web
que ser parametrizada com base no valor da varivel de
ambiente HOST_RUN. E, a possibilidade de efetuar, ou no,
o debug da aplicao com a varivel de ambiente DEBUG.
Vale salientar: nesse caso a varivel de ambiente precisa ser
passada para o continer, no basta ter a varivel no Docker
Host. preciso envi-la para o continer usando o parmetro
-e, caso utilize o comando docker container run ou, a
instruo 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:
Configuraes 102

22 external: false

Para executar o Docker-Compose, deveramos 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 variveis de ambiente HOST_-


RUN e DEBUG do Docker Host para enviar s variveis
de ambiente com os mesmos nomes dentro do continer
que, por sua vez, consumido pelo cdigo Python. Caso
no haja parmetros, o continer assume os valores padres
estipulados no cdigo.
Essa boa prtica seguida com ajuda do Docker, pois o cdigo
o mesmo e, a configurao, um anexo da soluo que pode
ser parametrizada de maneira distinta com base no que for
configurado nas variveis de ambiente.
Se a aplicao crescer, as variveis podem ser carregadas
em arquivos e parametrizadas no docker-compose.yml com
a opo env_file.
Servios de Apoio
Seguindo a lista do modelo 12factor, temos Servios de
Apoio como quarta boa prtica.
Para contextualizar, servios de apoio qualquer aplicao
que seu cdigo consome para operar corretamente (Ex.: banco
de dados, servio de mensagens e afins).

Com objetivo de evitar que o cdigo seja demasiadamente de-


pendente de determinada infraestrutura, a boa prtica indica
que voc, no momento da escrita do software, no faa dis-
tino entre servio interno ou externo. Ou seja, o aplicativo
deve estar pronto para receber parmetros que configurem
o servio corretamente e, assim, possibilitem o consumo de
aplicaes necessrias soluo proposta.
http://12factor.net/pt_br
Servios de Apoio 104

A aplicao exemplo sofreu modificaes para suportar a boa


prtica:

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 cdigo acima, a aplicao agora


recebe variveis de ambiente para configurar o hostname e
a porta do servio Redis. Nesse caso, possvel configurar o
host e a porta da Redis que deseja conectar. E isso pode e deve
ser especificado no docker-compose.yml que tambm passou
por mudana para se adequar a nova boa prtica:
Servios de Apoio 105

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 cdigos j tratados, a vantagem da


boa prtica passa pela possibilidade de mudana de compor-
tamento sem mudana do cdigo. Mais uma vez possvel
viabilizar que, o mesmo cdigo construdo em um momento,
possa ser reutilizado de forma semelhante, tanto no notebook
do desenvolvedor como no servidor de produo.
Fique atento para armazenamento de segredos dentro do
Servios de Apoio 106

docker-compose.yml, pois esse arquivo enviado para o


repositrio de controle de verso e importante pensar outra
estratgia de manuteno de segredos.
Uma estratgia possvel a manuteno de variveis de
ambiente no Docker Host. Dessa forma, voc precisa usar
variveis do tipo ${variavel} dentro do docker-compose.yml
para repassar a configurao ou, utilizar outro recurso mais
avanado de gerenciamento de segredos.
Construa, lance,
execute
O prximo item da lista do modelo 12factor, Construa,
lance, execute a quinta boa prtica..
No processo de automatizao de infraestrutura de implan-
tao de software precisamos cuidado para que o compor-
tamento do processo esteja dentro das expectativas e erros
humanos causem baixo impacto no processo completo do
desenvolvimento, do lanamento produo.

Visando organizar, dividir responsabilidade e tornar o pro-


cesso mais claro, o 12factor indica que o cdigo base, para ser
colocado em produo, deva passar por trs fases:

Construa - converter cdigo do repositrio em pacote


executvel. Nesse processo se obtm as dependncias,
compila-se o binrio e os ativos do cdigo.
http://12factor.net/pt_br/
Construa, lance, execute 108

Lance - pacote produzido na fase construir combi-


nado com a configurao. O resultado o ambiente
completo, configurado e pronto para ser colocado em
execuo.
Execute (tambm conhecido como runtime) - inicia
a execuo do lanamento (aplicao + configurao
daquele ambiente), com base nas configuraes espec-
ficas do ambiente requerido.

A boa prtica indica que a aplicao tenha separaes expl-


citas nas fases de Construa, Lance e Execute. Assim, cada
mudana no cdigo da aplicao, construda apenas uma
vez na etapa de Construa. Mudanas da configurao no
necessitam nova construo, sendo necessrio, apenas, as
etapas de lanar e executar.
De tal forma, possvel criar controles e processos claros em
cada etapa. Caso algo ocorra na construo do cdigo, uma
medida pode ser tomada ou mesmo se cancela o lanamento,
para que o cdigo em produo no seja comprometido por
conta do possvel erro.
Com a separao das responsabilidades possvel saber em
qual etapa o problema aconteceu e atuar manualmente, caso
necessrio.
Os artefatos produzidos devem ter um identificador de lan-
amento nico. Pode ser o timestamp (como 2011-04-06-
20:32:17) ou um nmero incremental (como v100). Com o
artefato nico possvel garantir o uso de verso antiga,
seja para plano de retorno ou, at mesmo, para comparar
comportamentos aps mudanas no cdigo.
Para atendermos a boa prtica precisamos construir a imagem
Docker com a aplicao dentro. Ela ser nosso artefato.
Construa, lance, execute 109

Teremos um script novo, aqui chamado build.sh, com o se-


guinte contedo:

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 tambm"
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

Alm de construir a imagem, a envia para o repositrio de


imagem do Docker.
Lembre-se que, o cdigo acima e os demais da boa prtica,
esto no repositrio na pasta factor5.
O envio da imagem para o repositrio parte importante da
boa prtica em questo, pois isola o processo. Caso a imagem
no seja enviada para o repositrio, permanece apenas no
servidor que executou o processo de construo, sendo assim,
a prxima etapa precisa, necessariamente, ser executada no
mesmo servidor, pois tal etapa precisa da imagem disponvel.
http://hub.docker.com/
https://github.com/gomex/exemplo-12factor-docker
Construa, lance, execute 110

No modelo proposto, a imagem no repositrio central fica


disponvel para ser baixada no servidor. Caso utilize uma fer-
ramenta de pipeline, importante - ao invs de utilizar a data
para tornar o artefato nico - usar variveis do produto para
garantir que a imagem a ser consumida na etapa Executar,
seja a mesma construda na etapa Lanar. Exemplo no GoCD:
variveis GO_PIPELINE_NAME e GO_PIPELINE_COUN-
TER podem ser usadas em conjunto como garantia.
Com a gerao da imagem podemos garantir que a etapa
Construir foi atendida perfeitamente, pois, agora temos um
artefato construdo e pronto para ser reunido configurao.
A etapa de Lanamento o arquivo docker-compose.yml
em si, pois o mesmo recebe as configuraes devidas para o
ambiente no qual se deseja colocar a aplicao. Sendo assim, o
arquivo docker-compose.yml muda um pouco e deixa de fazer
a construo da imagem, j que, agora, ser utilizado apenas
para Lanamento e Execuo (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
Construa, lance, execute 111

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 latest


para garantir que busque sempre a ltima imagem construda
no processo. Mas como j mencionamos, caso utilize alguma
ferramenta de entrega contnua (como GoCD, por exemplo)
faa uso das variveis, para garantir a imagem criada na
execuo especfica do pipeline.
Dessa forma, lanamento e execuo utilizaro o mesmo
artefato: a imagem Docker, construda na fase de construo.
A etapa de execuo, basicamente, executa o Docker-Compose
com o comando abaixo:

1 docker-compose up -d
Processos
Seguindo a lista do modelo 12factor, temos Processos
como sexta boa prtica.
Com o advento da automatizao e devida inteligncia na
manuteno das aplicaes, hoje, esperado que a aplicao
possa atender a picos de demandas com inicializao autom-
tica de novos processos, sem afetar seu comportamento.

A boa prtica indica que processos de aplicaes 12factor so


stateless (no armazenam estado) e share-nothing. Quaisquer
dados que precisem persistir devem ser armazenados em
servio de apoio stateful (armazena o estado), normalmente
usado uma base de dados.
O objetivo final dessa prtica no faz distino se a aplicao
executada na mquina do desenvolvedor ou em produo,
pois, nesse caso, o que muda a quantidade de processos
iniciados para atender as respectivas demandas. Na mquina
http://12factor.net/pt_br
Processos 113

do desenvolvedor pode ser apenas um e, em produo, um


nmero maior.
O 12factor indica que o espao de memria ou sistema de
arquivos do servidor pode ser usado brevemente como cache
de transao nica. Por exemplo, o download de um arquivo
grande, operando sobre ele e armazenando os resultados no
banco de dados.
Vale salientar que, um estado nunca deve ser armazenado
entre requisies, no importando o estado do processamento
da prxima requisio.
importante salientar: ao seguir a prtica, uma aplicao
no assume que, qualquer item armazenado em cache de
memria ou no disco, estar disponvel em futura solicitao
ou job com muitos processos de cada tipo rodando, so
altas as chances de futura solicitao ser servida por processo
diferente, at mesmo em servidor diferente. Mesmo quando,
rodando em apenas um processo, um restart (desencadeado
pelo deploy de um cdigo, mudana de configurao, ou o
ambiente de execuo realocando o processo para localizao
fsica diferente) geralmente vai acabar com o estado local
(memria e sistema de arquivos, por exemplo).
Algumas aplicaes demandam de sesses persistentes para
armazenar informaes da sesso de usurios e afins. Tais
sesses so usadas em futuras requisies do mesmo visitante.
Ou seja, se armazenado junto ao processo, clara violao
da boa prtica. Nesse caso, aconselhvel usar servio de
apoio, tal como redis, memcached ou afins para esse tipo
de trabalho externo ao processo. Com isso, possvel que
o prximo processo, independente de onde esteja, consegue
obter as informaes atualizadas.
A aplicao que estamos trabalhando no guarda dado local e
Processos 114

tudo o que precisa armazenado no Redis. No precisamos fa-


zer adequao alguma nesse cdigo para seguir a boa prtica,
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 cdigo da prtica, acesse o repositrio e a


pasta factor6.
https://github.com/gomex/exemplo-12factor-docker
Vnculo de portas
De acordo com a lista do modelo 12factor, a stima boa
prtica Vnculo de portas.
comum encontrar aplicaes executadas dentro de conti-
neres de servidores web, tal como Tomcat, ou Jboss, por exem-
plo. Normalmente, essas aplicaes so implantadas dentro
dos servios para que possam ser acessadas pelos usurios
externamente.
http://12factor.net/pt_br
Vnculo de portas 116

A boa prtica sugere que o aplicativo em questo seja auto-


contido e dependa de um servidor de aplicao, tal como
Jboss, Tomcat e afins. O software deve exportar um servio
HTTP e lidar com as requisies que chegam por ele. Significa
que, qualquer aplicao adicional desnecessria para o
cdigo estar disponvel comunicao externa.
Tradicionalmente, a implantao de artefato em servidor de
aplicao, tal como Tomcat e Jboss, exige a gerao de um
artefato e, esse, enviado para o servio web em questo. Mas
no modelo de continer Docker, a idia que o artefato do
processo de implantao seja o prprio continer.
O processo antigo de implantao do artefato em servidor de
Vnculo de portas 117

aplicao, normalmente, no tinha retorno rpido, o que au-


mentava demasiadamente o processo de implantao de um
servio, pois, cada alterao demandava enviar o artefato para
o servio de aplicao web; e, esse tinha a responsabilidade de
importar, ler e executar o novo artefato.
Usando Docker, facilmente, a aplicao torna-se auto-contida.
J construmos um Dockerfile que descreve o que a aplicao
precisa:

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 dependncias esto descritas no arquivo requirements.txt e


os dados que devem ser persistidos so geridos por um servio
externo (servios de apoio) aplicao.
Outro detalhe da boa prtica: a aplicao deve exportar o
servio atravs da vinculao a uma nica porta. Como vemos
no cdigo exemplo, a porta padro do python (5000) iniciada,
mas voc pode escolher outra, se julgar necessrio. Segue o
recorte do cdigo 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 localmente


em ambiente de desenvolvimento ou, atravs de proxy re-
verso, quando for migrada para produo, com nome de
domnio adequado a aplicao em questo.
Vnculo de portas 118

Utilizar o modelo de vinculao de portas torna o processo


de atualizao de aplicao mais fludo, uma vez que, na uti-
lizao de um proxy reverso inteligente, possvel adicionar
novos ns gradativamente, com a nova verso, e remover os
antigos medida que as verses atualizadas so executadas
em paralelo.
Convm salientar: mesmo que o Docker permita a utilizao
de mais de uma porta por contineres, a boa prtica enfatiza
que voc s deve utilizar uma porta vinculada por aplicao.
Concorrncia
A oitava boa prtica da lista do modelo 12factor, Con-
corrncia.
Durante o processo de desenvolvimento de uma aplicao
difcil imaginar o volume de requisio que ela ter no
momento que for colocada em produo. Por outro lado, um
servio que suporte grandes volumes de uso esperado nas
solues modernas. Nada mais frustante que solicitar acesso
a uma aplicao e ela no estar disponvel. Sugere falta de
cuidado e profissionalismo, na maioria dos casos.
Quando a aplicao colocada em produo, normalmente
dimensionada para determinada carga esperada, porm
importante que o servio esteja pronto para escalar. A soluo
deve ser capaz de iniciar novos processo da mesma aplicao,
caso necessrio, sem afetar o produto. A figura abaixo, apre-
senta grfico de escalabilidade de servios.
http://12factor.net/pt_br
Concorrncia 120

Com objetivo de evitar qualquer problema na escalabilidade


do servio, a boa prtica indica que as aplicaes devem su-
portar execues concorrentes e, quando um processo est em
execuo, instanciar outro em paralelo e o servio atendido,
sem perda alguma.
Para tal, importante dividir as tarefas corretamente. inte-
ressante o processo se ater aos objetivos, caso seja necessrio
executar alguma atividade em backend e, depois retornar uma
pgina para o navegador, salutar que haja dois servios tra-
tando as duas atividades, de forma separada. O Docker torna
essa tarefa mais simples, pois, nesse modelo, basta especificar
um container para cada funo e configurar corretamente a
rede entre eles.
Para exemplificar a boa prtica, usaremos a arquitetura de-
monstrada na figura abaixo:
Concorrncia 121

O servio web responsvel por receber a requisio e balan-


cear entre os workers, os quais so responsveis por processar
a requisio, conectar ao redis e retornar a tela de Hello
World informando quantas vezes foi obtida e qual nome
de worker est respondendo a requisio (para ter certeza
que est balanceando a carga), como podemos ver na figura
abaixo:

O arquivo docker-compose.yml exemplifica a boa prtica:

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:
Concorrncia 122

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 construo do balanceador de carga, temos o


diretrio web contendo arquivos Dockerfile (responsvel por
criar a imagem utilizada) e nginx.conf (arquivo de configura-
o do balanceador de carga utilizado).
Segue o contedo 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 contedo do arquivo nginx.conf:


Concorrncia 123

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 configurao acima, foram introduzidas algu-


mas novidades. A primeira, resolver 127.0.0.11, o servio
DNS interno do Docker. Usando essa abordagem possvel
efetuar o balanceamento de carga via nome, usando recurso
interno 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/) (apenas em ingls).
https://docs.docker.com/engine/userguide/networking/configure-dns/
Concorrncia 124

A segunda novidade, funo set $alias apps;, responsvel


por especificar o nome apps usado na configurao do
proxy reverso, em seguida proxy_pass http://$alias;. Vale
salientar, o apps o nome da rede especificada dentro do
arquivo docker-compose.yml. Nesse caso, o balanceamento
feito para a rede, todo novo continer que entra nessa rede
automaticamente adicionado ao balanceamento de carga.
Para efetuar a construo do worker temos o diretrio wor-
ker contendo os arquivos Dockerfile (responsvel por criar
a imagem utilizada), app.py (aplicao usada em todos os
captulos) e requirements.txt (descreve as dependncias do
app.py).
Segue abaixo o contedo do arquivo app.py modificado para
a prtica:

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'))
Concorrncia 125

17 if __name__ == "__main__":
18 app.run(host="0.0.0.0", debug=True)

Segue o contedo do requirements.txt:

1 flask==0.11.1
2 redis==2.10.5

E por fim, o Dockerfile do worker tem o seguinte contedo:

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 servio redis no h construo da imagem, usaremos a


imagem oficial para efeitos de exemplificao.
Para testar o que foi apresentado at ento, realize o clone
do repositrio (https://github.com/gomex/exemplo-12factor-
docker) e acesse a pasta factor8, executando o comando,
abaixo, para iniciar os contineres:

1 docker-compose up -d

Acesse os contineres atravs do navegador na porta 80 do


endereo localhost. Atualize a pgina e veja que apenas um
nome aparece.
https://github.com/gomex/exemplo-12factor-docker
Concorrncia 126

Por padro, o Docker-Compose executa apenas uma instncia


de cada servio explicitado no docker-compose.yml. Para
aumentar a quantidade de contineres worker, de um para
dois, execute o comando abaixo:

1 docker-compose scale worker=2

Atualize a pgina no navegador e veja que o nome do host


alterna entre duas possibilidades, ou seja, as requisies esto
sendo balanceadas para ambos contineres.
Nessa nova proposta de ambiente, o servio web se encarrega
de receber as requisies HTTP e fazer o balanceamento
de carga. Ento, o worker responsvel por processar as
requisies, basicamente obter o nome de host, acessar o redis
e a contagem de quantas vezes o servio foi requisitado e,
ento, gerar o retorno para devolv-lo ao servio web que,
por sua vez, responde ao usurio. Como podemos perceber,
cada instncia do ambiente tem funo definida e, com isso,
mais fcil escal-lo.
Aproveitamos para dar os crditos ao capito Marcosnils,
que nos mostrou como possvel balancear carga pelo nome
da rede docker.
https://twitter.com/marcosnils
Descartabilidade
Na nona posio da lista do modelo 12factor, a Descarta-
bilidade.
Quando falamos de aplicaes web, espera-se que mais de
um processo atenda a todo trfego requisitado para o servio.
Porm, to importante quanto a habilidade de iniciar novos
processos, a capacidade de um processo defeituoso terminar
na mesma velocidade que iniciou, pois um processo que
demora para finalizar pode comprometer toda soluo, uma
vez que ela pode ainda estar atendemos requisies de forma
defeituosa.

Em resumo, podemos dizer que aplicaes web deveriam ser


capazes de remover rapidamente processos defeituosos.
Com objetivo de evitar que o servio prestado seja dependente
das instncias que o servem, a boa prtica indica que as
http://12factor.net/pt_br
Descartabilidade 128

aplicaes devem ser descartveis, ou seja, desligar uma de


suas instncias no deve afetar a soluo como um todo.
O Docker tem a opo de descartar automaticamente um
continer aps o uso - no docker container run utilize a
opo rm. Vale salientar que essa opo no funciona em
modo daemon (-d), portanto, s faz sentido utilizar no modo
interativo (-i).
Outro detalhe importante na boa prtica viabilizar que o
cdigo desligue graciosamente e reinicie sem erros. Assim,
ao escutar um SIGTERM, o cdigo deve terminar qualquer
requisio em andamento e ento desligar o processo sem
problemas e de forma rpida, permitindo, tambm, que seja
rapidamente atendido por outro processo.
Entendemos como desligamento gracioso uma aplicao
capaz de auto finalizar sem danos soluo; ao receber
sinal para desligar, imediatamente recusa novas requisies
e apenas finaliza as tarefas pendentes em execuo naquele
momento. Implcito nesse modelo: as requisies HTTP so
curtas (no mais que poucos segundos) e, nos casos de co-
nexes longas, o cliente pode se reconectar automaticamente
caso a conexo seja perdida.
A aplicao sofreu a seguinte mudana para atender a espe-
cificao:
Descartabilidade 129

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 cdigo acima, adicionamos tratamento para quando rece-


Descartabilidade 130

ber um sinal de SIGTERM, finalizar rapidamente o processo.


Sem o tratamento, o cdigo demora mais para ser desligado.
Dessa forma, conclumos que a soluo descartvel o su-
ficiente. Podemos desligar e reiniciar os containers em outro
Docker Host e a mudana no causar impacto na integridade
dos dados.
Para fins de entendimento sobre o que trabalhamos aqui,
cabe esclarecimento, de acordo com o Wikipedia, sinal : ()
notificao assncrona enviada a processos com o objetivo de
notificar a ocorrncia de um evento. E, o SIGTERM: ()
nome de um sinal conhecido por um processo informtico
em sistemas operativos POSIX. Este o sinal padro enviado
pelos comandos kill e killall. Ele causa o trmino do processo,
como em SIGKILL, porm pode ser interpretado ou ignorado
pelo processo. Com isso, SIGTERM realiza um encerramento
mais amigvel, permitindo a liberao de memria e o fecha-
mento dos arquivos.
Para realizar o teste do que foi apresentado at ento, realize
o clone do repositrio (https://github.com/gomex/exemplo-
12factor-docker) e acesse a pasta factor8 (isso mesmo, a
nmero 8, vamos demonstrar a diferena pra o factor9),
executando o comando abaixo para iniciar os contineres:

1 docker-compose up -d

Depois, execute o comando abaixo para finalizar os contine-


res:

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

1 time docker-compose stop

Voc ver que a finalizao do worker demora cerca de 11


segundos, isso porque o comportamento do Docker-Compose,
para finalizar, primeiro faz um SIGTERM e espera por 10
segundos que a aplicao finalize sozinha, caso contrrio,
envia um SIGKILL que finaliza o processo bruscamente. Esse
timeout configurvel. Caso deseje modificar, basta usar o
parmetro -t ou timeout. Veja um exemplo:

1 docker-compose stop -t 5

Obs: O valor informado, aps o parmetro, considerado em


segundos.
Agora, para testar o cdigo modificado, mude para a pasta
factor9 e execute o seguinte comando:

1 docker-compose up -d

Depois, solicite o trmino:

1 time docker-compose stop

Veja que o processo worker finalizou mais rpido, pois re-


cebeu o sinal SIGTERM. A aplicao fez o servio de auto
finalizao e no precisou receber um sinal SIGKILL para ser,
de fato, finalizado.
Paridade entre desen-
volvimento/produo
Seguindo a lista do modelo 12factor, temos Paridade entre
desenvolvimento/produo como dcima boa prtica.

Infelizmente, na maioria dos ambientes de trabalho com


software, existe grande abismo entre desenvolvimento e pro-
duo. No mero acaso ou falta de sorte, existe por conta
das diferenas entre as equipes de desenvolvimento e as de
infraestrutura. E, de acordo com o 12factor, manifestam-se
nos seguintes mbitos:

Tempo: o desenvolvedor pode trabalhar um cdigo que


demora dias, semanas ou at meses para ser transferido
produo.
Pessoal: desenvolvedores escrevem cdigo, engenhei-
ros de operao fazem o deploy do cdigo.
Ferramentas: desenvolvedores podem usar conjuntos
como Nginx, SQLite e OS X, enquanto o app em produ-
o, usa Apache, MySQL e Linux.
http://12factor.net/pt_br
Paridade entre desenvolvimento/produo 133

O 12factor pretende colaborar para reduzir o abismo entre as


equipes e equalizar os ambientes. Com relao aos mbitos
apresentados, seguem as respectivas propostas:

Tempo: desenvolvedor pode escrever cdigo e ter o


deploy concludo em horas ou at mesmo minutos
depois.
Pessoal: desenvolvedores que escrevem cdigo esto
proximamente envolvidos em realizar o deploy e acom-
panhar o comportamento na produo.
Ferramentas: manter desenvolvimento e produo o
mais similares possvel.

A soluo de continer tem como um dos principais objetivos


colaborar com a portabilidade entre ambiente de desenvolvi-
mento e produo. A ideia que a imagem seja construda e
apenas seu status modifique para ser posta em produo. O
cdigo atual j est pronto para esse comportamento, assim,
no h muito a ser modificado para garantir a boa prtica.
como um bnus pela adoo do Docker e o seguimento das
outras boas prticas do 12factor.
Logs
A dcima primeira boa prtica, na lista do modelo 12factor,
Logs.

No desenvolvimento de cdigo, gerar dados para efeitos de


log algo bastante consolidado. No acreditamos que existam
softwares em desenvolvimento sem essa preocupao. Porm,
o uso correto do log vai alm de, apenas, gerar dados.
Para efeito de contextualizao, de acordo com o 12factor,
o log : () fluxo de eventos agregados e ordenados por
http://12factor.net/pt_br
Logs 135

tempo coletados dos fluxos de sada de todos os processos em


execuo e servios de apoio.
Logs, normalmente, so armazenados em arquivos, com even-
tos por linha (pilhas de exceo podem ocupar vrias linhas).
Mas essa prtica no indicada, ao menos no na perspectiva
da aplicao. Isso quer dizer que, a aplicao no deveria se
preocupar em qual arquivo guardar os logs.
Especificar arquivos, implica informar o diretrio correto
desse arquivo, que, por sua vez, resulta em configurao
prvia do ambiente. Isso impacta, negativamente, na porta-
bilidade da aplicao, pois necessrio que, o ambiente que
receber a soluo, siga uma srie de requisitos tcnicos para
suportar a aplicao, enterrando, assim, a possibilidade do
Construa uma vez, rode em qualquer lugar.
A boa prtica indica que as aplicaes no devem gerenciar
ou rotear arquivos de log, mas devem ser depositados sem
qualquer esquema de buffer na sada padro (STDOUT).
Assim, uma infraestrutura externa aplicao - plataforma -
deve gerenciar, coletar e formatar a sada dos logs para futura
leitura. Isso realmente importante quando a aplicao est
rodando em vrias instncias.
Com o Docker, tal tarefa se torna fcil, pois o Docker j coleta
logs da sada padro e encaminha para algum dos vrios
drivers de log. O driver pode ser configurado na inicializao
do container de forma a centralizar os logs no servio remoto
de logs, por exemplo syslog.
O cdigo exemplo no repositrio(https://github.com/gomex/exemplo-
12factor-docker), na pasta factor11, est pronto para testar
a boa prtica, pois j envia todas as sadas de dados para
https://github.com/gomex/exemplo-12factor-docker
Logs 136

STDOUT e voc pode conferir iniciando o servio com o


comando abaixo:

1 docker-compose up

Depois de iniciar, acesse o navegador e verifique as requi-


sies da aplicao que aparecem na console do Docker-
Compose.
Processos de
administrao
Dcima segunda e ltima boa prtica da lista do modelo
12factor: Processos de administrao.
http://12factor.net/pt_br
Processos de administrao 138

Toda aplicao demanda administrao. Isso quer dizer que,


uma vez implantada, possvel que a aplicao precise receber
determinados comandos para corrigir possveis problemas
ou simplesmente mudar de comportamento. Como exemplos
temos migraes de banco de dados, execuo de scripts
diversos como backup e, tambm, execuo de um console
para inspeo do servio.
A boa prtica recomenda processos de administrao exe-
Processos de administrao 139

cutados em ambientes idnticos ao utilizado no cdigo em


execuo, seguindo todas as prticas apresentadas at ento.
Usando Docker possvel rodar os processos utilizando a
mesma imagem base no ambiente de execuo que desejar.
Com isso, podemos nos beneficiar da comunicao entre os
contineres e do uso de volumes que forem necessrios e afins.
Para exemplificar a boa prtica 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)

Responsvel por reinicializar o contador de visitas do Redis,


o comando dado usando um continer diferente a partir da
mesma imagem Docker. Primeiro iniciamos o ambiente, baixe
o repositrio e acesse a pasta factor12 e execute o comando:

1 docker-compose up

Acesse a aplicao pelo navegador. Caso esteja usando GNU/-


Linux ou Docker For MAC e Windows, acesse o endereo
127.0.0.1. Voc ver a seguinte frase:
Processos de administrao 140

1 Hello World! 1 times.

Acesse a aplicao mais algumas vezes para o marcador


aumentar.
Depois, execute o comando de administrao a partir do
servio worker:

1 docker-compose exec worker python reset.py

O comando python reset.py ser executado dentro de um


novo continer, mas usando a mesma imagem de um worker
regular.
Acesse novamente a aplicao e verifique se o marcador
iniciou a partir de 1 novamente.
Dicas para uso do
Docker
Se voc leu a primeira parte do livro j sabe o bsico sobre
Docker, mas agora que pretende comear a usar com mais
frequncia, alguns desconfortos podem surgir, pois, como
qualquer ferramenta, o Docker tem seu prprio conjunto de
boas prticas e dicas.
O objetivo dessse texto apresentar algumas dicas para o bom
uso do Docker. Isso no quer dizer que, a forma que voc
executa , necessariamente, errada.
Toda ferramenta demanda algumas melhores prticas para
tornar o uso mais efetivo e com menor possibilidade de
problemas futuros.
Esse captulo foi separado em duas sees: dicas para rodar
(docker container run) e boas prticas de construo de
imagens (docker build/Dockerfile).

Dicas para Rodar


Lembre-se, cada comando docker container run cria novo
continer com base em uma imagem especfica e inicia um
processo dentro dele, a partir de um comando (CMD especifi-
cado no Dockerfile).
Dicas para uso do Docker 142

Continers descartveis
esperado que os continers executados possam ser des-
cartados sem qualquer problema. Sendo assim, importante
utilizar continers verdadeiramente efmeros.
Para tal, utilize o argumento --rm. Isso faz com que todos os
continers, e seus dados, sejam removidos aps o termino da
execuo, 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. usado


para fixar a linha de comando com o continer, assim, aps
esse docker container run, todos os comandos so executa-
dos pelo bash de dentro do continer. Para sair use exit ou
pressione Control-d. Esses parmetros so muito teis para
executar um continer em primeiro plano.

Verifique variveis de ambiente


s vezes faz-se necessrio verificar qual metadados so de-
finidos como variveis de ambiente em uma imagem. Use o
comando env para obter essa informao:

1 docker container run --rm -it debian env

Para verificar as variveis de ambientes passados de um


continer j criado:
Dicas para uso do Docker 143

1 docker inspect --format '{{.Config.Env}}' <contai\


2 ner>

Para outros metadados, use variaes do comando docker


inspect.

Logs
Docker captura logs da sada padro (STDOUT) e sada de erros
(STDERR).
Esses registros podem ser roteados para diferentes sistemas
(syslog, fluentd, ) que, podem ser especificados atravs da
configurao de driver --log-driver=VALUE no comando
docker container run.

Quando utilizado o driver padro json-file (e tambm jour-


nald), pode-se utilizar o seguinte comando para recuperar os
logs:

1 docker logs -f <container_name>

Observe tambm o argumento -f para acompanhar as pr-


ximas mensagens de log de forma interativa. Quando quiser
parar, pressione Ctrl-c .

Backup
Dados em continers Docker so expostos e compartilhados
atravs de argumentos de volumes utilizados ao criar e iniciar
o continer. Esses volumes no seguem as regras do Union File
https://docs.docker.com/engine/admin/logging/overview/
Dicas para uso do Docker 144

System, pois os dados persistem mesmo quando o continer


removido.
Para criar um volume em determinado continer, execute da
seguinte forma:

1 docker container run --rm -v /usr/share/nginx/htm\


2 l --name nginx_teste nginx

Com a execuo desse container, teremos servio Nginx que


usa o volume criado para persistir seus dados; os dados
persistiro mesmo aps o continer ser removido.
boa prtica de administrao de sistema fazer cpias de
segurana (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

Aps a execuo 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

https://docs.docker.com/engine/reference/glossary/#union-file-system
Dicas para uso do Docker 145

Mais informao tambm podem ser encontradas na res-


posta, onde possvel encontrar alguns aliases para es-
ses dois comandos. Esses aliases tambm esto disponveis
abaixo, na seo Aliases.
Outras fontes so:

Documentao oficial do Docker sobre Backup, restau-


rao ou migrao de dados (em ingls)
Uma ferramenta de backup (atualmente deprecada):
docker-infra/docker-backup

Use docker container exec para entrar


em um continer
Eventualmente, necessrio entrar em um continer em
execuo afim de verificar algum problema, efetuar testes ou
simplemente depurar (debug). Nunca instale o daemon SSH
em um continer Docker. Use docker container exec para
entrar em um continer e rodar comandos:

1 docker container exec -it <nome do container em e\


2 xecuo> bash

A funcionalidade til em desenvolvimento local e experi-


mentaes. Mas evite utilizar o continer em produo ou
automatizar ferramentas em volta dele.
Verifique a documentao.
http://stackoverflow.com/a/34776997/1046584
https://docs.docker.com/engine/userguide/containers/dockervolumes/#backup-
restore-or-migrate-data-volumes
https://github.com/docker-infra/docker-backup
https://docs.docker.com/engine/reference/commandline/exec/
Dicas para uso do Docker 146

Sem espao em disco do Docker Host


Ao executar continers e construir imagens vrias vezes, o
espao em disco pode se tornar escasso. Quando isso acontece,
necessrio limpar alguns continers, imagens e logs.
Uma maneira rpida de limpar continers e imagens utilizar
o seguinte comando:

1 docker system prune

Com esse comando voc remover:

Todos os continers que no esto em uso no momento


Todos os volumes que no esto em uso por ao menos
um continer
Todas as redes que no esto em uso por ao menos um
continer
Todas as imagens dangling

Obs: Pra no aprofundar muito no conceito baixo nvel do


Docker, podemos dizer que imagens dangling so simples-
mente sem ponteiros e assim desnecessrias para o uso con-
vencional.
Dependendo do tipo de aplicao, logs tambm podem ser
volumosos. O gerenciamento depende muito de qual driver
utilizado. No driver padro (json-file) a limpeza pode
se dar atravs da execuo do seguinte comando dentro do
Docker Host:

https://docs.docker.com/engine/admin/logging/overview/
Dicas para uso do Docker 147

1 echo "" > $(docker inspect --format='{{.LogPath}}\


2 ' <container_name_or_id>)

A proposta de funcionalidade de limpar o histrico


de logs foi, na verdade, rejeitada. Mais informao:
https://github.com/docker/compose/issues/1083
Considere especificar a opo max-size para o driver de
log ao executar docker container run: https://docs.docker.com/engine
file-options

Aliases
Com alias possvel transformar comandos grandes em me-
nores. Temos algumas novas opes para executar tarefas
mais complexas.
Utilize esses aliases no seu .zshrc ou .bashrc para limpar
imagens e continers, fazer backup e restaurao, 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

https://github.com/docker/compose/issues/1083
https://docs.docker.com/engine/reference/logging/overview/#json-file-options
Dicas para uso do Docker 148

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
Dicas para uso do Docker 149

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 }
Dicas para uso do Docker 150

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/
https://website-humblec.rhcloud.com/docker-tips-and-
tricks/

Boas prticas para construo de


imagens
Em Docker, as imagens so tradicionalmente construdas
usando um arquivo Dockerfile. Existem alguns bons guias
sobre as melhores prticas para construir imagens Docker.
Recomendamos dar uma olhada:

Documentao oficial
https://zwischenzugs.wordpress.com/2015/06/14/my-favourite-docker-tip/
https://website-humblec.rhcloud.com/docker-tips-and-tricks/
https://docs.docker.com/engine/articles/dockerfile_best-practices/
Dicas para uso do Docker 151

Guia do projeto Atomic


Melhores prticas do Michael Crosby Parte 1
Melhores prticas do Michael Crosby Parte 2

Use um linter
Linter uma ferramenta que fornece dicas e avisos sobre
algum cdigo fonte. Para Dockerfile existem opes simples,
mas , ainda, um espao novo em evoluo.
Muitas opes foram discutidas aqui.
Desde janeiro de 2016, o mais completo parece ser hadolint,
disponvel em duas verses: on-line e terminal. O interessante
dessa ferramenta que usa o maduro Shell Check para
validar os comandos shell.

O bsico
O continer produzido pela imagem do Dockerfile deve ser
o mais efmero possvel. Significa que deve ser possvel para-
lo, destru-lo e substitu-lo por um novo continer construdo
com o minimo de esforo.
comum colocar outros arquivos, como documentao, no
diretrio junto ao Dockerfile; para melhorar a performance
de construo, exclua arquivos e diretrios criando um ar-
quivo dockerignore no mesmo diretrio. Esse arquivo fun-
ciona de maneira semelhante ao .gitignore. Us-lo ajuda a
http://www.projectatomic.io/docs/docker-image-author-guidance/
http://crosbymichael.com/dockerfile-best-practices.html
http://crosbymichael.com/dockerfile-best-practices.html
https://stackoverflow.com/questions/28182047/is-there-a-way-to-lint-the-dockerfile
http://hadolint.lukasmartinelli.ch/
http://www.shellcheck.net/about.html
https://docs.docker.com/engine/reference/builder/
Dicas para uso do Docker 152

minimizar o contexto de construo enviado -completa com


a verso correta- docker host a cada docker build.
Evite adicionar pacotes e dependncias extras no necessrias
aplicao e minimize a complexidade, tamanho da imagem,
tempo de contruo e superfcie de ataque.
Minimize tambm o nmero de camadas: sempre que possvel
agrupe vrios comandos. Porm, tambm leve em conta a
volatilidade e manuteno dessas camadas.
Na maioria dos casos, rode apenas um nico processo por
continer. Desacoplar aplicaes em vrios continers faci-
lita a escalabilidade horizontal, reuso e monitoramento dos
continers.

Prefira COPY ao invs de ADD


O comando ADD existe desde o incio do Docker. verstil
e permite truques alm de simplesmente copiar arquivos do
contexto de construo, o que o torna mgico e difcil de
entender. 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 inserir
arquivos e pastas do caminho de construo para dentro da
imagem Docker. Assim, favorea COPY a menos que tenha
certeza absoluta que ADD necessrio. Para mais detalhes veja
aqui.
https://labs.ctl.io/dockerfile-add-vs-copy/
Dicas para uso do Docker 153

Execute um checksum depois de


baixar e antes de usar o arquivo
Em vez de usar ADD para baixar e adicionar arquivos
imagem, favorea a utilizao de curl e a verificao atravs
de um checksum aps o download. Isso garante que o arquivo
o esperado e no poder variar ao longo do tempo. Se o
arquivo que a URL aponta mudar, o checksum ir mudar
e a construo da imagem falhar. Isso importante, pois,
favorece a reproducibilidade e a segurana na construo de
imagens.
Bom exemplo para inspirao o Dockerfile oficial do Jen-
kins:

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 mnima


Sempre que possvel, utilize imagens oficiais como base para
sua imagem. Voc pode usar a imagem debian, por exem-
plo, que muito bem controlada e mantida mnima (por volta
https://curl.haxx.se/
https://github.com/jenkinsci/docker/blob/83ce6f6070f1670563a00d0f61d04edd62b78f4f/
Dockerfile#L36
https://hub.docker.com/_/debian/
Dicas para uso do Docker 154

de 150 mb). Lembre-se tambm usar tags especficas, por


exemplo, debian:jessie.
Se mais ferramentas e dependncias so necessrias, olhe por
imagens como buildpack-deps.
Porm, caso debian ainda seja muito grande, existem imagens
minimalistas como alpine ou mesmo busybox. Evite al-
pine se DNS necessrio, existem alguns problemas a serem
resolvidos. Alm disso, evite-o para linguagens que usam
o GCC, como Ruby, Node, Python, etc, isso porque alpine
utiliza libc MUSL que pode produzir binrios diferentes.
Evite imagens gigantes como phusion/baseimage. Essa
imagem muito grande, foge da filosofia de processo por
continer e muito do que a compe no essencial para
continers Docker, veja mais aqui .
Outras fontes

Use o cache de construo de camadas


Outra funcionalidade til que o uso de Dockerfile propor-
ciona a reconstruo rpida usando o cache de camadas. A
fim de aproveitar o recurso, insira ferramentas e dependncias
que mudem com menos frequncia no topo do Dockerfile.
Por exemplo, considere instalar as dependncias de cdigo
antes de adicionar o cdigo. No caso de NodeJS:

https://hub.docker.com/_/buildpack-deps/
https://hub.docker.com/r/gliderlabs/alpine/
https://hub.docker.com/r/gliderlabs/alpine/
https://github.com/gliderlabs/docker-alpine/blob/master/docs/caveats.md
https://hub.docker.com/r/phusion/baseimage/
https://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/
http://www.iron.io/microcontainers-tiny-portable-containers/
Dicas para uso do Docker 155

1 COPY package.json /app/


2 RUN npm install
3 COPY . /app

Para ler mais sobre isso, veja esse link.

Limpe na mesma camada


Ao usar um gerenciador de pacotes para instalar algum soft-
ware, uma boa prtica limpar o cache gerado pelo gerenci-
ador de pacotes logo aps a instalao das dependncias. Por
exemplo, 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) atravs da remoo de /var/lib/apt/lists.
Isso ajuda a manter reduzido o tamanho da imagem. Alm
disso, observe que, pip e curl tambm so removidos uma
vez que so desnecessrios para a aplicao de produo.
Lembre-se que a limpeza precisa ser feita na mesma camada
(comando RUN). Caso contrrio, os dados sero persistidos
nessa camada e remov-los mais tarde no ter efeito no
tamanho da imagem final.
http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/
Dicas para uso do Docker 156

Note que, segundo a documentao, as imagens oficiais de


Debian e Ubuntu rodam automaticamente apt-get clean.
Logo, a invocao explcita no necessria.
Evite rodar apt-get upgrade ou dist-upgrade, pois, vrios
pacotes da imagem base no vo atualizar dentro de um con-
tiner desprovido de privilgios. Se h um pacote especfico
a ser atualizado, simplesmete use apt-get install -y foo
para atualiz-lo automaticamente.
Para ler mais sobre o assunto, veja o link e esse outro.

Use um script wrapper como


ENTRYPOINT, s vezes
Um script wrapper pode ajudar ao tomar a configurao
do ambiente e definir a configurao do aplicativo. Pode,
at mesmo, definir configuraes padres quando no esto
disponveis.
timo exemplo o fornecido no artigo de Kelsey Hightower:
12 Fracturated Apps:

https://github.com/docker/docker/blob/03e2923e42446dbb830c654d0eec323a0b4ef02a/
contrib/mkimage/debootstrap#L82-L105
http://blog.replicated.com/2016/02/05/refactoring-a-dockerfile-for-image-size/
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#apt-
get
https://medium.com/@kelseyhightower/12-fractured-apps-1080c73d481c#
.xn2cylwnk
Dicas para uso do Docker 157

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 a


aplicao. Desta forma, a aplicao pode receber sinais Unix.
Considere tambm usar um sistema de inicializao simples
(e.g. dumb init) como a CMD base, assim, os sinais do Unix
podem ser devidamente tratados. Leia mais aqui.

Log para stdout

Aplicaes dentro de Docker devem emitir logs para stdout.


Porm, algumas aplicaes escrevem os logs em arquivos.
https://github.com/Yelp/dumb-init
http://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html
Dicas para uso do Docker 158

Nestes casos, a soluo criar um symlink do arquivo para


stdout.
Exemplo: Dockerfile do nginx:

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 link.

Cuidado ao adicionar dados em um


volume no Dockerfile
Lembre-se de usar a instruo VOLUME para expor dados de
bancos de dados, configurao ou arquivos e pastas criados
pelo continer. Use para qualquer dado mutvel e partes
servidas ao usurio do servio para qual a imagem foi criada.
Evite adicionar muitos dados em uma pasta e, em seguida,
transform-lo em VOLUME apenas na inicializao do conti-
ner, pois, nesse momento, pode tornar o carregamento mais
lento. Ao criar continer, os dados sero copiados da imagem
para o volume montado. Como dito antes, use VOLUME na
criao da imagem.
Alm disso, ainda em tempo de criao da imagem (build),
no adicione dados para caminhos previamente declarados
como VOLUME. Isso no funciona, os dados no sero persisti-
dos, pois, dados em volumes no so comitados em imagens.
Leia mais na explicao de Jrme Petazzoni.
https://github.com/nginxinc/docker-nginx/blob/master/Dockerfile
https://serverfault.com/questions/599103/make-a-docker-application-write-to-stdout
https://jpetazzo.github.io/2015/01/19/dockerfile-and-data-in-volumes/
Dicas para uso do Docker 159

EXPOSE de portas
O Docker favorece reproducibilidade e portabilidade. Imagens
devem ser capazes de rodar em qualquer servidor e quantas
vezes forem necessrias. Dessa forma, nunca exponha portas
pblicas. Porm, exponha, de maneira privada, as portas
padres da aplicao.

1 # mapeamento pblico e privado, evite


2 EXPOSE 80:8080
3
4 # apenas privado
5 EXPOSE 80
Apndice
Container ou mquina virtual?
Aps o sucesso repentino do Docker - virtualizao com
base em continers - muitas pessoas tm se questionado
sobre possvel migrao do modelo de mquina virtual para
continers.

Respondemos tranquilamente: Os dois!


Ambos so mtodos de virtualizao, mas atuam em cama-
das distintas. Vale a pena detalhar cada soluo para deixar
claro que, no so, necessariamente, concorrentes.
Apndice 161

Mquina virtual
Conceito antigo, oriundo dos Mainframes em meados de 1960.
Cada operador tinha a viso de estar acessando uma mquina
dedicada, mas na verdade, todo recurso do Mainframe, era
compartilhado para todos os operadores.
O objetivo do modelo compartilhar recursos fsicos entre
vrios ambientes isolados, sendo que, cada um deles tem sob
tutela uma mquina inteira: com memria, disco, processador,
rede e outros perifricos, todos entregues via abstrao de
virtualizao.
como se dentro da mquina fsica, se criasse mquinas me-
nores e independentes entre s. Cada mquina tem seu prprio
sistema operacional completo que, por sua vez, interage com
os hardwares virtuais que lhe foram entregues pelo modelo
de virtualizao a nvel de mquina.
Vale ressaltar: o sistema operacional instalado dentro da
mquina virtual far interao com os hardwares virtuais e
no com o hardware real.
Apndice 162

Com a evoluo desse modelo, os softwares que implementam


a soluo, puderam oferecer mais funcionalidades, tais como
melhor interface para gerncia de ambientes virtuais e alta
disponibilidade utilizando vrios hosts fsicos.
Com as novas funcionalidades de gerncia de ambientes de
mquinas virtuais possvel especificar quanto recurso fsico
cada ambiente virtual usa e, at mesmo, aumentar gradual-
mente em caso de necessidade pontual.
Atualmente, as mquinas virtuais so realidade para qualquer
organizao que necessite de ambiente de TI, pois facilita a
gerncia das mquinas fsicas e o compartilhamento entre os
diversos ambientes necessrios para a infraestrutura bsica.
Apndice 163

Continer
Esse modelo de virtualizao est no nvel de sistema opera-
cional, ou seja, ao contrrio da mquina virtual, um continer
no tem viso da mquina inteira, apenas processo em
execuo em um kernel compartilhado entre todos os outros
continers.
Utiliza o namespace para prover o devido isolamento de
memria RAM, processamento, disco e acesso rede. Mesmo
compartilhando o mesmo kernel, esse processo em execuo
tem a viso de estar usando um sistema operacional dedicado.
um modelo de virtualizao relativamente antigo. Em mea-
dos de 1982, o chroot j fazia algo que podemos considerar
virtualizao a nvel de sistema operacional e, em 2008, o
LXC j fazia algo relativamente parecido ao Docker, hoje.
Inclusive, no incio, o Docker usava o LXC, mas hoje tem
interface prpria para acessar o namespace, cgroup e afins.
Apndice 164

Como soluo inovadora o Docker traz diversos servios e


novas facilidades que deixam o modelo muito mais atrativo.
A configurao de ambiente LXC no era tarefa simples; era
necessrio algum conhecimento tcnico mdio para criar e
manter um ambiente com ele. Com o advento do Docker,
esse processo ficou bem mais simples. Basta instalar o binrio,
baixar as imagens e execut-las.
Outra novidade do Docker foi a criao do conceito de ima-
gens. Grosseiramente podemos descrever as imagens como
definies estticas daquilo que os continers devem ser na
inicializao. So como fotografias do ambiente. Uma vez
instanciadas e, colocadas em execuo, assumem a funo de
continers; saem da abstrao de definio e se transformam
em processos em execuo, dentro de um contexto isolado.
Enxergam um sistema operacional dedicado para s, mas na
verdade compartilham o mesmo kernel.
Junto facilidade de uso dos continers, o Docker agregou
o conceito de nuvem, que dispe de servio para carregar e
baixar imagens Docker. Trata-se de aplicao web que dis-
ponibiliza repositrio de ambientes prontos, onde viabilizou
um nvel absurdo de compartilhamento de ambientes.
Com o uso do servio de nuvem do Docker, podemos perceber
que a adoo do modelo de continers ultrapassa a questo
tcnica e adentra assuntos de processo, gerncia e atualizao
do ambiente; onde, agora possvel compartilhar facilmente
as mudanas e viabilizar uma gesto centralizada das defini-
es de ambiente.
Utilizando a nuvem Docker agora, possvel disponibilizar
ambientes de teste mais leves, permitindo que, em plena
reunio com o chefe, voc pode baixar a soluo para um
problema que ele descreve e mostrar antes que ele saia da
Apndice 165

sala. Permite tambm que voc consiga disponibilizar padro


de melhores prticas para determinado servio e compartilhar
com todos da sua empresa e alm, onde pode receber crticas
e executar modificaes com o passar do tempo.

Concluso
Com os dados apresentados, percebemos que o ponto de
conflito entre as solues baixo. Podem e, normalmente, so
adotadas em conjunto. Voc pode provisionar uma mquina
fsica com um servidor de mquinas virtuais, onde sero
criadas mquinas virtuais hospedes, que por sua vez tero
o docker instalado em cada mquina. Nesse docker sero
disponibilizados os ambientes com seus respectivos servios
segregados, cada um em um continer.
Percebam que teremos vrios nveis de isolamento. No pri-
meiro, a mquina fsica, que foi repartida em vrias m-
quinas virtuais, ou seja, j temos nossa camada de sistemas
operacionais interagindo com hardwares virtuais distintos,
como placas de rede virtuais, discos, processo e memria.
Nesse ambiente, teramos apenas o sistema operacional bsico
instalado e o Docker.
No segundo nvel de isolamento, temos o Docker baixando as
imagens prontas e provisionamento continers em execuo
que, por sua vez, criam novos ambientes isolados, a nvel de
processamento, memria, disco e rede. Nesse caso, podemos
ter na mesma mquina virtual um ambiente de aplicao
web e banco de dados. Mas em continers diferentes e, isso
no seria nenhum problema de boas prticas de gerncia de
servios, muito menos de segurana.
Apndice 166

Caso esses continers sejam replicados entre as mquinas vir-


tuais, seria possvel prover alta disponibilidade sem grandes
custos, ou seja, usando um balanceador externo e viabilizando
o 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 paradigma
de gerncia dos ativos e pacincia para lidar com os novos
problemas inerentes do modelo.

Comandos teis
Seguem alguns comandos teis e simples abaixo:

Remover todos os containers sem uso


docker container prune
Parar todos os containers
docker stop $(docker ps -q)
Remover todas as imagens locais
docker image prune
Apndice 167

Remove volumes rfos


docker volume prune
Mostra uso de recursos dos containers rodando
docker stats $(docker ps --format {{.Names}})

Posso rodar aplicaes GUI?


Com certeza, plenamente possvel rodar aplicaes GUI (ou
X11) em containers, o que significa que todas as vantagens de
utilizar o Docker se aplicam tambm a aplicaes grficas.
Alm disso possvel fazer a aplicao funcionar em multiplos
sistemas (Linux, Windows e macOS) apenas construindo ela
para Linux.

Como?
Antes de mais nada Em 99% dos casos preciso liberar ,o
acesso ao X: xhost local (essa liberao ficar vigente at
desligar/reinicar o host)
Comando mais simples o possvel, monta o socket X11 do host
no container e define o display (note que vamos evoluindo o
comando aos poucos, mas pode usar apenas as flags que achar
necessrio - as nicas obrigatrias so a montagem de volume
do /tmp/.X11-unix e a varivel de ambiente DISPLAY):

1 docker container run [--rm [-it]|-d] \


2 -v /tmp/.X11-unix:/tmp/.X11-unix \
3 -e DISPLAY \
4 imagem [comando]
Apndice 168

Em alguns casos a varivel DISPLAY tem de ser DISPLAY=unix$DISPLAY


(mas pra ser sincero at agora eu no sei bem o motivo,
somente que era o indicado pela pessoa que fez a imagem).
Para utilizar o suporte a acelerao 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:


Apndice 169

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]

Ateno: dependendo da distribuio, no h um /etc/local-


time, tem de averiguar como ela define o timezone e replicar
no container.
Mantendo as configuraes 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.


Bnus: Controle do video-game (na verdade qualquer dispo-
sitivo de entrada):
Apndice 170

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 definir
a varivel de ambiente no docker-compose.yml e ser possvel
iniciar multiplos aplicativos com apenas um comando.

No Windows e macOS

Mac OS X

Instalar o Docker for Mac

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]
Apndice 171

#### Windows
Instalar o xming
Instalar 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)

https://github.com/docker/docker/issues/8710#issuecomment-135109677