Começando bem com Docker

igorspestana

Igor Pestana

Posted on February 21, 2023

Começando bem com Docker
  1. Introdução

  2. Arquitetura do Docker

  3. Instalação do Docker

  4. Imagem

  5. Container

  6. Port Bind

  7. Networks

  8. Volumes

  9. Docker Registry

  10. Docker compose

  11. Boas práticas

  12. Desinstalar o Docker

1. Introdução

1.1. Stacks para fazer deploy da aplicação

Stack tradicional com vm

hardware → hypervisor → virtual machine → operating system → application

  • Na criação de um hardware virtual o kernel é isolado e cada vm tem o seu próprio kernel.

Desvantagem:

  • Desperdício de hardware

  • Difícil gerenciamento de libs — Várias aplicações usando a mesma lib pode gerar problema. Atualizações de lib feita pelo próprio OS podem quebrar a aplicação

  • Não é imutável

Stack com container

hardware → operating system → container engine (docker) → container 1 / container 2 / containter 3

  • Docker foi feito para ser usado no linux porque usa primitivas do kernel linux para construir um container (chroot, cgroups)

  • O Docker é instalado como um pacote do linux

  • O container utiliza o mesmo kernel do OS (docker host) e isola as aplicações usando o conceito de namespaces.

  • Os containers são pedaços lógicos isolados compartilhando o mesmo kernel.

Vantagens:

  • Otimização de recursos hardware

  • Empacotamento da aplicação — Acaba com o problema de “funciona na minha máquina mas não funciona na sua”

  • Imutabilidade — Por conta do empacotamento a mesma aplicação pode rodar na minha máquina, no servidor, em cloud e onde mais quiser porque a aplicação não muda, é um objeto.

  • Facilidade no deploy

1.2. Containers

  • Abstração a nível de sistema operacional

  • Agrupa códigos, bibliotecas e dependências para garantir a execução de um aplicativo em um ambiente isolado

  • Parece com as máquinas virtuais mas as máquinas virtuais são uma abstração a nível de hardware com a simulação de servidores dentro de um servidor com um sistema operacional completo.

  • Containers (MB) são mais leves que VMs (GB).

  • Os containers não precisam de um SO completo.

  • Os containers compartilham o mesmo kernel do SO onde estão sendo executados. São como um processo do SO.

Vantagens do uso:

  • Ambiente isolado

  • Idempotência

  • Distribuição facilitada

Desvantagens:

  • Escalabilidade

  • Resiliência

Ferramentas container:

  • Docker

  • Podman

  • ContainerD

1.3. Docker

  • Tecnologia e plataforma open source

  • Para VMs temos o Virtualbox e para containers temos o Docker

  • Otimização muito mais eficiente dos recursos

  • Inicialização muito mais rápida que as VMs

  • Importante para trabalhar numa arquitetura de sistemas distribuídos com microsserviços.

  • Microsserviços são serviços independentes que se comunicam entre si. Uma vantagem de utilizar o microsserviços é utilizar a multilinguagens (um java e outro em node).

  • Usando o Docker para microsserviços a gente garante um ambiente isolado com as dependências específicas para aquele serviço para serem executados em qualquer ambiente ou em qualquer servidor.

  • Facilidade de escalar os containers, os serviços de acordo com a demanda. Facilidade de expandir a aplicação.

  • Orquestração de containers: Docker Swarm e Kubernetes

1.4. Virtualização X Containerização

Container = combinação de tecnologias do kernell do linux (cgroups + namespaces + overlayfilesystem)

2. Arquitetura do Docker

2.1. Elementos da arquitetura

Docker Daemon — responsável por executar os containers e gerenciar todos os objetos do docker

Docker Client — ferramenta de interação com Docker Daemon

Docker Registry — repositório de imagens docker. dockerhub, azure container registry, elastic container registry

Client

  • O client é a linha de comando

  • $ docker ps $ docker pull $ docker run

  • O client se comunica diretamente com o docker daemon do docker host. É possível configurar a linha de comando da minha máquina para se comunicar com outro docker host como o docker host que está na aws, azure, na empresa via vpn, etc.

