Repositório de estudos do Docker, Docker Compose, Docker Swarm e Kubernetes (k8s)
- O que é Docker?
- Containers
- Imagens
- Volumes
- Networks
- YAML
- Docker Compose
- Orquestração de containers
- Docker Swarm
- Kubernetes (k8s)
É um software que facilita o setup de aplicações, onde cada container possui configurações específicas de cada aplicação, independente de Sistema Operacional ou outro ambiente. Além disso, as tecnologias que utilizamos no Docker não precisam ser instaladas localmente no computador.
Imagine um cenário de 6 projetos em uma empresa, cada projeto com suas dependências e ambientes para execução. Como no exemplo abaixo.
Sem o Docker, é preciso configurar cada depenência separadamente para cada ambiente, uma tarefa que consome muito tempo para garantir que todas elas estejam rodando com as mesmas configurações. Além disso, é preciso ter muita resiliência para dar manutenção em todos os ambientes.
É um pacote de código que pode executar uma ação, Ex: projeto Node, projeto PHP, projeto Python. Os containers utilizam imagens para serem executados.
Diferente de uma VM (Virtual Machine), um container possui apenas um fim, não tendo um sistema operacional dedicado todo para ele, o que acaba tornando ele leve, geralmente com alguns MBs, enquanto VMs possuem GBs.
- Dar
pullno container
docker pull <imagem>- Executar o container
docker run <imagem>- Verificar se container está executando
docker psou
docker container lsPara verificar todos os containers que já foram executados
docker ps -aÉ quando o container fica executando em um terminal, permitindo executar comandos específicos dentro do container.
docker run -it <imagem>É quando o container roda em plano de fundo, não ocupando uma aba no terminal
docker run -d <imagem>docker stop <nome ou id do container>O comando docker stop para os containers, mas ele ainda ficam listados no comando docker ps -a, assim podemos executar eles novamente.
docker start <id do container>O comando
docker runCRIA UM NOVO CONTAINER. O comandodocker startroda o container novamente com as mesmas configurações de quando odocker runfoi executado a primeira vez
Também é possível reiniciar o container em modo iterativo
docker start -it <id do container>O container do docker é ISOLADO, ou seja, NÃO TEM CONEXÃO COM O MUNDO EXTERNO. Para possibiiltar isso é preciso export alguma porta do container.
Ex: usando o nginx como servidor web
- Baixar imagem do
nginx
docker pull nginx:stable-perl - Executar o container e expor uma porta
docker run -d -p 80:80 nginx:stable-perl O primeiro 80 é a porta que será aberta para o navegador, para que possamos acessar e o segundo 80 é a porta que a a plicação aplicação expõe. Se fizermos
3000:80é possível acessar a o servidornginxemlocalhost:3000.
- Entrar no servidor web
locahost:80
Caso não seja informado, um nome aleatório será atribuído ao container.
docker run --name <nome> <imagem>docker logs <id ou nome do container>Para exibir logs em tempo real é possível adicionar a flag
-f(follow)
docker logs -f <id ou nome do container>docker rm <id ou nome do container>Se o container estiver rodando ainda é preciso usar a flag
-f(force)
docker rm -f <id ou nome do container>É possível também remover um container automaticamente após a execução dele
docker run --rm <id ou nome da imagem>É possível copiar e colar arquivos entre uma máquina local e um container
docker cp <id ou nome do container>:/<diretório dentro do container para copiar> <diretório de destino>docker top <id ou nome do container>docker stats <id ou nome do container>Exibe todas as configurações do container
docker inspect <id ou nome do container>É o projeto que será executado pelo container, todas as instruções para rodar o container são feitas dentro de de um arquivo Dockerfile que é a imagem. Uma imagem pode levar como base uma imagem pronta.
Imagens prontas podem ser hospedadas no DockerHub.
Utilizando um servidor node com express como exemplo:
- Na raiz de um projeto criar um arquivo
Dockerfile
FROM node:latest
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]- Fazer o
buildda imagem
docker build <diretorio da imagem>- Verificar se a imagem foi criada com sucesso
docker image lsou
docker image ls- Copiar o id da imagem e executar o container
docker run -d -p 3000:3000 <id da imagem>Sempre o Dockerfile é alterado, é preciso executar o build novamente, pois para o Docker ela será é imagem completamente nova. Após isso é preciso executar o docker run com o novo id da imagem.
Cada instrução dentro do Dockerfile é uma camada. Quando algo é atualizado, apenas as camadas abaixo da linha atualizada são refeitas, o restante permanece em cache.
Sempre que uma imagem é gerada um nome anônimo é criado
docker tag <id da imagem> <nome>ou
docker tag <id da imagem> <nome>:<tag> Por default
:<tag>é:latest
É possível também nomear atribuir um nome a imagem ao executar o build.
docker build -t <nome>:<tag> .docker rmi <id ou nome da imagem>ou para remover todas as imagens
docker rmi -f $(docker images -q)Caso nenhum recurso do docker esteja sendo utilizado, como containers e imagens, é possível rodar o seguinte comando para remover todos:
docker system pruneUma forma prática de persistir dados (fazer backup) em aplicações para não depender de um container (Todo dado criado em um container é salvo nele, quando ele é removido, todos os dados também são).
- Anonymous: Volumes com nomes aleatórios (Criados com a flag
-v)
docker run -v /<diretorio do volume anonimo>Ex:
docker run -d -p 80:80 --name php-messages-container -v /data php-messages - Named: Volumes com nomes definidos
docker run -v <nome do volume>:/<diretorio do volume>Ex:
docker run -d -p 80:80 --name php-messages-container -v php-volume:/var/www/html/messages --rm php-messagesO diretório do volume precisa ser o mesmo do
WORKDIRdoDockerfile
- Bind Mounts: Forma de salvar na máquina local, sem gerenciamento do docker.
docker run <diretorio da maquina local>:/<diretorio do volume>Ex:
docker run -d -p 80:80 --name php-messages-container -v /Users/danielg.favero/Documents/estudos/docker/2-volumes/messages:/var/www/html/messages --rm php-messages- Apenas para leitura: Nesse tipo de volume não é possível escrever nenhum arquivo
docker run <diretorio da maquina local>:/<diretorio do volume>:ro
:roé abreviação para Read Only
É possível criar volume sem precisar rodar um container
docker volume create <nome do volume>Posteriormente é possível atrelar esse volume a um container.
docker volume lsdocker volume inspect <nome do volume>docker volume rm <nome do volume>Remover um volume REMOVE TODOS OS DADOS dentro dele
É possível também remover todos os volumes não utilizados
docker volume pruneÉ a forma gerenciar a conexão entre os containers do docker com outras plataformas ou até mesmo outros containers. Assim como os Volumes, eles são criados separados dos containers.
- Externa: Conexão com uma API ou servidor externo.
- Com o host: Comunicação do container com a máquina local.
- Entre containers: Comunicação que utiliza com um
driverbridgepara comunicar dois ou mais containers.
- Bridge: É o default do Docker, utilizado quando dois ou mais containers precisam se conectar.
- Host: Permite conexão do container com a máquina local.
- Macvlan: Permite conexão a um container por meio de um endereço MAC.
- None: Remove todas as conexões de rede de um container.
- Plugins: Permite extensões para criar outras redes.
docker network lsAlguns networks são criados por padrão pelo Docker para sua configuração inicial.
NETWORK ID NAME DRIVER SCOPE
da3c20a11139 bridge bridge local
d9b873f523c1 host host local
70f5a0873c36 none null localdocker network create <nome da rede>Por padrão ela será do tipo
bridge
Para criar com um driver específico:
docker network create -d macvlan <nome da rede>docker network rm <nome da rede>Para remover todas as redes não utilizadas:
docker network pruneAo executar o container:
docker run --network <nome da rede>Ou manualmente após a execução:
docker network connect <nome da rede> <nome do container>docker network disconnect <nome da rede> <nome do container>docker network inspect <nome da rede>É uma linguagem utilizada para arquivos de configuração, principalmente para configurar o docker compose. São arquivos com extensão .yml ou .yaml.
Assim como o python as instruções são identificadas por identações e espaços.
# String
name: "Daniel"
last_name: Gustavo Favero # Não precis de aspas
# Integer
age: 24
# Float
currency: 150.4
# Boolean
is_admin: True # True
is_customer: on # True
is_visitor: False # False
is_guest: off # False
# Null
first_null_value: null
second_null_value: ~
# Objects
first_object:
version: 2
file: "test.txt"
nested:
key: value
second_object: { version: 2, file: "test.txt", nested: { key: value } }
# Lists
first_list: [1, 2, 3, 4, 5]
second_list:
- "First"
- 2
- 3.0
- TrueÉ uma ferramenta para rodar múltiplos containers usando apenas um arquivo de configuração. É semelhante a criar um arquivo Dockerfile.
name: WordpressApp
services:
db: # Container do MySQL
container_name: MySQL
image: mysql:8.0.43 # FROM mysql:8.0.43
command: mysqld --default_authentication_plugin=mysql_native_password
environment:
TZ: America/Sao_Paulo
MYSQL_ROOT_PASSWORD: docker
MYSQL_USER: docker
MYSQL_PASSWORD: docker
MYSQL_DATABASE: wordpress
ports:
- 3308:3306
networks:
- wordpress-network
wordpress: # Container do Wordpress
container_name: Wordpress
depends_on: # Quais serviços o container depende (ele só vai executar esse serviço após essa lista ser executada)
- db
image: wordpress:latest
volumes:
- ./config/php.conf.uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
- ./wp-app:/var/www/html
environment:
TZ: America/Sao_Paulo
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: docker
ports:
- 80:80
networks:
- wordpress-network
networks:
wordpress-network:
driver: bridgedocker-compose upou para executar em background
docker-compose up -ddocker-compose downPara inserir variáveis de ambiente em um arquivo docker-compose.yaml:
- Criar um arquivo
.env
ENV_1=1
ENV_2=2
...- Atualizar arquivo
docker-compose.yaml:
# ...
services:
# ...
service-1:
# ...
env_file:
- ./.env
# ...Por padrão o docker compose cria uma rede com driver bridge. Mas é possível isolar redes.
# ...
services:
# ...
service-1:
# ...
networks:
- network-name
# ...
networks:
# ...
network-name:
driver: bridge
# ...É preciso informar o caminho do Dockerfile para que seja executado o build. Nesse caso não é necessário informar a chave image.
# ...
services:
# ...
service-1:
# ...
build: <caminho-para-o-dockerfile>Para fazer alterações no projeto e persistir as alterações nos containers.
services:
# ...
service-1:
# ...
volumes:
- <caminho-onde-o-bind-mount-vai-monitorar-para-verificar-alteracoes>docker-compose psÉ o ato de conseguir gerenciar e escalar containers de uma aplicação. Geralmente se opta por uma arquitetura horizontal, onde pequenas máquinas ficam responsáveis por dar vazão e distribuição dos containers para os usuários. Nessa arquitetura há uma serviço que rege todos os outros.
Alguns serviços que realizam orquestração: Docker Swarm, Kubernetes, etc.
É uma ferramenta do Docker para orquestrar containers de forma horizontal. Os comandos são muito semelhantes aos do Docker. Por padrão, o Docker já vem com o Swarm, porém desabilitado.
- Nodes: é uma instância que participa do Swarm;
- Manager Node: node que gerencia os demais nodes;
- Worker Node: node que trabalha em função do manager;
- Service: Um conjunto de tarefas que o Manager Node manda para o Worker Node executar;
- Task: Comandos que são executados nos Nodes.
docker swarm initRodar esse comando tornará a máquina um
nodee o transformará emmanager
docker node lsdocker swarm join --token <token do node><ip>:<porta>Esse
nodejá entra no swarm comoworkerAo rodardocker swarm inito comando dejoinjá é apresentado para conectar osnodes
docker service create --name <nome do servico> -p <porta da aplicacao> <imagem>Isso inicia o serviço em apenas uma máquina
docker service lsApenas o
nodemanagertem acesso a essa informação
docker service rm <nome ou id do serviço>É definido na hora da criação do serviço
docker service create --name <nome do servico> -p <porta da aplicacao> --replicas <numero de replicas> <imagem>Isso irá emitir uma task que irá replicar o serviço nos workers.
Remover um container de um
workerfaz o swarm atualizar e iniciar novamente de forma automatica o serviço naqueleworker
Recuperar o comando de join do node manager.
docker swarm join-token managerdocker infodocker swarm leave Ou para sair de um node manager
docker swarm leave -f O node apenas sai do Swarm, mas ele continua executando.
docker node rm <id do node>Caso esteja rodando um serviço, é preciso usar a flag
-f
docker service inspect <id do serviço>docker service ps <id do serviço>É semelhante ao
docker ps -aEle mostra informações de quenodesestão executando o serviço
docker stack deploy -c <arquivo do compose> <nome>docker service scale <nome do serviço> = <numero de replicas>docker node update --availability drain <id do node>docker service update --<propriedade> <novo valor da propriedade> <id do serviço>Ex 1: Alterando imagem do serviço
docker service update --image <id da imagem> <id do serviço>Ex 2: Alterando rede do serviço
docker service update --network <id da rede> <id do serviço>Apenas os nodes com status
ACTIVEreceberão essa atualização
docker network create --driver overlay <nome da rede>Entra máquinas o driver que precisa ser utilizado é o
overlay
docker service update --image <id da imagem> <id do serviço>Assim como o Docker Swarm, é também uma ferramenta de orquestração de containers. Diferente do Swarm, o Kubernetes possui o Minikube para simular diversas máquinas
- Control Plane: onde é gerenciado o controle dos processos dos Nodes. É o Node Manager;
- Nodes: Máquinas gerenciadas pelo Control Plane;
- Deployment: A execução de uma imagem no Pod;
- Pod: Um ou mais containers que estão em um Node. Dados gerados nos Pods são apagados;
- Services: Serviços que expõem os Pods ao mundo externo por meio de uma rede;
- kubectl: CLI do Kubernetes.
minikube start --driver=<nome do driver>O nome do driver por ser:
virtualboxhypervdocker
minikue stopAo reiniciar o computador, o Minibuke para automaticamente
minikube dashboardOu para obter apenas a URL
minikube dashboard --urlPara subir o container para o Minikube, primeiro é preciso enviar a imagem buildada para o Docker Hub
docker push <nome-da-imagem>E em seguida criar um Deployment
kubectl create deployment <nome do deployment> --image=<nome da imagem>O resultado do Deployment pode ser exibido na dashboard do Minikube
Pode-se verificar na dashboard ou por linha de comando
kubectl get deploymentsOu para receber mais detalhes
kubectl describe deploymentskubectl get podsOu para receber mais detalhes
kubectl describe podskubectl config viewkubectl expose deployment <nome do deployment> --type=<nome do tipo> --port=<porta para expor o pod>O
typeLoadBalanceré o mais comum de se utilizar
Executar um service gera um IP para acessar o serviço
minikube service <nome do service>kubectl get servicesOu para mais detalhes
kubectl describe services/<nome do service>kubectl scale deployment/<nome do deployment> --replicas=<numero de replicas>kubectl get rsO nome dessa técnica é Scale Down
kubectl scale deployment/<nome do deployment> --replicas=<numero menor de replicas>- Subir uma nova tag da imagem no Docker Hub
docker push <nome da imagem atualizada>- Atualizar a imagem no kubernetes
kubectl set image deployment/<nome do deployment> <nome do container> = <nome da imagem atualizada>Para verificar uma alteração
kubectl rollout status deployment/<nome do deployment>E para fazer o Rollback
kubectl roullout undo deployment/<nome do deployment>kubectl delete service <nome do service>kubectl delete deployment <nome do deployment>É quando o kubernetes é executado por meio de um arquivo de configuração (semelhante ao docker compose).
# Versão que a ferramenta vai utilizar
apiVersion: apps/v1
# Tipo do arquivo (Deployment ou Service)
kind: Deployment
metadata:
name: flask-app-deployment
spec:
# Número de replicas
replicas: 4
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
# Especificação dos containers
containers:
- name: flask
image: danielgfavero/flask-kubernetes:2
kubectl apply -f <caminho do arquivo>kubectl delete -f <nome do arquivo># Versão que a ferramenta vai utilizar
apiVersion: v1
# Tipo do arquivo (Deployment ou Service)
kind: Service
metadata:
name: flask-service
spec:
# Link entre o service e o deployment
selector:
app: flask-app
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: LoadBalancerO comando é igual ao arquivo de deployment
kubectl apply -f <caminho do arquivo>kubectl delete -f <nome do arquivo>- Criar nova versão da imagem
- Dar push no
Docker Hub - Alterar a tag da imagem no arquivo de deployment
- Usar o comando
applypara aplicar as mudanças
Uma boa prática é escrever o service antes do deployment.
---
# Versão que a ferramenta vai utilizar
apiVersion: v1
# Tipo do arquivo (Deployment ou Service)
kind: Service
metadata:
name: flask-service
spec:
# Link entre o service e o deployment
selector:
app: flask-app
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: LoadBalancer
---
# Versão que a ferramenta vai utilizar
apiVersion: apps/v1
# Tipo do arquivo (Deployment ou Service)
kind: Deployment
metadata:
name: flask-app-deployment
spec:
# Número de replicas
replicas: 4
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
# Especificação dos containers
containers:
- name: flask
image: danielgfavero/flask-kubernetes:2
---separa o arquivo yaml em seções
