Buscar

Prévia do material em texto

Docker - Do básico à
Certificação Docker DCA
Certificação Docker DCA
Caio Delgado
Esse livro está à venda em http://leanpub.com/dockerdca
Essa versão foi publicada em 2021-09-19
Esse é um livro Leanpub. A Leanpub dá poderes aos autores e
editores a partir do processo de Publicação Lean. Publicação Lean
é a ação de publicar um ebook em desenvolvimento com
ferramentas leves e muitas iterações para conseguir feedbacks dos
leitores, pivotar até que você tenha o livro ideal e então conseguir
tração.
© 2021 Caio Delgado
http://leanpub.com/dockerdca
http://leanpub.com/
http://leanpub.com/manifesto
Tweet Sobre Esse Livro!
Por favor ajude Caio Delgado a divulgar esse livro no Twitter!
O tweet sugerido para esse livro é:
Eu acabei de comprar Docker - Do básico a Certificação Docker
DCA. Você também pode adquirir o livro de forma gratuita ou
pagar o quanto desejar pelo livro.
A hashtag sugerida para esse livro é #dockerdca.
Descubra o que as outras pessoas estão falando sobre esse livro
clicando nesse link para buscar a hashtag no Twitter:
#dockerdca
http://twitter.com
https://twitter.com/intent/tweet?text=Eu%20acabei%20de%20comprar%20%20Docker%20-%20Do%20b%C3%A1sico%20a%20Certifica%C3%A7%C3%A3o%20Docker%20DCA.%20Voc%C3%AA%20tamb%C3%A9m%20pode%20adquirir%20o%20livro%20de%20forma%20gratuita%20ou%20pagar%20o%20quanto%20desejar%20pelo%20livro.
https://twitter.com/intent/tweet?text=Eu%20acabei%20de%20comprar%20%20Docker%20-%20Do%20b%C3%A1sico%20a%20Certifica%C3%A7%C3%A3o%20Docker%20DCA.%20Voc%C3%AA%20tamb%C3%A9m%20pode%20adquirir%20o%20livro%20de%20forma%20gratuita%20ou%20pagar%20o%20quanto%20desejar%20pelo%20livro.
https://twitter.com/intent/tweet?text=Eu%20acabei%20de%20comprar%20%20Docker%20-%20Do%20b%C3%A1sico%20a%20Certifica%C3%A7%C3%A3o%20Docker%20DCA.%20Voc%C3%AA%20tamb%C3%A9m%20pode%20adquirir%20o%20livro%20de%20forma%20gratuita%20ou%20pagar%20o%20quanto%20desejar%20pelo%20livro.
https://twitter.com/search?q=%23dockerdca
https://twitter.com/search?q=%23dockerdca
Dedico este livro a todos que acreditaram em mim e me ajudaram a
desenvolver na minha carreira, principalmente minha esposa Érika
Correa que sempre esteve ao meu lado me apoiando e dando todo o
suporte e a meu amigo Diego Sanches que me apresentou o mundo
DevOps e fez acender a primeira fagulha de conhecimento desta
área. Sem vocês nada disso seria possível.
Conteúdo
Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Sobre o Autor . . . . . . . . . . . . . . . . . . . . . . . . . 1
Capítulo 01 - Fundamentos . . . . . . . . . . . . . . . . . . . 3
O que é o Docker . . . . . . . . . . . . . . . . . . . . . . . 3
Por que usar Docker . . . . . . . . . . . . . . . . . . . . . 4
O que é um container . . . . . . . . . . . . . . . . . . . . 5
Versões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Instalação . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Instalando o Vagrant e Virtualbox . . . . . . . . . . . 8
Preparando o Ambiente . . . . . . . . . . . . . . . . . 9
Namespaces e Cgroups . . . . . . . . . . . . . . . . . . . . 11
Namespaces . . . . . . . . . . . . . . . . . . . . . . . 12
cgroups . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Instalação do Docker . . . . . . . . . . . . . . . . . . . . . 13
Instalando Docker no Ubuntu . . . . . . . . . . . . . 13
Instalando Docker no CentOS . . . . . . . . . . . . . 15
Instalando Docker através do script de Conveniência. 16
Teste de Execução . . . . . . . . . . . . . . . . . . . . 17
Componentes . . . . . . . . . . . . . . . . . . . . . . . . . 17
Docker Client . . . . . . . . . . . . . . . . . . . . . . 18
Docker Daemon . . . . . . . . . . . . . . . . . . . . . 18
Docker Registry . . . . . . . . . . . . . . . . . . . . . 19
Comandos Essenciais . . . . . . . . . . . . . . . . . . . . 19
Executando comandos . . . . . . . . . . . . . . . . . 20
CONTEÚDO
Capítulo 02 - Imagens . . . . . . . . . . . . . . . . . . . . . . 25
Dockerhub . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Criando uma conta no Dockerhub . . . . . . . . . . . 26
Docker Image . . . . . . . . . . . . . . . . . . . . . . . . . 28
Gerenciar Imagens no Docker . . . . . . . . . . . . . . . . 30
Dockerfile . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Criando Dockerfiles . . . . . . . . . . . . . . . . . . . 34
Dockerfile Servidor WEB . . . . . . . . . . . . . . . . 35
Enviando a imagem para o Dockerhub . . . . . . . . . . 36
Melhores práticas com o Dockerfile . . . . . . . . . . . . 37
Entendendo o contexto de Build . . . . . . . . . . . . 38
Excluindo arquivos do build . . . . . . . . . . . . . . 41
Dicas . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Removendo todas as imagens . . . . . . . . . . . . . 54
Capítulo 03 - Storage Drivers . . . . . . . . . . . . . . . . . 55
Docker Volumes . . . . . . . . . . . . . . . . . . . . . . . 56
Gerenciar Volumes . . . . . . . . . . . . . . . . . . . . . . 58
Selinux Labels . . . . . . . . . . . . . . . . . . . . . . . . . 60
tmpfs mounts . . . . . . . . . . . . . . . . . . . . . . . . . 61
Backup & Restore . . . . . . . . . . . . . . . . . . . . . . . 63
Backup . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Restore . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Volume Plugins . . . . . . . . . . . . . . . . . . . . . 66
Capítulo 04 - Networking . . . . . . . . . . . . . . . . . . . . 70
Administrando Redes . . . . . . . . . . . . . . . . . . . . 70
Network Drivers . . . . . . . . . . . . . . . . . . . . . . . 71
Redes Básico . . . . . . . . . . . . . . . . . . . . . . . . . 72
Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Host . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
None . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Macvlan . . . . . . . . . . . . . . . . . . . . . . . . . . 77
CONTEÚDO
Overlay . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Conectando Containers . . . . . . . . . . . . . . . . . . . 79
DNS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Capítulo 05 - Docker Compose . . . . . . . . . . . . . . . . 84
O que é o Compose . . . . . . . . . . . . . . . . . . . . . . 84
Etapas de um Compose . . . . . . . . . . . . . . . . . . . 84
docker-compose.yml . . . . . . . . . . . . . . . . . . . . . 84
Instalando o Docker Compose . . . . . . . . . . . . . . . 86
Criando Composes . . . . . . . . . . . . . . . . . . . . . . 86
Compose Multi-containers . . . . . . . . . . . . . . . 89
Capítulo 06 - Docker Swarm . . . . . . . . . . . . . . . . . . 93
Conceitos . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Cluster . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Node . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Raft Consensus . . . . . . . . . . . . . . . . . . . . . . . . 94
Criando o Cluster . . . . . . . . . . . . . . . . . . . . . . . 97
Adicionando nós ao cluster. . . . . . . . . . . . . . . 98
Promovendo um node a Manager ou rebaixando a
worker . . . . . . . . . . . . . . . . . . . . . 100
Private Registry . . . . . . . . . . . . . . . . . . . . . . . . 101
Preparando nosso Registry . . . . . . . . . . . . . . . 102
Deploy do Registry . . . . . . . . . . . . . . . . . . . 103
Enviando Imagens . . . . . . . . . . . . . . . . . . . . 104
Listando Imagens . . . . . . . . . . . . . . . . . . . . 104
Adicionando as imagens que iremos utilizar nos
laboratórios . . . . . . . . . . . . . . . . . . 105
Services e Tasks . . . . . . . . . . . . . . . . . . . . . . . . 107
Tasks e Agendadores . . . . . . . . . . . . . . . . . . . . . 108
Serviços Replicados e Globais . . . . . . . . . . . . . . . . 109
Gerenciando Serviços . . . . . . . . . . . . . . . . . . . . 110
Escalando Serviços . . . . . . . . . . . . . . . . . . . . . . 113
Disponibilidade dos Nodes . . . . . . . . . . . . . . . . . 114
Secrets . . . . . . . . . . . . . . . . . .. . . . . . . . . . . 115
CONTEÚDO
Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Volumes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Gerenciando Limites do container . . . . . . . . . . . . . 128
Traefik com Stack (Extra) . . . . . . . . . . . . . . . . . . 131
Capítulo 07 - Monitoramento . . . . . . . . . . . . . . . . . 135
Stack de Monitoramento . . . . . . . . . . . . . . . . . . . 135
Prometheus . . . . . . . . . . . . . . . . . . . . . . . . 135
node-exporter . . . . . . . . . . . . . . . . . . . . . . 135
CAdvisor . . . . . . . . . . . . . . . . . . . . . . . . . 136
Grafana . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Subindo a Stack de monitoramento . . . . . . . . . . . . 136
Configurando a Stack de Monitoramento . . . . . . . . . 140
Prometheus . . . . . . . . . . . . . . . . . . . . . . . . 140
Grafana . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Importando Dashboards . . . . . . . . . . . . . . . . 148
Capítulo 08 - Ferramentas . . . . . . . . . . . . . . . . . . . 156
Play With Docker . . . . . . . . . . . . . . . . . . . . . . . 156
Swarmpit . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Instalação . . . . . . . . . . . . . . . . . . . . . . . . . 162
Dashboard . . . . . . . . . . . . . . . . . . . . . . . . 164
Registries . . . . . . . . . . . . . . . . . . . . . . . . . 164
Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Services . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Networks . . . . . . . . . . . . . . . . . . . . . . . . . 170
Nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Volumes . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Secrets . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Config . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Portainer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Instalação . . . . . . . . . . . . . . . . . . . . . . . . . 172
Dashboard . . . . . . . . . . . . . . . . . . . . . . . . 173
CONTEÚDO
App Templates . . . . . . . . . . . . . . . . . . . . . . 174
Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Services . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Containers . . . . . . . . . . . . . . . . . . . . . . . . 177
Images . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Networks . . . . . . . . . . . . . . . . . . . . . . . . . 178
Volumes . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Configs e Secrets . . . . . . . . . . . . . . . . . . . . . 180
Swarm . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Settings . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Harbor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Instalação . . . . . . . . . . . . . . . . . . . . . . . . . 182
Dashboard . . . . . . . . . . . . . . . . . . . . . . . . 184
Users . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Enviando imagens . . . . . . . . . . . . . . . . . . . . 187
Docker Machine . . . . . . . . . . . . . . . . . . . . . . . 190
Instalando o Docker Machine . . . . . . . . . . . . . 190
Provisionando docker-machines em uma máquina
virtual local . . . . . . . . . . . . . . . . . . 191
Interagindo com o Docker Machine . . . . . . . . . . 192
Provisionando Docker Machines em Cloud . . . . . 195
Capitulo 9 - Kubernetes . . . . . . . . . . . . . . . . . . . . . 198
O que é o Kubernetes . . . . . . . . . . . . . . . . . . . . 198
Pods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Minikube . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Recursos Necessários: . . . . . . . . . . . . . . . . . . 200
Instalação e Configuração . . . . . . . . . . . . . . . 201
Estrutura dos Comandos . . . . . . . . . . . . . . . . . . . 202
Descrevendo Aplicações . . . . . . . . . . . . . . . . . . . 205
Pod Multi-container . . . . . . . . . . . . . . . . . . . . . 207
ClusterIP e NodePort . . . . . . . . . . . . . . . . . . . . . 210
ClusterIP . . . . . . . . . . . . . . . . . . . . . . . . . 211
Node Port . . . . . . . . . . . . . . . . . . . . . . . . . 214
Deployments . . . . . . . . . . . . . . . . . . . . . . . . . 217
CONTEÚDO
configMaps e secrets . . . . . . . . . . . . . . . . . . . . . 220
Criando um configMap . . . . . . . . . . . . . . . . . 220
Configurando Secrets . . . . . . . . . . . . . . . . . . . . 224
Persistent Storage . . . . . . . . . . . . . . . . . . . . . . . 227
Modos de Acesso . . . . . . . . . . . . . . . . . . . . 229
Criando PVs . . . . . . . . . . . . . . . . . . . . . . . . . . 230
Atrelando Pod a Volumes. . . . . . . . . . . . . . . . . . . 234
Destruindo o Ambiente . . . . . . . . . . . . . . . . . . . 237
Introdução
Este livro/curso tem como objetivo ajudar a comunidade e difundir
o conhecimento de Containeres.
O curso por si só não tem fins lucrativos, podendo ser utilizado
de forma totalmente gratuita, peço apenas que ao utilizá-lo em
qualquer situação que seja feita a citação do autor do material.
SPOILER ALERT (Soon)
Caso você queira ajudar o autor a produzir mais conteúdos sinta-se
a vontade em adquirir o curso na plataforma da udemy.
Caso você não tenha condições de adquirir o curso,
entre em contato comigo pelo twitter e eu irei gerar um
cupom de 100% de desconto afinal a ideia não é lucrar e
sim ajudar a comunidade. O Link será atualizado assim
que começarmos as gravações!
Neste livro/curso iremos cobrir todos os fundamentos de Docker
bem como todo o conteúdo para a certificação Docker Certified
Associate (DCA).
Sobre o Autor
Caio Delgado é graduado em Engenharia da Computação e Pós
Graduado em Engenharia de Redes.
Trabalhou por 12 Anos com ambientes Microsoft e Redes e em 2018
migrou para o mundo Open Source.
Mantém um canal no youtube e um blog onde publica regularmente
conteúdo sobre OpenSource, DevOps e Site Reliability Enginee-
ring.
Introdução 2
Fã de Zeldinha desde criança.
Links: https://linktr.ee/caiodelgadonew
Capítulo 01 -
Fundamentos
O que é o Docker
Docker é uma plataforma Open Source escrita em Go (Linguagem
de programação em alta performance desenvolvida pela Google)
que ajuda a criação e a administração de ambientes isolados.
Com a utilização do Docker podemos gerenciar toda a infraes-
tutura de uma aplicação, bem como garantir que ambientes de
desenvolvimento, homologação e produção contenham os mesmos
componentes e versões de aplicações, a fim de minimizar impactos
no processo de desenvolvimento e entrega de software.
O Docker trabalha com uma virtualização a nível do sistema
operacional, onde o mesmo utiliza de recursos como o kernel do
sistema hospedeiro para executar seus containers. Diferente do
modelo tradicional de Máquinas Virtuais, o Docker não necessita
da instalação de um sistema operacional por completo, e sim apenas
dos arquivos necessários para a aplicação ser executada.
Capítulo 01 - Fundamentos 4
Weaveworks - VM x Containers
Por que usar Docker
Em 2013, Docker introduziu o que se tornou o padrão da indústria
para containers, trouxe uma maneira simples, rápida e eficiente de
executar aplicações sem a complexidade de uma máquina virtual.
Docker garante um ecossistema consistente, fazendo com que o
desenvolvedor possa trabalhar sem se preocupar, por exemplo, com
a abertura de tickets para uma equipe de infraestrutura provisionar
um ambiente por completo, atrasando o trabalho de entrega de
software.
Existem diversas engines e runtimes de containers e até é possível
utilizar containers sem Docker, mas atualmente o Docker é a
engine/runtime de container mais utilizada no mercado, o que
torna o conhecimento do mesmo um “Must have” e dificilmente
encontramos vagas na área de tecnologia que não pedem um
conhecimento, mesmo que básico, de containers ou Docker.
Capítulo 01 - Fundamentos 5
O que é um container
Um container consiste de um ambiente completo (umaaplicação
e todas suas dependências, bibliotecas, binários, arquivos de con-
figuração) em um único pacote. Ao containerizar uma plataforma
de aplicação e suas dependências as diferenças em distribuições de
sistemas operacionais e camadas inferiores da infraestrutura são
abstraídas.
Imagine que o container Docker é como se fosse um con-
tainer real em um navio (servidor), todos os containeres
estão lado a lado, porém seu conteúdo (ecossistema) não
tem interferência de outros containers.
Podemos dizer também que um container é a unidade mínima
computacional do Docker, ou seja, o menor recurso que o Docker
pode fornecer.
Capítulo 01 - Fundamentos 6
Container
Versões
ODocker possui basicamente duas versões, a versão da comunidade
(Community Edition) e a versão empresarial (Enterprise Edition).
A versão Community é de uso gratuito e também tem seu código
aberto.
Amaioria dos sistemas Docker em produção utiliza a versão Docker
Community Edition. O licenciamento anual da versão Enterprise
custa cerca de US$750 por nó, o que torna o processo inviável para
algumas empresas.
ATENÇÃO: Para fins da prova Docker Certified As-
sociate (Docker DCA) a versão Community deve ser
Capítulo 01 - Fundamentos 7
utilizada apenas em ambientes de desenvolvimento e
não deve ser utilizada em produção. Para produção a
única versão a ser utilizada é a Enterprise Edition.
A versão Enterprise conta com recursos como o UCP (Universal
Control Plane) e o DTR (Docker Trusted Registry), bem como
suporte da Docker Inc.
A recomendação mínima para a versão Enterprise do Docker EE é:
• 8GB de RAM para nós Managers
• 4GB de RAM para nós Workers
• 2vCPUs para nós Managers
• 10GB de espaço em disco livre para a partição /var em nós
Managers (Minimo de 6GB Recomendado)
• 500MB de espaço em disco livre para a partição /var em nós
workers
A recomendação para ambientes de produção do Docker EE é:
• 16GB de RAM para nós Managers
• 4vCPUs para nós Managers
• 25 a 100GB de espaço livre em disco.
Instalação
Iremos instalar o Docker em máquinas virtuais para que possamos
facilitar o estudo, para isto utilizaremos uma solução chamada
Vagrant somado ao Virtualbox, você pode utilizar a solução de vir-
tualização que preferir, porém eu indico que você siga exatamente
como listado no curso porque caso você precise de suporte eu possa
lhe ajudar.
Lembre-se de habilitar a virtualização Intel VT-x ou
AMD SVM na UEFI/BIOS.
Capítulo 01 - Fundamentos 8
Instalando o Vagrant e Virtualbox
Para instalar o Virtualbox siga os passos:
1. Acesse a página de Downloads do Virtualbox¹ e faça o down-
load da versão coorespondente ao seu sistema operacional.
2. Execute a instalação do pacote do Virtualbox.
2.1. Para Linux execute o programa de instalação de pacotes (sudo
dpkg -i <pacote>.deb para sistemas debian-like ou sudo rpm -i
<pacote>.rpm)
2.2. Para Windows, clique sob o instalador e avance até o final da
instalação.
2.3. Para MacOS, clique sob o instalador e avance até o final da
instalação.
Para Instalar o vagrant siga os passos:
1. Acesse a página de Downloads do Vagrant² e faça o download
da versão correspondente ao seu sistema operacional.
2. Execute a instalação do pacote do vagrant.
2.1. Para Linux execute o programa de instalação de pacotes (sudo
dpkg -i <pacote>.deb para sistemas debian-like ou sudo rpm -i
<pacote>.rpm)
2.2. Para Windows, clique sob o instalador e avance até o final da
instalação.
2.3. Para MacOS, clique sob o instalador e avance até o final da
instalação.
3. Após a instalação abra um terminal ou um prompt de comando
e execute o comando vagrant --version para verificar se o pacote
foi instalado com sucesso.
¹https://www.virtualbox.org/wiki/Downloads
²https://www.vagrantup.com/downloads.html
https://www.virtualbox.org/wiki/Downloads
https://www.vagrantup.com/downloads.html
https://www.virtualbox.org/wiki/Downloads
https://www.vagrantup.com/downloads.html
Capítulo 01 - Fundamentos 9
Preparando o Ambiente
Após instalar oVagrant e oVirtualbox, podemos criar um diretório
com um arquivo Vagrantfile.
O Vagrantfile é o arquivo do Vagrant responsável por
criar nossa infraestrutura.
Caso queira utilizar os arquivos mais atualizados, basta clonar o
repositório: https://github.com/caiodelgadonew/docker-dca
1 $ mkdir ~/docker
2 $ cd docker
3 $ vim Vagrantfile
Adicione o conteúdo ao arquivo Vagrantfile
1 # -*- mode: ruby -*-
2 # vi: set ft=ruby :
3
4 machines = {
5 "master" => {"memory" => "2048", "cpu" => "2", "ip" =\
6 > "100", "image" => "ubuntu/bionic64"},
7 "node01" => {"memory" => "1024", "cpu" => "2", "ip" =\
8 > "110", "image" => "ubuntu/bionic64"},
9 "node02" => {"memory" => "1024", "cpu" => "2", "ip" =\
10 > "120", "image" => "centos/7"},
11 "registry" => {"memory" => "2048", "cpu" => "2", "ip" =\
12 > "200", "image" => "ubuntu/bionic64"}
13 }
14
15 Vagrant.configure("2") do |config|
16
17 machines.each do |name, conf|
18 config.vm.define "#{name}" do |machine|
Capítulo 01 - Fundamentos 10
19 machine.vm.box = "#{conf["image"]}"
20 machine.vm.hostname = "#{name}.docker-dca.example"
21 machine.vm.network "private_network", ip: "10.20.20\
22 .#{conf["ip"]}"
23 machine.vm.provider "virtualbox" do |vb|
24 vb.name = "#{name}"
25 vb.memory = conf["memory"]
26 vb.cpus = conf["cpu"]
27 vb.customize ["modifyvm", :id, "--groups", "/Dock\
28 er-DCA"]
29 end
30 machine.vm.provision "shell", inline: "hostnamectl \
31 set-hostname #{name}.docker-dca.example"
32 config.vm.provision "shell", inline: <<-SHELL
33 HOSTS=$(head -n7 /etc/hosts)
34 echo -e "$HOSTS" > /etc/hosts
35 echo '192.168.200.10 master.docker.example' >> /\
36 etc/hosts
37 echo '192.168.200.21 node01.docker.example' >> /\
38 etc/hosts
39 echo '192.168.200.22 node02.docker.example' >> /\
40 etc/hosts
41 echo '192.168.200.50 registry.docker.example' >>\
42 /etc/hosts
43 SHELL
44 end
45 end
46 end
Para criar o ambiente do laboratório, execute o comando vagrant
up, e o vagrant irá criar todas as máquinas virtuais bem como
configurar os hostnames e endereços IP’s
Para se conectar asmáquinas utilize o comando vagrant ssh <host>
informando o nome do host a ser conectado, lembre-se de estar
dentro da pasta com o Vagrantfile.
Capítulo 01 - Fundamentos 11
Para desligar as máquinas execute o comando vagrant halt.
Para destruir o ambiente execute o comando vagrant destroy.
Execute o comando vagrant up para criar nossa infraestrutura.
1 $ cd ~/docker
2 $ vagrant up
Caso você queira saber mais sobre Vagrant eu tenho um
post no meu blog onde ensino como utilizar o Vagrant
para subir os laboratórios de estudo, para acessar basta
clicar em Vagrant-101³
Adicione também as seguintes entradas ao arquivo hosts da sua
máquina.
1 # Docker
2 192.168.200.10 master.docker.example
3 192.168.200.21 node01.docker.example
4 192.168.200.22 node02.docker.example
5 192.168.200.50 registry.docker.example
Emmáquinas Linux eMacOS o arquivo fica localizado
em /etc/hosts
Em máquinas Windows o arquivo fica localizado em
C:\Windows\System32\drivers\etc\hosts
Namespaces e Cgroups
O Docker utiliza de recursos do linux como por exemplo namespa-
ces, cgroups dentre vários outros que iremos falar futuramente para
isolar os containers que serão executados.
³https://caiodelgado.dev/vagrant-101
https://caiodelgado.dev/vagrant-101
https://caiodelgado.dev/vagrant-101
Capítulo 01 - Fundamentos 12
Namespaces
Namespaces
• PID: Process ID
• MNT: Mount Points
• IPC: Comunicação Inter Processos
• UTS: Unix Timesharing System (Kernel e Identificadores)
• NET: Networking
Os Namespaces fornecem isolamento para os containers, limitando
seu acesso aos recursos do sistema e a outros namespaces. Isto
significa, por exemplo, que um usuário root dentro de um container
é diferente de um usuário root da máquina hospedeira.
Com o isolamento, os sistemas em execução nos containers tem
suas próprias árvores de processo, sistemas de arquivos, conexões
de rede e muito mais.
cgroups
cgroups
• cpu: Divisão de CPU por containers.
Capítulo01 - Fundamentos 13
• cpuset: CPU Masks, para limitar threads
• memory: Memória
• device: Dispositivos
Os containers trabalham com cgroups (Control Groups) que fazem
isolamento dos recursos físicos da máquina. Em geral os cgroups
podem ser utilizados para controlar estes recursos tais como limites
e reserva de CPU, limites e reserva de memória, dispositivos, etc…
Instalação do Docker
Existem duas maneiras de instalar o Docker
• Script de Conveniência
• Maneira Tradicional
Iremos efetuar a instalação da maneira tradicional nas máquinas
master e node02 e com o script de conveniência nas máquinas
node01 e registry.
Instalando Docker no Ubuntu
Primeiramente vamos acessar a máquina master
1 $ cd ~/docker
2 $ vagrant ssh master
Uma vez conectado na máquina docker, execute os seguintes co-
mandos:
Capítulo 01 - Fundamentos 14
1 $ sudo apt update
2 $ sudo apt install \
3 apt-transport-https \
4 ca-certificates \
5 curl \
6 gnupg2 \
7 software-properties-common \
8 bash-completion -y
9 $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg\
10 | sudo apt-key add -
11 $ sudo add-apt-repository \
12 "deb [arch=amd64] https://download.docker.com/linux/ub\
13 untu \
14 $(lsb_release -cs) \
15 stable"
16 $ sudo apt update
17 $ sudo apt-get install docker-ce docker-ce-cli containerd\
18 .io
Após a conclusão da instalação, podemos configurar agora nosso
usuário para fazer parte do grupo docker, isso garantirá que possa-
mos executar os comandos do docker sem a necessidade de elevar
os privilégios.
1 $ sudo usermod -aG docker $USER
Vamos também instalar o recurso de Bash Completion através do
comando:
1 $ sudo curl https://raw.githubusercontent.com/docker/mach\
2 ine/v0.16.0/contrib/completion/bash/docker-machine.bash -\
3 o /etc/bash_completion.d/docker-machine
Saia do terminal e inicie uma nova sessão e o usuário já poderá
executar o comando como super user.
Capítulo 01 - Fundamentos 15
1 $ exit
2 $ vagrant ssh master
Instalando Docker no CentOS
Abra um novo terminal e acesse a máquina node02
1 $ cd ~/docker
2 $ vagrant ssh node02
Uma vez conectado na máquina docker, execute os seguintes co-
mandos:
1 $ sudo yum install -y yum-utils curl vim bash-completion
2 $ sudo yum-config-manager \
3 --add-repo \
4 https://download.docker.com/linux/centos/docker-ce.re\
5 po
6 $ sudo yum install docker-ce docker-ce-cli containerd.io
Nos sistemas RHEL like, precisamos habilitar e iniciar o serviço
após a instalação do mesmo
1 $ sudo systemctl enable docker
2 $ sudo systemctl start docker
Após a conclusão da instalação, podemos configurar agora nosso
usuário para fazer parte do grupo docker, isso garantirá que possa-
mos executar os comandos do docker sem a necessidade de elevar
os privilégios.
1 $ sudo usermod -aG docker $USER
Vamos também instalar o recurso de Bash Completion através do
comando:
Capítulo 01 - Fundamentos 16
1 $ sudo curl https://raw.githubusercontent.com/docker/mach\
2 ine/v0.16.0/contrib/completion/bash/docker-machine.bash -\
3 o /etc/bash_completion.d/docker-machine
Saia do terminal e inicie uma nova sessão e o usuário já poderá
executar o comando como super user.
1 $ exit
2 $ vagrant ssh node02
Instalando Docker através do script de
Conveniência.
Os passos a seguir devem ser executados nas máquinas node01
e registry, não esqueça de abrir um terminal novo para cada
máquina e executar o comando vagrant ssh <host>
A Docker disponibiliza um script de conveniência, que trata-se
de uma maneira simples e rápida para instalar o Docker para
ambientes de desenvolvimento, este script faz a validação da dis-
tribuição Linux bem como instala os pacotes necessários para o
funcionamento do Docker.
Para instalar o Docker através do script de conveniência basta
executar o comando:
1 $ sudo curl -fsSL https://get.docker.com | bash
Nos sistemas RHEL like, precisamos habilitar e iniciar o serviço
após a instalação do mesmo
1 $ sudo systemctl enable docker
2 $ sudo systemctl start docker
Capítulo 01 - Fundamentos 17
Após a conclusão da instalação, podemos configurar agora nosso
usuário para fazer parte do grupo docker, isso garantirá que possa-
mos executar os comandos do docker sem a necessidade de elevar
os privilégios.
1 $ sudo usermod -aG docker $USER
Vamos também instalar o recurso de Bash Completion através do
comando:
1 $ sudo curl https://raw.githubusercontent.com/docker/mach\
2 ine/v0.16.0/contrib/completion/bash/docker-machine.bash -\
3 o /etc/bash_completion.d/docker-machine
Teste de Execução
Para garantirmos que o docker foi instalado corretamente e está
funcional, podemos rodar nosso primeiro container e verificar o
retorno na tela.
1 $ docker container run --rm -it hello-world
Componentes
Agora que rodamos nosso primeiro container, precisamos entender
alguns componentes básicos da sua arquitetura e seu funciona-
mento.
Ao executar o container com a imagem hello-world o Docker fez
os seguintes passos:
1. O Docker Client se comunicou com o Docker Daemon.
Capítulo 01 - Fundamentos 18
2. O Docker Daemon fez o download da imagem hello-world no
Docker Hub.
3. O Docker Daemon criou um novo container, através da imagem
que rodou o executável que produz o texto que vimos no
terminal.
4. O Docker Daemon enviou o texto diretamente para o Docker
Client que enviou para nosso terminal.
Componentes
Docker Client
O Docker Client é o pacote docker-ce-cli ele fornece os comandos
do lado do cliente, como por exemplo o comando docker container
run, que irá interagir com o Docker Daemon
Docker Daemon
O Docker Daemon é o pacote docker-ce ele é o servidor propria-
mente dito, que receberá os comandos através do Docker Client e
fornecerá os recursos de virtualização a nível de sistema operacio-
nal.
Capítulo 01 - Fundamentos 19
Docker Registry
O Docker Registry é o local de armazenamento de imagens Docker,
normalmente o Docker hub, de onde o Docker Daemon receberá
as imagens a serem executadas no processo de criação de um
container.
Comandos Essenciais
Iremos agora aprender alguns comandos essenciais do Docker.
1 docker --help
O primeiro passo para entendermos os comandos do docker é visu-
alizar sua lista de comandos, iremos falar dos seguintes comandos
de gerenciamento:
• docker container
• docker image
• docker network
• docker system
• docker volume
Para cada comando de gerenciamento acima, temos diversos sub-
comandos a serem executados, muitos deles são parecidos com
comandos Linux como por exemplo ls, rm, dentre outros.
Antigamente o comando utilizado para listar containers era o
comando docker ps que ainda existe na documentação, porém é
indicado que seja utilizado o novo comando docker container ls.
PS é o abreviamento de Process Status enquanto LS é o
abreviamento de LIST
Existem diversos outros comandos que iremos ver ao longo do
curso.
Capítulo 01 - Fundamentos 20
Executando comandos
Antes de executar os comandos do docker, vamos conectar na
máquina node01.
1 vagrant ssh node01
Para visualizar informações do ambiente, podemos utilizar o co-
mando docker system info o qual exibirá informações do Docker
como versão, quantidade de containers em execução, storage dri-
vers, entre outros.
1 docker system info
2 docker info
Os comandos listados acima são equivalentes.
Para listar containers, imagens, redes e volumes no docker, utiliza-
mos o comando docker <comando> ls
1 docker container ls
2 docker image ls
3 docker network ls
4 docker volume ls
• docker container ls - lista os containers
• docker image ls - lista as imagens
• docker network ls - lista as redes
• docker volume ls - lista os volumes
Para pesquisar por uma imagem, utilizamos o comando docker
search
Capítulo 01 - Fundamentos 21
1 docker search debian
Para efetuar o download da imagem utilizamos o comando docker
image pull
1 docker image pull debian
Para executar um container, utilizamos o comando docker contai-
ner run
1 docker container run -dit --name debian1 --hostname c1 de\
2 bian
Descrição do comando:• docker container run (…) debian - Executa um container,
sendo o último parâmetro o nome da imagem a ser utilizada
• -dit - Executa um container como processo (d = Detached),
habilitando a interação com o container (i = Interactive) e
disponibiliza um pseudo-TTY(t = TTY)
• –name - Define o nome do container
• –hostname - Define o hostname do container
Agora que temos nosso primeiro container em execução, podemos
listar os containers (docker container ls) e conectar ao mesmo
através do comando docker container attach
1 docker container ls
2 docker container attach debian1
Note que ao se conectar ao container a PS1 será modificada para
root@c1:/# .
Execute alguns comandos no container:
Capítulo 01 - Fundamentos 22
1 ip -c a
2 hostname
3 cat /etc/hosts
4 exit
Liste novamente os containers
1 docker container ls -a
Note que agora o container está parado, isto aconteceu pois o
processo principal do container recebeu um return code diferente
de 0
Inicie novamente o container e conecte-se ao mesmo
1 docker container start debian1
2 docker container attach debian1
O comando docker container start inicia um container parado, o
comando docker container stop para um container que esteja em
execução
Utilize a sequencia de teclas <CTRL> + <P> + <Q> para se desconec-
tar do container sem que ele seja parado. Este comando é chamado
de Read escape sequence.
1 <CTRL> + <P> + <Q>
2 docker container ls
Note que agora o container ainda está em execução.
Para verificar os logs do container utilizamos o comando docker
container logs
Capítulo 01 - Fundamentos 23
1 docker container logs debian1
Pare e remova o container, após isto verifique os containers exis-
tentes
1 docker container stop debian1
2 docker container rm debian1
3 docker container ls -a
Podemos utilizar o parâmetro -f no comando docker container rm
para que o container seja removido mesmo que esteja sendo
executado
Execute um novo container
1 docker container run -dit --name c1 --hostname server deb\
2 ian
3 docker container ls
Crie um arquivo de teste na pasta atual para enviar ao container c1
1 echo "Arquivo de teste" > /tmp/arquivo
2 docker container cp /tmp/arquivo c1:/tmp
O comando docker container cp copia um arquivo da maquina
host para o container ou vice-versa.
Verifique se o arquivo existe dentro do container através do co-
mando exec
1 docker container exec c1 ls -l /tmp
2 docker container exec c1 cat /tmp/arquivo
O comando docker container exec executa um comando no
container e envia o retorno na saída padrão(STDOUT) da máquina,
caso o container não tenha sido iniciado com a opção -i o retorno
não será mostrado no STDOUT
Remova o container criado anteriormente
Capítulo 01 - Fundamentos 24
1 docker container rm -f c1
Capítulo 02 - Imagens
Dockerhub
Estas imagens ficam armazenadas em repositórios locais e/ou re-
motos, um exemplo de repositório remoto é o DockerHub que é
um repositório publico de imagens docker onde podemos escolher
e utilizar as imagens para subir nossos containers.
Dockerhub
Serviços Fornecidos pelo Dockerhub:
• Hospedagem de Imagens Docker;
• Autenticação de usuário
Capítulo 02 - Imagens 26
• Automatização do processo de construção de imagens através
de triggers (webhooks)
• Integração com o Github e Bitbucket
Criando uma conta no Dockerhub
Acesse o endereço https://hub.docker.com e clique em Sign Up para
criar uma conta, preencha com os seus dados e clique emContinue
Registro
Confirme o cadastro em seu e-mail e logue noDocker Hub através
do link Sign In
Capítulo 02 - Imagens 27
login
Logue no terminal com o usuário criado através do comando
docker login e digite sua senha
1 docker login -u <usuario_dockerhub>
Verifique se um arquivo de autorização foi criado
1 cat ~/.docker/config.json
Encerre o login na conta do Dockerhub no terminal
Capítulo 02 - Imagens 28
1 docker logout
Docker Image
Uma imagem Docker é um pacote executável que inclui tudo o
que é necessário para executar um aplicativo, incluindo o código,
bibliotecas, variáveis de ambientes e arquivos de configuração.
As imagens do Docker possuem camadas intermediárias que au-
mentam a capacidade de reutilização, diminuem o uso do disco
e aceleram a construção do docker, permitindo que cada etapa
seja armazenada em cache. Essas camadas intermediárias não são
mostradas por padrão.
Docker Image
A principal diferença entre um container e uma imagem é a camada
gravável superior. Todas as gravações no container que adicionam
novos dados ou modificam dados existentes são armazenados nessa
Capítulo 02 - Imagens 29
camada gravável. Quando o container é excluido, a camada gravá-
vel também é excluida. A imagem subjacente permanece inalterada.
Docker Images e Containers
Um ponto interessante é que em um cenário onde temos 1 container
com a imagem ubuntu:18.04 por exemplo, ocuparia 200MB ( estamos
considerando este tamanho para a imagem citada) somados a
quantidade de dados específicos deste container ( vamos considerar
50MB para este exemplo) totalizando 250MB. o mesmo caso com
10 containers serão utilizados os 200MB da imagem somados aos
50MB de cada container em execução, pois suas camadas readonly
é compartilhada, totalizando assim 750MB no total.
O mesmo cenário em máquinas virtuais seria exponen-
cialmente maior, uma vez que precisamos instalar todo
o sistema operacional e parametrizar cada máquina
individualmente.
Capítulo 02 - Imagens 30
Gerenciar Imagens no Docker
Liste as imagens e verifique o histórico de comandos utilizados para
sua construção
1 docker image ls
2 docker image history debian
O comando docker image history mostra as camadas que
compoem uma imagem
Para inspecionar uma imagem utilizamos o comando docker image
inspect
1 docker image inspect debian
O comando docker image inspect exibe informações detalhadas
de uma imagem
Vamos criar uma nova imagem a partir de um container existente,
para vamos criar um container e instalar alguns pacotes
1 docker container run -dit --name servidor-debian debian
2 docker container exec servidor-debian apt-get update
3 docker container exec servidor-debian apt-get install ngi\
4 nx -y
Para criar uma nova imagem a partir das alterações feitas em um
container podemos utilizar o parametro commit
1 docker container commit servidor-debian webserver-nginx
2 docker image ls
Capítulo 02 - Imagens 31
O comando docker container commit <container> <imagem>
cria uma imagem a partir de alterações realizadas em um container,
este procedimento não é o recomendado para este fim, mais a
frente veremos outras soluções
Para salvar a imagem podemos utilizar o parâmetro save
1 docker image save webserver-nginx -o imagem-webserver-ngi\
2 nx.tar
3 du -sh imagem-webserver-nginx.tar
Remova o container e a imagem servidor web
1 docker container rm -f servidor-debian
2 docker image rm webserver-nginx
3 docker image ls
Para carregar uma imagem salva a partir de um arquivo, podemos
utilizar o parâmetro load
1 docker image load -i imagem-webserver-nginx.tar
2 docker image ls
Para testar o funcionamento da imagem, podemos criar um contai-
ner utilizando a mesma
1 docker container run -dit --name webserver webserver-nginx
2 docker container ls
Remova todos os containers
1 docker container rm -f $(docker container ls -aq)
2 docker container ls
No comando acima, estamos passando através de um subshell o
comando docker container ls -aq que lista todos os containers por
id, sendo assim, será feita a remoção de todos os containers
Capítulo 02 - Imagens 32
Dockerfile
O Dockerfile é um arquivo de instruções de como deve ser gerada
a imagem Docker, através deste arquivo podemos criar novas
imagens para serem utilizadas.
Dockerfile
ODocker pode criar imagens automaticamente, lendo as instruções
de umDockerfile, que é um documento de texto que contém as ins-
truções para a criação de uma imagem docker através docomando
docker build.
Sintaxe
Capítulo 02 - Imagens 33
Parâmetro Valor
FROM Distribuição:Versão
COPY Arquivo_LocalCaminho_Absoluto_no_Container
RUN Comando
EXPOSE Porta do serviço
CMD Comando executado ao iniciar o
Container
O arquivo de Dockerfile não é case-sensitive, no entanto por
convenção utilizamos os parâmetros em maiúsculo para que sua
leitura seja mais agradável e de fácil compreensão. O nome do
arquivo deve se chamar Dockerfile apenas com a letra inicial D
em maiúsculo.
O Docker executará as instruções do Dockerfile em ordem (Top-
down) e deverá sempre iniciar com a instrução FROM, as linhas
que começam com # são tratadas como comentário a menos que
a linha seja uma diretiva de analisador válida, o caractere # em
qualquer outro lugar em uma linha é tratado como um argumento.
Definições
• FROM - Inicializa um novo estágio de compilação e define a
imagem de base para instruções subsequentes;
• COPY - Copia arquivos ou diretórios de origem local
adicionando-os a imagem do container;
• ADD - Similar ao parâmetro COPY porém possibilita que a
origem seja uma URL bem como a alteração de permissiona-
mento ao adicionar os arquivos a imagem do container;
• RUN - Executa os comandos em uma nova camada na parte
superior a imagem atual, é uma boa prática combinar diversos
comandos em um unico RUN utilizando de ; e && para a
combinação, assim criando apenas uma camada;
• EXPOSE - Informa ao docker a porta na qual o container
estará escutando enquanto estiver sendo executado, é possível
especificar portas TCP e UDP, caso não seja declarado o tipo
de porta, o padrão (TCP) é assumido.
Capítulo 02 - Imagens 34
• CMD - Só pode existir uma unica instrução deste tipo em
um arquivo, o propósito desta instrução é prover os padrões
para a execução do container, podendo ser um executável ou
até mesmo opções para o executável definido na instrução
ENTRYPOINT
• ENTRYPOINT - Possibilita configurar o container para ro-
dar como um executável, o comando docker run <image>
inicializará o container em seu entrypoint somado ao CMD
se existente.
Criando Dockerfiles
Vamos criar um diretório para armazenar os dockerfiles e criar
nosso primeiro Dockerfile
1 mkdir -p ~/dockerfiles/echo-container
2 cd ~/dockerfiles/echo-container
3 vim Dockerfile
1 FROM alpine
2 ENTRYPOINT ["echo"]
3 CMD ["--help"]
Para criar a imagem a partir do Dockerfile, utilizamos o comando
docker image build
1 docker image build -t echo-container .
2 docker image ls
A opção -t significa TAG, após o nome da imagem:tag informamos
qual o diretório em que o Dockerfile se encontra, utilizamos o ponto
( . ) para dizer que o Dockerfile está no diretório atual (PWD)
Execute o container com a imagem criada
Capítulo 02 - Imagens 35
1 docker container run --rm -it echo-container
A opção –rm informa que o container será apagado após cumprir
seu papel
Execute o container com a imagem criada alterando seu CMD
1 docker container run --rm -it echo-container Se inscreva \
2 no canal https://youtube.com/caiodelgadonew
Ao passar um parâmetro após o nome da imagem estamos
alterando o CMD do container, anteriormente echo –help para
echo Container DevOps
Dockerfile Servidor WEB
Vamos criar um diretório para armazenar o dockerfile para nosso
servidor WEB e criar o Dockerfile
1 mkdir ~/dockerfiles/webserver
2 cd ~/dockerfiles/webserver
3 vim Dockerfile
1 FROM debian
2 RUN apt-get update; \
3 apt-get install wget git apache2 -yq
4 EXPOSE 80
5 CMD ["apachectl", "-D", "FOREGROUND"]
Crie a imagem
Capítulo 02 - Imagens 36
1 docker image build -t webserver .
2 docker image ls
Enviando a imagem para o
Dockerhub
Para enviar uma imagem para o dockerhub é necessário que sejam
feitos 3 passos:
1. docker login
2. docker image tag
3. docker push
Vamos efetuar o login com nossa conta no dockerhub
1 docker login -u <usuario_dockerhub>
Agora precisamos criar a tag da imagem, que deve seguir o padrão
usuario/imagem:versao
1 docker image tag echo-container <usuario_dockerhub>/echo-\
2 container:latest
3 docker image tag webserver <usuario_dockerhub>/webserver
Caso não seja informada uma versão, o docker entende que a versão
trata-se da latest
Agora podemos enviar as imagens para o dockerhub
1 docker image push <usuario_dockerhub>/echo-container
2 docker image push <usuario_dockerhub>/webserver
Ao finalizar, lembre-se de efetuar o logout em sua conta do doc-
kerhub
Capítulo 02 - Imagens 37
1 docker logout
As imagens enviadas podem ser visualizadas na sua página do
dockerhub e todos os usuários podem efetuar o download damesma
com o comando docker image pull usuario/imagem:versao desde
que o repositório seja público
Repositório
Melhores práticas com o Dockerfile
Quando criamos uma imagem, através do comando docker image
build , a imagem definida pelo Dockerfile deve gerar containers
que são tão efêmeros quanto possível, isso quer dizer que o con-
tainer deve poder ser parado e/ou destruido a qualquer momento,
e reconstruido ou substituido com o mínimo de configuração ou
atualização.
Uma boa metodologia para conseguir chegar neste ponto é a do
Twelve-factor App, ou Aplicação de Doze-fatores, e em sua seção
Capítulo 02 - Imagens 38
de processos⁴ podemos verificar algumas das motivações para subir
containers maneira stateless (não armazenam estado).
Entendendo o contexto de Build
Quando executamos o comando docker image build , o diretório
no qual apontamos (muitas das vezes como . para referir o diretório
atual) é chamado de build context. Por padrão oDocker espera que
o Dockerfile esteja localizado nesta pasta, mas também podemos
especificar uma nova localização através da flag -f. Independente-
mente de onde o Dockerfile esteja, todo o conteúdo dos diretórios
recursivamente e arquivos é enviado para o Docker daemon como
build context.
Por isto não devemos, por exemplo, criar um
Dockerfile diretamente em nossa home ∼/Dockerfile
, uma vez que todo o conteúdo, inclusive o cache de
navegadores web e todas aplicações ∼/.cache será
enviado para o Docker daemon, muitas das vezes
falhando a build ou até mesmo fazendo com que ela
demore muito tempo.
Primeiramente vamos criar um diretório para guardar nosso doc-
kerfile e criar um arquivo com um conteúdo estático
1 mkdir -p ~/dockerfiles/exemplo1
2 cd ~/dockerfiles/exemplo1
3 echo "Dockerfile Melhores Práticas" > conteudo.txt
Agora podemos criar nosso Dockerfile:
⁴https://12factor.net/pt_br/processes
https://12factor.net/pt_br/processes
https://12factor.net/pt_br/processes
Capítulo 02 - Imagens 39
1 vim Dockerfile
1 FROM busybox
2 COPY conteudo.txt /
3 RUN cat /conteudo.txt
Agora vamos criar a imagem.
1 docker image build -t exemplo:v1 .
Agora vamos criar novos diretórios e mover o arquivo conteudo.txt
para um diretório diferente do dockerfile para construir uma se-
gunda imagem.
1 mkdir -p image context
2 mv Dockerfile image
3 mv conteudo.txt context
4 docker image build --no-cache -t exemplo:v2 -f image/Dock\
5 erfile context
As duas imagens tem o mesmo tamanho e o mesmo conteúdo,
porém note que as imagens tem o ID diferente porque criamos
a imagem sem utilizar o cache --no-cache, ou seja, criamos uma
imagem totalmente nova.
Capítulo 02 - Imagens 40
1 $ docker image ls
2
3 REPOSITORY TAG IMAGE ID CREATED \
4 SIZE
5 exemplo v2 589078e3e007 2 seconds \
6 ago 1.24MB
7 exemplo v1 de0bdd45cb9a 3 minutes \
8 ago 1.24MB
Caso sejam incluidos arquivos que não são necesssários para a
construção da imagem o build context se tornará maior e conse-
quentemente uma imagem maior. Isso pode aumentar o tempo de
construção, envio e download da imagem e do container runtime.
Para ver o tamanho do build context basta verificar a mensagem
exibida quando executar o build do seu Dockerfile.
Vamos copiar todo o conteúdo do diretório /var/log para o context
e construir a imagem.
1 sudo cp -r /var/log/ ~/dockerfiles/exemplo1/context/
2 sudo chown -R vagrant:vagrant ~/dockerfiles/exemplo1/cont\
3 ext/log
4 docker image build --no-cache -t exemplo:v3 -f image/Dock\
5 erfile context
Veja que o context que anteriormente era de apenas 2.6KB desta vez
foi de 26,62MB, oque resulta em um tempo de buildmaior porém sua
imagem continua do mesmo tamanho das outras já que o arquivo
foi enviado para o context e não foi utilizado.
1 Sending build context to Docker daemon 2.607kB
2 Sending build context to Docker daemon 26.62MB
Tratando de poucos MB o tempo de construção pode não ser muito
expressivo, porém imagine em uma grande aplicação com diversos
Capítulo 02 - Imagens 41
arquivos. Utilizando o comando time fiz a medição no caso de
2.6KB que gerou a build em 0m0.910s contra 0m1.368s do arquivo
de 26,62MB. esse tempo pode ser superior caso a imagem execute
diversos comandos em diversas camadas.
Excluindo arquivos do build
Para excluir arquivos que não são relevantes a build, podemos
criar um arquivo .dockerignore contendo os padrões de exclusão
similares aos do .gitignore possibilitando que ignoremos arquivos
no build sem ter que modificar nosso repositório.
Para a referência do Docker Ignore veja a Documenta-
ção Oficial⁵
Vamos criar agora um arquivo .dockerignore para que o diretório
log não seja enviado para a build.
1 vim context/.dockerignore
1 # Comentario: Ignorando arquivos do diretorio log
2 log
1 docker image build --no-cache -t exemplo:v4 -f image/Dock\
2 erfile context
Veja que o diretório log foi ignorado, uma vez que o build context
ficou em 2.6kB (agora um pouco maior que a primeira por possuir
o arquivo .dockerignore) ao invés dos 26MB anteriores.
⁵https://docs.docker.com/engine/reference/builder/#dockerignore-file
https://docs.docker.com/engine/reference/builder/#dockerignore-file
https://docs.docker.com/engine/reference/builder/#dockerignore-file
https://docs.docker.com/engine/reference/builder/#dockerignore-file
Capítulo 02 - Imagens 42
Dicas
Vamos criar um diretório para o exemplo a seguir para guardar
nosso Dockerfile e fazer o download de uma aplicação exemplo em
java que conta o numero de caracteres de um texto.
1 mkdir -p ~/dockerfiles/dicas
2 cd ~/dockerfiles/dicas
3 git clone https://github.com/caiodelgadonew/java-wc-app.g\
4 it app
Dica #1: A ordem importa para o cache
A ordem dos passos de build é importante, se o cache de um pri-
meiro passo é invalidado pela modificação de arquivos ou linhas do
Dockerfile, os arquivos subsequentes do build quebrarão. Sempre
faça a ordenação dos passos do que sofrerá menos mudanças para
o que sofrerá mais mudança.
melhores-práticas-1
1 vim Dockerfile
Capítulo 02 - Imagens 43
1 FROM debian:9
2 RUN apt-get update
3 RUN apt-get install -y openjdk-8-jdk wget ssh vim
4 COPY app /app
5 ENTRYPOINT ["java", "-jar", "/app/target/app.jar"]
1 docker image build -t dicas:v1 .
Dica #2: COPY mais específico para limitar a quebra
de cache
Só copie o necessário. Se possível evite o COPY. Quando copiamos
arquivos para nossa imagem, tenha certeza que você está sendo bem
específico sob o que quer copiar, qualquer mudança no arquivo
copiado quebrará o cache. Copiaremos então apenas a aplicação
para a imagem, desta maneira as mudanças nos arquivos não
afetarão o cache.
melhores-práticas-2
1 vim Dockerfile
Capítulo 02 - Imagens 44
1 FROM debian:9
2 RUN apt-get update
3 RUN apt-get install -y openjdk-8-jdk wget ssh vim
4 COPY app/target/app.jar /app/app.jar
5 COPY app/samples /samples
6 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v2 .
Dica #3: Identifique as instruções que podem ser
agrupadas
Cada instrução RUN cria uma unidade de cache e uma nova camada
de imagem, agrupar todos os comandos RUN em uma única instrução
pode melhorar o desempenho e diminuir a quantidade de camadas
uma vez que eles se tornarão uma unidade única cacheavel.
melhores-práticas-3
1 vim Dockerfile
Capítulo 02 - Imagens 45
1 FROM debian:9
2 RUN apt-get update \
3 && apt-get install -y \
4 openjdk-8-jdk wget \
5 ssh vim
6 COPY app/target/app.jar /app/app.jar
7 COPY app/samples /samples
8 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v3 .
Dica #4: Remova as dependências desnecessárias
Remover as dependencias desnecessárias e não instalar pacotes de
debug é uma boa prática, como por exemplo trocar o jdk (Java
Development Kit) pelo jre (Java Runtime Environment) que é um
pacote relativamente menor e contém apenas o necessário para
execução. Você pode instalar as ferramentas de debug posterior-
mente caso necessite. O instalador de pacotes apt possui uma flag
--no-install-recommends que garante que dependencias que não
são necessárias não sejam instaladas. Caso precise, adicione elas
explicitamente.
melhores-práticas-4
1 vim Dockerfile
Capítulo 02 - Imagens 46
1 FROM debian:9
2 RUN apt-get update \
3 && apt-get install -y --no-install-recommends \
4 openjdk-8-jre
5 COPY app/target/app.jar /app/app.jar
6 COPY app/samples /samples
7 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v4 .
Com a Dica #4 podemos notar uma diminuição consideravel no
tamanho de nossa imagem.
melhores-práticas-dica4
Dica #5: Remover o cache do gerenciador de pacotes
O gerenciador de pacotes mantem seu próprio cache, o apt por
exemplo guarda seu cache no diretório /var/lib/apt/lists e
/var/cache/apt/. Uma das maneiras de lidar com este problema
é remover o cache na mesma instrução que o pacote foi instalado.
Remover este cache em outra instrução não irá diminuir o tamanho
da imagem.
Capítulo 02 - Imagens 47
melhores-práticas-5
1 vim Dockerfile
1 FROM debian:9
2 RUN apt-get update \
3 && apt-get install -y --no-install-recommends \
4 openjdk-8-jre \
5 && rm -rf /var/lib/apt/lists \
6 && rm -rf /var/cache/apt
7 COPY app/target/app.jar /app/app.jar
8 COPY app/samples /samples
9 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v5 .
Agora com a Dica #5 nossa imagem ficou relativamente menor.
melhores-práticas-dica5
Capítulo 02 - Imagens 48
Dica #6: Utilize imagens oficiais quando possível
Imagens oficiais podem ajudar muito e reduzir bastante o tempo
preparando a imagem, isto porque os passos de instalação já vem
prontos e normalmente com as melhores praticas aplicadas, isto
também fará você ganhar tempo caso tenha multiplos projetos, eles
compartilham as mesmas camadas e utilizam a mesma imagem
base.
melhores-práticas-6
1 vim Dockerfile
1 FROM openjdk
2 COPY app/target/app.jar /app/app.jar
3 COPY app/samples /samples
4 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v6 .
Dica #7: Utilize Tags mais específicas
Nunca utilize a tag latest. Ela pode receber alguma atualização
e em um momento de update sua aplicação pode quebrar, depen-
dendo de quanto tempo passou do seu último build. Ao invés disso,
utilize tags mais específicas.
Capítulo 02 - Imagens 49
melhores-práticas-7
1 vim Dockerfile
1 FROM openjdk:8
2 COPY app/target/app.jar /app/app.jar
3 COPY app/samples /samples
4 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v7 .
Dica #8: Procure por flavors mínimos
Existem diversos flavors linux que fazem com que nossa imagem
se torne cada vez menor, um bom exemplo são as imagens slim
e alpine as quais são as menores encontradas. A imagem slim é
baseada no Debian, enquanto a alpine é baseada em uma distribui-
ção linux muito menor chamada Alpine. A diferença básica entre
elas é que o debian utiliza a biblioteca GNU libc enquanto o alpine
utiliza musl lbc, que apesar de muito menor, pode ter problemas
de compatibilidade.
Capítulo 02 - Imagens 50
1 docker image pull openjdk:8
2 docker image pull openjdk:8-jre
3 docker image pull openjdk:8-jre-slim
4 docker image pull openjdk:8-jre-alpine
5 docker image ls | egrep "REPOSITORY|openjdk"
1 REPOSITORY TAG SIZE
2 openjdk 8 510MB
3 openjdk 8-jre 265MB
4 openjdk 8-jre-slim 184MB
5 openjdk 8-jre-alpine 84.9MB
1 vim Dockerfile
1 FROM openjdk:8-jre-alpine
2 COPY app/target/app.jar /app/app.jar
3 COPY app/samples /samples
4 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1 docker image build -t dicas:v8 .
Agora temos uma diminuição enorme em nossa imagempois
estamos utilizando uma imagem base bem menor.
melhores-práticas-dica8
Capítulo 02 - Imagens 51
Dica #9: Multi-stage build
Multi-stage build é um recurso muito poderoso que apareceu a
partir do docker 17.05. Multi-stage builds são uteis para quem quer
otimizar Dockerfiles enquanto mantém eles fáceis de ler e manter.
Antes do Multi-stage build o maior desafio das imagens é de fato
manter as imagens pequenas, vimos nos exemplos anteriores que
conseguimos, ao utilizar algumas das melhores práticas, diminuir
bastante o tamanho da imagem. Utilizando imagens slim ou alpine
resolvem boa parte dos nossos problemas mas quando precisamos
resolver algo mais complexo podemos utilizar elas somadas ao
multi-stage build.
O multi-stage build faz com que possamos utilizar diversas
instruções FROM em um Dockerfile, e cada instrução pode utilizar
uma imagem diferente, fazemos isto por exemplo para subir uma
imagem, dentro desta imagem instalar os pacotes e coletar apenas
os arquivos necessários diretamente para a imagem subsequente.
Com isso temos uma imagem muito mais enxuta e otimizada.
Por exemplo vamos criar esta imagem emGO pelo processo normal:
1 git clone https://github.com/alexellis/href-counter.git ~\
2 /dockerfiles/multistage
3 cd ~/dockerfiles/multistage
4 rm Docker*
5 vim Dockerfile
Capítulo 02 - Imagens 52
1 FROM golang:1.7.3
2 WORKDIR go/src/github.com/alexellis/href-counter/
3 RUN go get -d -v golang.org/x/net/html
4 COPY app.go .
5 RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuf\
6 fix cgo -o app .
7 CMD ["./app"]
1 docker image build -t multistage:v1 .
Esta imagem ficou com o tamanho de 700MB, po-
rém o que precisamos nela é apenas o diretório
/go/src/github.com/alexellis/href-counter/app, podemos
então utilizar o multistage build para recolher estes arquivos,
chamando a primeira imagem de builder através do parâmetro AS
<nome> e depois invocar a imagem em um segundo estágio através
do parâmetro --from=<nome>.
1 vim Dockerfile
1 FROM golang:1.7.3 AS builder
2 WORKDIR /go/src/github.com/alexellis/href-counter/
3 RUN go get -d -v golang.org/x/net/html
4 COPY app.go .
5 RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuf\
6 fix cgo -o app .
7
8 FROM alpine:latest
9 RUN apk --no-cache add ca-certificates
10 WORKDIR /root/
11 COPY --from=builder /go/src/github.com/alexellis/href\
12 -counter/app .
13 CMD ["./app"]
Capítulo 02 - Imagens 53
melhores-práticas-9
1 docker image build -t multistage:v2 .
Agora tivemos uma “pequena” redução de 700MB para 12MB
1 docker image ls | egrep "REPOSITORY|multistage"
1 REPOSITORY TAG IMAGE ID CREATED \
2 SIZE
3 multistage v1 dae3f0761024 28 minute\
4 s ago 700MB
5 multistage v2 a1108a2b5102 33 minute\
6 s ago 11.7MB
Caso deseje testar a imagem basta executar o comando
1 docker container run --rm -it -e url=https://youtube.com/\
2 caiodelgadonew multistage:v1
3 docker container run --rm -it -e url=https://youtube.com/\
4 caiodelgadonew multistage:v2
Outra coisa interessante é que ao invés de utilizar uma imagem
completa podemos puxar um arquivo de uma imagem já criada
anteriormente através da flag --from=<image>:<tag>, vamos fazer
a cópia de um arquivo da imagem da dica 7 para a imagem do
multistage, para isto criaremos um diretório chamado multistage2.
Capítulo 02 - Imagens 54
1 mkdir -p ~/dockerfiles/multistage2
2 cd ~/dockerfiles/multistage2
3 vim Dockerfile
1 FROM alpine:latest
2 WORKDIR /root/
3 COPY --from=dicas:v7 /samples/1.txt .
4 CMD ["cat", "1.txt"]
1 docker image build -t multistage:v3 .
Podemos agora executar nosso container para verificar se o arquivo
1.txt é de fato o arquivo extraido da imagem dica:v7
1 docker container run --rm -it multistage:v3
É sempre bom tentar diminuir as imagens de docker e seguir as
melhores práticas, isso faz com que nosso tempo de deploy ou
scale da aplicação seja menor, bem como a necessidade de um
armazenamento maior e diversos outros fatores.
Removendo todas as imagens
1 docker image prune -a
Capítulo 03 - Storage
Drivers
Storage Drivers possibilitam a criação de dados em uma camada
gravável do container. Os arquivos não serão persistidos após o
container ser deletado, ambas velocidades de leitura e escrita tem
performance mais lentas que um sistema de arquivos.
Storage Drivers
• Device Mapper: Framework de gerenciamento de volumes
linux
• btrfs: CoW (copy-on-write) filesystem, pode ser utilizado
para combinar diversos blocos físicos em um único sistema
btrfs
• aufs: Union Filesystem. Driver antigo, não deve ser utilizado
em kernel > 4.0 , overlay2 é superior
• OverlayFS: Union Filesystem morderno, também conhecido
como overlay2, é o recomendado pelo docker.
• ZFS: Next Generation filesystem, suporta gerenciamento de
volume, snapshot, checksum, compressão, replicação, etc…
• VFS: cada camada é diretamente um diretório no disco, sem
suporte ao CoW (copy-on-write)
CoW ou copy-on-write é uma tecnica de gestão de
recursos criada para duplicar ou copiar em recursos
Capítulo 03 - Storage Drivers 56
modificáveis. Se um recurso é duplicado mas não mo-
dificado, não é preciso criar um novo recurso, é feito o
compartilhamento do recurso atual.
Para visualizar o storage driver em uso basta executar o comando
1 docker system info | grep Storage
A alteração do storage driver padrão deve ser feita através do
arquivo de parametrização daemon.json no qual falaremos mais
adiante
1 {
2 "storage-driver": "overlay2"
3 }
Docker Volumes
Volume é um diretório especialmente designado, seja em um ou
mais containers que compartilham o sistema de arquivos UnionFS
Os volumes são projetados para manter os dados, independente-
mente do ciclo de vida do container. O Docker nunca exclui um
volume automaticamente quando você remove um container.
Existem 3 tipos de Volumes:
• host - Reside no sistema de arquivos do host do docker e pode
ser acessado dentro de um container;
• nomeado - Volume gerenciado e criado pelo Docker, na
criação do volume é dado um nome para o mesmo.
• anônimo - Volume gerenciado e criado pelo Docker, na
criação do volume não é informado o nome para o mesmo
e o Docker se encarrega de nomeá-lo com um hash de 64
caracteres.
Capítulo 03 - Storage Drivers 57
Existem alguns tipos de montagem para os volumes. O volume
do tipo host tem sua montagem realizada como um bind mount
e existe ainda um volume do tipo tmpfs mount o qual reside na
memória do sistema (volátil)
Mounts
Existem algumas vantagens ao se utilizar volumes do Docker ao
invés de bind mounts
• Volumes são mais fáceis de efetuar o backup ou migração que
bind mounts;
• É possível efetuar a gerência de volumes utilizando o Docker
CLI ou o Docker API;
• Volumes podem ser compartilhados de maneira mais segura
entre múltiplos containers;
• Drivers de Volumes podem habilitar o armazenamento em
hosts remotos ou provedores de cloud, criptografar o con-
teúdo ou adicionar novas funcionalidades;
• Novos volumes podem ter seu conteúdo pré-populados por
um container.
Capítulo 03 - Storage Drivers 58
Gerenciar Volumes
Para utilizar volumes no docker utilizamos a opção -v ou –volume
para indicar qual volume deve ser montado no container.
Também podemos montar um volume utilizando a opção --mount
que é mais explicita e verbosa.
A maior diferença é que a sintaxe do -v combina todas as opções
no mesmo campo, enquanto a --mount separa elas. Contrário a bind
mounts, todas as opções para volumes são disponíveis para ambas
flags -v e --mount.
Quando usamos volumes com serviços, somente a opção --mount é
suportada.
Primeiramente vamos montar um volume do tipo host através de
um bind mount
1 docker container run -dit --name servidor -v /srv:/srv de\
2 bian
3 docker container exec servidor df -Th
O parâmetro -v seguido de um diretório em caminho absoluto
ou relativo separado por : a um caminho absoluto faz com que
o diretório /srv da máquina hospedeira seja montado dentro do
container gerado.
Vamos efetuar a cópia de alguns arquivos para o volume, verifi-
cando o conteúdoda pasta antes e após a execução
1 docker container exec servidor ls -lR /srv
2 sudo cp -r ~/dockerfiles /srv
3 docker container exec servidor ls -lR /srv
Note que os arquivos copiados para a pasta /srv do host estão sendo
exibidos também na pasta /srv do container
Capítulo 03 - Storage Drivers 59
Vamos remover o container e criá-lo novamente utilizando um
volume anônimo
1 docker container rm -f servidor
2 docker container run -dit --name servidor -v /volume debi\
3 an
Podemos utilizar o comando docker container inspect para verifi-
car o local e nome do volume criado
1 docker container inspect servidor | grep volume
Por padrão, os volumes criados e gerenciados pelo docker se
localizam no diretório /var/lib/docker/volumes
Podemos também visualizar informações do volume através do
comando docker volume inspect
1 docker volume ls
2 docker volume inspect <hash>
Visualize o volume criado no container
1 docker container exec servidor df -Th
2 docker container exec servidor ls -lR /volume
Copie os arquivos no host hospedeiro e verifique o conteúdo no
container
1 sudo cp -r ~/dockerfiles /var/lib/docker/volumes/<hash>/_\
2 data
3 docker container exec servidor ls -lR /volume
Vamos remover o container e criá-lo novamente utilizando um
volume nomeado
Capítulo 03 - Storage Drivers 60
1 docker container rm -f servidor
2 docker container run -dit --name servidor -v volume:/volu\
3 me debian
4 docker volume ls
Perceba que a diferença de um volume nomeado para um anônimo
é apenas o nome do volume
Para criar o mesmo container utilizando a flag --mount precisamos
passar o source e o target
1 docker container run -dit --name servidor2 --mount source\
2 =volume2,target=/volume2 debian
Podemos inspecionar o container filtrando o volume com a opção
-f ou --format
1 docker container inspect servidor --format '{{json .Mount\
2 s }}'
3 docker container inspect servidor2 -f '{{json .Mounts }}'
Podemos também visualizar de uma maneira mais agradável ao
instalar o jq e passar a saída dos comandos acima para o jq
1 sudo apt-get update && sudo apt-get install jq -y
2 docker container inspect servidor --format '{{json .Mount\
3 s }}' | jq
4 docker container inspect servidor2 -f '{{json .Mounts }}'\
5 | jq
Selinux Labels
O mode :z indica que o conteúdo do bind mount é compartilhado
entre múltiplos containers
Capítulo 03 - Storage Drivers 61
O mode :Z indica que o conteúdo do bind mount é privado e não
compartilhado
Para remover um volume no docker podemos utilizar a opção rm
1 docker volume ls
2 docker volume rm <hash>
3 docker volume rm $(docker volume ls -q)
O comando docker volume ls -q lista os volumes por id
ATENÇÃO: a remoção do volume através do comando
docker volume rm faz com que o volume seja excluído,
não sendo possível a recuperação dos dados.
tmpfs mounts
Volume e bind mounts permitem que compartilhemos arquivos
entre a máquina hospedeira e o container, de maneira a persistir
os dados após o container ser parado.
Outro tipo de volume é o tmpfs. quando criamos um container com
tmpfs mount, o container pode criar arquivos fora da camada de
escrita do container.
Diferente de volumes e bind mounts, um tmpfs é uma montagem
temporária, e só persiste na memória do host. Quando o container
para, o tmpfsmount é removido e os arquivos que foram criados lá
não persistem em disco.
tmpfs mounts são úteis para armazenar temporariamente informa-
ção sensível das quais não gostaríamos de persistir no host ou na
camada de escrita.
Para criar uma montagem tmpfs utilizamos o comando --tmpfs
Existem algumas diferenças que precisamos saber entre tmpfs e
bind mounts.
Capítulo 03 - Storage Drivers 62
• a flag --tmpfs não possibilita o uso de opções configuráveis.
• a flag --tmpfs não pode ser utilizada com serviços swarm.
(Apenas --mount)
Utilizando uma montagem do tipo tmpfs
1 docker container run -dit --name tmpfstest1 --mount type=\
2 tmpfs,destination=/app debian
3 docker container run -dit --name tmpfstest2 --tmpfs /app \
4 debian
Vamos inspecionar os containers
1 docker container inspect tmpfstest1 --format '{{json .Mou\
2 nts }}' | jq
3 docker container inspect tmpfstest2 -f '{{json .HostConfi\
4 g.Tmpfs }}' | jq
Adiferença entre osmodos demontagem é vista através
do docker container inspect e a seção de mounts e
host config.
Vamos remover os containers
1 docker container rm -f tmpfstest1 tmpfstest2
O tmpfs mount possibilita duas opções de configuração (Não obri-
gatórias), que apenas funcionam através da opção --mount
Opção Descrição
tmpfs-size Tamanho em bytes, por padrão não existe
limite
tmpfs-mode Permissionamento do tmpfs em octal. Ex:
700 ou 0770. Padrão 1777
Capítulo 03 - Storage Drivers 63
Exemplo:
1 docker container run -dit --name tmpfstest --mount type=t\
2 mpfs,destination=/app,tmpfs-size=100M debian
3 docker container inspect tmpfstest --format '{{json .Host\
4 Config.Mounts }}' | jq
5 docker container exec tmpfstest df -Th
6 docker container rm -f $(docker container ls -aq)
Backup & Restore
Podemos utilizar volumes para fazer backups, restaurações ou
migrações de sistemas, para isto utilizamos a flag --volumes-from
para criar um novo container que utilize o mesmo volume utilizado
anteriormente.
Backup
Vamos criar um container básico com o nome de webserver e copiar
alguns arquivos para o mesmo
1 docker container run -dit -v /webdata --name webserver de\
2 bian
3 docker container cp ~/dockerfiles webserver:/webdata
4 docker container exec webserver ls -lR /webdata
5 docker container exec webserver df -Th
6 docker volume ls
Veja que foi criado um volume do tipo anônimo.
Para entender como isto funciona, podemos subir um novo contai-
ner utilizando este volume do container webserver
Capítulo 03 - Storage Drivers 64
1 docker container run -dit --volumes-from webserver --name\
2 volumetest debian
3 docker container exec volumetest df -Th
4 docker container exec volumetest ls -lR /webdata
5 docker container inspect webserver --format '{{json .Moun\
6 ts }}' | jq
7 docker container inspect volumetest --format '{{json .Mou\
8 nts }}' | jq
9 docker container rm -f volumetest
Note que os volumes são os mesmos, com isso podemos efetuar o
backup dos arquivos do container subindo um container extra com
o propósito de empacotar os arquivos.
1 mkdir ~/backup
2 cd ~/backup
3 docker container run --rm --volumes-from webserver -v $(p\
4 wd):/backup alpine tar cvf /backup/backup.tar /webdata
5 tar -tvf backup.tar
O container com a imagem do alpine foi executado com a finalidade
única de empacotar o conteúdo do diretório /webdata em um novo
arquivo backup.tar
1 drwxr-xr-x root/root 0 2021-06-24 07:05 webdata/
2 drwxrwxr-x 1000/1000 0 2021-06-24 07:05 webdata/d\
3 ockerfiles/
4 -rw-rw-r-- 1000/1000 0 2021-06-24 07:05 webdata/d\
5 ockerfiles/arquivo2.txt
6 -rw-rw-r-- 1000/1000 0 2021-06-24 07:05 webdata/d\
7 ockerfiles/arquivo3.txt
8 -rw-rw-r-- 1000/1000 0 2021-06-24 07:05 webdata/d\
9 ockerfiles/arquivo1.txt
10 ````
11
Capítulo 03 - Storage Drivers 65
12 Vamos agora remover todos os containers e volumes criados
13 ```bash
14 docker container rm -f $(docker container ls -aq)
15 docker volume rm -f $(docker volume ls -q)
Restore
Para restaurar o volume para um novo container primeiramente
iremos criar o novo container com um novo volume.
1 docker container run -dit -v /webdata --name webserver2 d\
2 ebian
3 docker container exec webserver2 ls -lR /webdata
Agora podemos subir um novo container com o novo volume e
restaurar o backup
1 docker container run --rm --volumes-from webserver2 -v $(\
2 pwd):/backup alpine ash -c "cd /webdata && tar xvf /backu\
3 p/backup.tar --strip 1"
4
5 docker container exec webserver2 ls -lR /webdata
Plugins
Plugins são utilizados para extender as funcionalidades do Docker.
Atualmente o Docker suporta os plugins de Autorização, Redes e
Volumes.
Plugins são distribuidos como imagens docker e podem ser armaze-
nados no Docker Hub ou em um private registry.Para gerenciamento de plugins, utilizamos o comando docker
plugin
Capítulo 03 - Storage Drivers 66
Para uma lista completa dos plugins veja Docker Engine
Plugins⁶
Volume Plugins
Lista completa com definições Volume Plugins⁷
Os plugins de volumes habilitam com que os volumes docker
persistam através de diversos docker hosts.
Instalando um plugin
Iremos instalar um plugin chamado sshfs que trata-se de um plugin
para sistema de arquivos baseado em SSH.
O exemplo utilizado deve ser utilizado apenas para fins
de estudo, uma vez que o volume seja criado, sua senha
ssh para o host remoto será exposta como texto plano
quando inspecionar o volume.
1. Instale o plugin sshfs
1 docker plugin install vieux/sshfs
O plugin irá solicitar acesso a alguns privilégios.
• Acesso a rede host
• Acesso a capability CAP_SYS_ADMIN que habilita o plugin a
executar o comando mount.
• Acesso ao ponto de montagem
• acesso ao dispositivo /dev/fuse ou Filesystem in Userspace
2. Verifique se o plugin foi instalado e está habilitado
⁶https://docs.docker.com/engine/extend/legacy_plugins/
⁷https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins
https://docs.docker.com/engine/extend/legacy_plugins/
https://docs.docker.com/engine/extend/legacy_plugins/
https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins
https://docs.docker.com/engine/extend/legacy_plugins/
https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins
Capítulo 03 - Storage Drivers 67
1 docker plugin ls
3. Na máquina destino, garanta que o ssh está habilitado com
usuário e senha. Em um novo terminal
1 $ vagrant ssh node02
2 $ sudo yum install vim -y
3 $ sudo vim /etc/ssh/sshd_config
4
5 PasswordAuthentication yes
6
7 $ sudo systemctl restart sshd
4. Crie um volume utilizando o plugin.
1 $ docker volume create -d vieux/sshfs --name sshvolume -o\
2 sshcmd=vagrant@10.20.20.120:/vagrant -o password=vagrant
3 $ docker volume ls
4 $ docker volume inspect sshvolume | jq
5. Inicie um container com o volume
1 $ docker container run --rm -v sshvolume:/data alpine ls \
2 /data
Volume NFS
Na máquina master vamos instalar um servidor NFS e mapear um
diretório
Capítulo 03 - Storage Drivers 68
1 $ vagrant ssh master
2 $ sudo apt-get update
3 $ sudo apt-get install nfs-server -y
4 $ mkdir -p /home/vagrant/storage
5 $ echo "/home/vagrant/storage/ 10.20.20.0/24(rw)" | sudo \
6 tee -a /etc/exports
7 $ echo "<h1> Volume NFS master.docker-dca.example</h1>" |\
8 tee /home/vagrant/storage/index.html
9 $ sudo systemctl restart nfs-server
10 $ showmount -e
Na máquina node01 vamos instalar o client nfs
1 $ vagrant ssh node01
2 $ sudo apt-get install nfs-common -y
3 $ sudo showmount -e master.docker-dca.example
Na máquina node02 vamos instalar o client nfs
1 $ vagrant ssh node02
2 $ sudo yum install nfs-utils -y
3 $ sudo showmount -e master.docker-dca.example
Instale o plugin NFS na máquina node01 e node02
1 $ docker plugin install trajano/nfs-volume-plugin --grant\
2 -all-permissions
O plugin irá solicitar acesso a alguns privilégios.
• Acesso a rede host
• Acesso a capability CAP_SYS_ADMIN que habilita o plugin a
executar o comando mount.
• Acesso ao ponto de montagem /sys/fs/cgroup
Crie o volume na máquina node01
Capítulo 03 - Storage Drivers 69
1 $ docker volume create -d trajano/nfs-volume-plugin \
2 --opt device=master.docker-dca.example:/home/vagrant/stor\
3 age \
4 --opt nfsopts=hard,proto=tcp,nfsvers=3,intr,nolock volum\
5 e_nfs
6
7 $ docker volume inspect volume_nfs | jq
Execute um container com o volume nfs
1 $ docker container run -dit --name webserver -v volume_nf\
2 s:/usr/share/nginx/html/ -p 80:80 nginx
3 $ docker volume inspect volume_nfs | jq
Verifique nas máquinas o conteudo
1 $ watch curl -s localhost
Altere o conteudo do index.html na máquina master e verifique o
conteudo em tempo real nas máquinas node01 e node02
1 $ echo "<h2> Novo conteudo para o volume compartilhado</h\
2 2>" | tee -a /home/vagrant/storage/index.html
3 $ echo "<marquee> Se inscreva no canal https://youtube.co\
4 m/caiodelgadonew</marquee>" | tee -a /home/vagrant/storag\
5 e/index.html
Remova os containers dos nodes
1 $ docker container rm -f webserver
Capítulo 04 - Networking
Um dos motivos pelos quais os contêineres e serviços do Docker
são tão poderosos é que você pode conecta-los entre si ou a outros
serviços. Para isso, utilizamos as redes docker.
Recursos de Network utilizados pelo docker:
Networking
• veth: Virtual Ethernet
• bridge: Interface Bridge
• iptables: Regras de isolamento de redes
Administrando Redes
Por padrão quando um container é criado ele não publica nenhuma
de suas portas para o mundo externo. Para disponibilizar uma porta
para serviços fora do ambiente Docker ou para containers que não
estejam conectados a mesma rede, utilizamos a flag –publish ou -p.
Isso cria uma regra de firewall que mapeia uma porta de container
para uma porta do host.
Quando executamos um container, podemos definir a
publicação de uma ou mais portas através da opção -p
Capítulo 04 - Networking 71
hostaddress:hostport:containerport. Para expor as portas em
qualquer endereço utilizamos o hostaddress 0.0.0.0.
Vamos subir nosso container webserver expondo a porta para a
nossa rede
1 $ docker container run -dit --name webserver -p 80:80 web\
2 server
Podemos acessar a aplicação no navegador pelo endereço
http://node01.docker-dca.example
Remova o container webserver
1 $ docker container rm -f webserver
Network Drivers
O sistema de redes do docker é “plugável” com a utilização de
drivers. Existem diversos drivers para fornecer recursos e funcio-
nalidades de rede:
• bridge: Driver de rede padrão. Se não especificarmos um
driver, é o tipo de rede que o docker irá utilizar. Geralmente
utilizamos redes bridge quando a aplicação será executada em
containers isolados que precisam de comunicação.
• host: Para containers isolados, remove o isolamento de rede
entre o container e o host Docker e utiliza a rede diretamente.
• overlay: Redes utilizadas para conectar multiplos Docker
Daemons e habilitar os serviços de swarm (cluster) para se
comunicarem entre si.
• macvlan: Redes Macvlan possibilitam que configuremos um
endereço MAC a um container, fazendo com que ele apareça
como um dispositivo físico na rede. O docker daemon faz o
roteamento do trafégo entre containers pelo MAC Address.
Capítulo 04 - Networking 72
• none: Redes do tipo none disabilitam toda parte de redes do
container, não pode ser utilizada com swarm (cluster).
• plugins: Utilizados para extender a funcionalidade de redes
docker
Redes Básico
Para gerenciar as redes do docker, utilizamos o comando docker
network
Liste as redes disponiveis
1 $ docker network ls
Bridge
É a rede padrão do Docker, caso o container seja criado sem
especificar um driver de rede a rede do tipo bridge é utilizada. Esta
rede é criada utilizando um driver de rede de ponte que instancia
uma interface de rede no linux chamada de dockerX sendo X um
numero. Por padrão a rede bridge conta com um serviço interno
de DNS, ou seja, os containers respondem internamente através de
seu nome. Também é possivel conectar e desconectar containers
on-the-fly.
Capítulo 04 - Networking 73
bridge
Para executar um container com a rede bridge podemos passar
a flag --network bridge como parametro do comando docker
container run
1 $ docker container run -dit --name webserver --network br\
2 idge -p 80:80 webserver
Verifique o serviço na porta 80 do host
Capítulo 04 - Networking 74
1 $ sudo ss -ntpl | grep 80
O processo que é executado na porta através da rede bridge é o
docker-proxy
O que o docker faz por trás dos panos é a criação de uma série de
regras do iptables para criar o isolamento dos processos de rede.
Podemos verificar isto através do comando
1 $ sudo iptables -nL
Remova o container webserver
1 $ docker container rm -f webserver
Host
É a rede onde o IP da máquina é compartilhado com o container,
nesta rede não é

Mais conteúdos dessa disciplina