Docker Host

  • No docker host existe um processo chamado docker daemon que faz a lógica de gerenciar as imagens.

  • Quando baixamos uma imagem o docker daemon coloca em /var/livre/docker

Registry

  • Como uma store das imagens docker

  • Servidor remoto que tem imagens para o docker daemon baixar.

  • https://hub.docker.com/

  • Empresas possuem registry privado como o Nexus, Jay Frog ou um provedor de cloud.

3. Instalação do Docker

Aqui apresento duas possibilidades para instação do Docker.

Opção 1- Seguir a documentação para instalação no Ubuntu https://docs.docker.com/engine/install/ubuntu/

Erro de falta de permissão

Para corrigir

Depois que o Docker é instalado ele cria um grupo. É necessário adicionar o usuário ao grupo Docker.

Para acessar todos os grupos do linux cat /etc/group

Para adicionar o usuário ao grupo sudo usermod -a -G docker

Reiniciar o sistema

Opção 2- Seguir para instalação do docker engine diretamente no wsl2 https://github.com/codeedu/wsl2-docker-quickstart#docker-engine-docker-nativo-diretamente-instalado-no-wsl2

4. Imagem

Imagem:

  • Base para executar o processo com o container

  • Template do que vai ser executado em um container

  • Filesytem necessário para executar o container: Executável da aplicação, Instalação da aplicação, Pacotes necessários para executar a aplicação.

Comandos

docker image ls - lista as imagens

docker image rm $(docker image ls -aq) - remove todas as imagens

docker image prune - remove as imagens que não estão sendo mais utilizadas

docker build -t -f Dockerfile . - cria uma imagem baseada no Dockerfile. Se o Dockerfile estiver no diretório atual não é necessário usar o parâmetro -f. ex. docker build -t ubuntu-curl -f Dockerfile . ou docker build -t ubuntu-curl .

docker build -t . --no-cache - cria uma imagem sem o cache. ex. docker build -t ubuntu-curl . --no-cache

Padrão do nome da imagem

  • Na criação da imagem é necessário informar a tag.

  • Durante o uso do Docker quando a tag não é inserida é utilizado a tag latest da imagem.

    docker build -t igorspestana/rotten-potatoes:v1 -f Dockerfile .

Cache

Imagem

  • Sistema de arquivo em camadas

  • A cada execução de um parâmetro é criada uma nova camada. Criando uma pilha de camadas.

  • As camadas criadas na imagem são apenas de leitura (read).

Container

  • O container cria uma camada de leitura e escrita (read and write) sobre a camada de leitura (read) de uma imagem pronta.

  • O container é rápido de ser criado e jogado fora porque é apenas uma camada.

    Pesquisar sobre o overlay file system para entender o modelo de camadas.
    Quando o docker cria uma container ele usa uma imagem como referência. Dessa forma não é criado uma imagem toda vez que um container novo é criado e isso gera uma economia de recursos, otimiza a construção da imagem e o upload da imagem. O Docker cria um cache para armazenar os dados das imagens de referencia e é reutilizado para cada container.

Dockerfile

Receita para criar imagem.

Processo: Dockerfile → Imagem → Container

  • Arquivo de texto enviado para o Docker com as instruções para criar uma imagem.

  • Alguns statements:

  • From: a partir de qual imagem será criado. imagem base com binário e pip. Workdir: Run: comandos que vou executar dentro da imagem. instalar um pacote, permissão de execução para um arquivo, mover um arquivo, etc. comandos executados antes de subir a aplicação. Expose: porta que está exposta. onde a aplicação está recebendo dados. Copy: copiar arquivos de onde esta rodando o docker e vai jogar para dentro da imagem. Env: declarar variáveis de ambiente Cmd: qual comando será executado quando eu der um docker run, quando iniciar o container a partir da imagem. comando para subir a aplicação.

Statements

FROM -> Inicializa o build de uma imagem a partir de uma imagem base.
RUN -> Executa um comando.
LABEL -> Adiciona metadados a imagem.
CMD -> Define o comando e/ou os parâmetros padrão.
EXPOSE -> Define que o container precisa expor a porta em questão.
ARG -> Define um argumento para ser usado no processo de construção.
ENV -> Define variáveis de ambiente.
ADD -> Copia arquivos ou diretórios ou arquivos remotos e adiciona ao sistema de arquivos da imagem.
COPY -> Copia arquivos ou diretórios e adiciona ao sistema de arquivos da imagem.
ENTRYPOINT -> Ajuda a configurar um container que pode ser executado como executável.
VOLUME -> Define volumes que devem ser definidos.
WORKDIR -> Define o seu diretório corrente.

Exemplo 1 — Criando uma imagem Ubuntu a partir de um Dockerfile

1- Criando o Dockerfile

Dockerfile

FROM ubuntu
RUN apt update
RUN apt install curl --yes
Enter fullscreen mode Exit fullscreen mode

FROM ubuntu
RUN apt update && \\
        apt install curl --yes
        apt install vim --yes

FROM ubuntu
RUN apt update && \\
        apt install curl vim --yes
Enter fullscreen mode Exit fullscreen mode

Importante manter o apt install junto do apt update no mesmo comando.

2- Criando a imagem

docker build -t ubuntu-curl .
Enter fullscreen mode Exit fullscreen mode

5. Container

docker container ls -a - mostra os containers criados. -a parâmetro que mostra também os containers que não estão em execução.

docker - mostra as informações do container

docker container run - inicia o container. ex. docker container run ubuntu

docker container stop - interrompe um container em execução.

docker container start -i - inicia um container existente. -i parâmetro que executa o container de forma interativa. ex. docker container start f06a0ce6cd43 -i

docker container run -it ubuntu /bin/bash - inicia o container. -i parâmetro que executa o container de forma interativa. -t parâmetro que habilita o tty.

docker container run -e - inicia o container. -e parâmetro de variável de ambiente. ex. docker container run -e MONGO_INITDB_ROOT_USERNAME=mongouser -e MONGO_INITDB_ROOT_PASSWORD=mongopwd mongo

docker container rm - remove um container.

docker container rm $(docker container ls -aq) - remove todos os containers.

docker container rm -f $(docker container ls -aq) - remove todos os containers. -f remove mesmo se estiverem em execução

docker inspect - mostra informações do container ex. docker inspect 60037a544848

6. Port Bind

O port bind vincula uma porta local a uma porta do container. Dessa forma não é necessário acessar o container para só então acessar a aplicação. Na imagem ao acessar a porta local 8080 é feito um vínculo com a porta 27017 onde é possível acessar o processo que está rodando nessa porta.

docker container run -p : - inicia o container. -p parâmetro que define o vínculo da porta local com a porta do container.

Exemplo 1 — Criando um servidor http Nginx.

Exemplo 2 — Criando um gerenciador de banco de dados PostgreSQL.

1- Criando o container

Para acessar um banco de dados é necessário definir usuário, senha e definir um banco de dados. Nesse caso a criação do container precisa especificar variáveis de ambiente.

Para ler a documentação: https://hub.docker.com/_/postgres

2- Configurando o DBeaver

Para download do client de db: https://dbeaver.io/download/

Exemplo 3 — Criando um gerenciador de banco de dados MongoDB.

7. Networks

IP

Todo container tem um IP e pode ser visto usando o comando docker container inspect :

Exemplo

Criação do container usando as variáveis do mongo e referenciando o ip 172.17.0.2

docker container run -d -p 5000:5000 -e MONGODB_HOST=172.17.0.2 -e MONGODB_USERNAME=mongouser -e MONGODB_PASSWORD=mongopwd igorspestana/rotten-potatoes:v1

Container não deve ser referenciado por IP porque ele é efêmero e está o tempo todo caindo e subindo um novo com novo IP. A forma correta é usando o Docker Network

Docker Network

docker network create - cria uma network

Exemplo

Criação do container usando as variáveis do mongo e referenciando a network

Criando container com network especificada

docker container run -d -p "27017:27017" -e MONGO_INITDB_ROOT_USERNAME=mongouser -e MONGO_INITDB_ROOT_PASSWORD=mongopwd --name mongodb --network=rotten-network mongo

Criação do container usando as variáveis do mongo e referenciando o host mongodb

Criando container com network especificada

docker container run -d -p 5000:5000 -e MONGODB_HOST=mongodb -e MONGODB_USERNAME=mongouser -e MONGODB_PASSWORD=mongopwd --name rotten-potatoes --network=rotten-network igorspestana/rotten-potatoes:v1

8. Volumes

Existem duas possibilidades para que os dados sejam mapeados: fazendo um bind de diretório ou usando o Docker Engine

O volume deve ser especificado no container para que na situação do container com o banco de dados cair e subir um novo os dados continuem populando a aplicação.

Comandos

docker inspect - mostra informações do volume como o diretório local de armazenamento

docker volume ls - lista os volumes

docker volume rm $(docker volume ls) - remove todos os volumes

Bind de diretório

Cuidado quando for trabalhar com volume gerenciado por você mesmo utilizando o bind, fazendo um vínculo de diretório. A melhor forma de trabalhar com o volume é o docker gerenciando o volume com o Docker Engine.

Exemplo:

docker container run -d -p "27017:27017" -e MONGO_INITDB_ROOT_USERNAME=mongouser -e MONGO_INITDB_ROOT_PASSWORD=mongopwd --name mongodb --network=rotten-network -v "$(pwd)/mongodb:/data/db" mongo

Docker Engine

Criar volume

docker volume create - para criar o volume. ex. docker volume create mongo-vol

docker volume ls - lista os volumes criados.

Backup do volume

9. Docker Registry

Enviar imagem para o docker registry

Comandos

docker login - login no docker

docker logout - logout no docker

docker push - sobe a imagem para o dockerhub ex. docker push igorspestana/rotten-potatoes:v1

docker tag - criar uma imagem com a tag latest. ex. docker tag igorspestana/rotten-potatoes:v1 igorspestana/rotten-potatoes:latest

Boa prática: enviar a imagem latest

10. Docker compose

Receita para criar container

docker network create

docker volume create

docker container run mongo

docker container run app

docker-componse up -d - subir container a partir do compose

docker-compose down - derrubar container a partir do compose

11. Boas práticas

Para garantir a idempotência é necessário informar a tag da imagem base. ex. node:16.15.0 . Especificando apenas node teremos a imagem latest, essa imagem mais atualizada pode ter algum breaking change e comprometer a aplicação. É possível conferir as versões disponíveis no dockerhub.

Nunca use imagens desconhecidas. Use imagens oficiais ou imagens confiáveis.

FROM node:16.15.0
WORKDIR /app
COPY ./package*.json
RUN npm install
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
Enter fullscreen mode Exit fullscreen mode

Usar COPY separado para arquivo das dependências e arquivo da aplicação. A aplicação constantemente sofre alteração e as dependências não, dessa forma aproveitamos o cache das camadas para otimizar a construção da imagem.

FROM node:16.15.0
WORKDIR /app
COPY ./package*.json
RUN npm install
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
Enter fullscreen mode Exit fullscreen mode

Usar o .dockerignore para que ignorar diretórios específicos na hora de construir imagens.

Quando o comando npm install roda o diretório node_modules é criado com as dependências especificadas em package-lock.json e package.json.

Usando o .dockerignore com esse diretório especificado a criação desse diretório será ignorada no momento que a imagem for criada. **

12. Desinstalar o Docker

Para desinstalar completamente o Docker:

Passo 1

dpkg -l | grep -i docker
Enter fullscreen mode Exit fullscreen mode

Para identificar qual pacote instalado você tem:

Passo 2

sudo apt-get purge -y docker-engine docker docker.io docker-ce docker-ce-cli docker-compose-plugin
sudo apt-get autoremove -y --purge docker-engine docker docker.io docker-ce docker-compose-plugin
Enter fullscreen mode Exit fullscreen mode

Os comandos acima não removerão imagens, conteineres, volumes ou arquivos de configuração criados pelo usuário em seu host. Se você deseja excluir todas as imagens, contêineres e volumes, execute os seguintes comandos:

sudo rm -rf /var/lib/docker /etc/docker
sudo rm /etc/apparmor.d/docker
sudo groupdel docker
sudo rm -rf /var/run/docker.sock
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
igorspestana
Igor Pestana

Posted on February 21, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related