Docker: "funciona na minha máquina"
Containers são um dos maiores responsáveis por como servimos as aplicações hoje.
O que é o Docker?
Docker é um conjunto de soluções PaaS (Plataforma Como Um Serviço), de código aberto, para servir aplicações através da construção, deploy e gerência de containers.
O que é um container?
Segundo o site oficial do Docker
Containers são unidades padrão de software, que empacotam códigos e todas as suas dependências, para que a aplicação rode de maneira rápida e confiável de um ambiente para outro.
Vamos entender essa definição. Eles são unidades padrão de software, porque sua execução é isolada do sistema operacional, isso permite que ela funcione sem interferências de outros programas, o que a torna mais estável e reprodutível.
Container vs Máquina virtual
Após a definição acima, você talvez esteja pensando: “Não é isso que uma máquina virtual faz?”. Bom, realmente um máquina virtual cria um isolamento do sistema operacional principal, mas ela faz isso virtualizando outros sistemas operacionais, consumindo muito mais recursos em relação aos containers, já que eles funcionam como processos do sistema operacional.
Como funciona um container?
O container funciona através da combinação de namespaces, que é uma funcionalidade que permite o isolamento entre grupos de processos em seu nível lógico, com cgroups, que uma funcionalidade de definição de limite e compartilhamento de consumo de recursos por um processo.
Namespaces
- PID - Isolamento de processos
- NET - Isolamento de interfaces de rede
- IPC - Isolamento de comunicação entre processos e memória compartilhada
- MNT - Isolamento do Sistema de Arquivos / ponto de montagem
- UTS - Isolamento do kernel (simula outro host)
Cgroups
- blkio - Implementa bloqueio de entrada e saída
- acct - Agrupa tarefas usando cgroups e declara o uso de CPU desses grupos
- sets - Provém um mecanismo de atribuição de CPUs e memória para um conjunto de tarefas
- devices - Implementa um cgroup para impor restrições a arquivos de dispositivos
- freezer - Gerencia o estado de execução de uma tarefa, pausando e executando de acordo com a vontade do administrador do sistema
- hugetlb - Controlador que permite ajustar o uso de páginas de memória virtual maiores, por grupo de controle
- memory - Controlador que isola o comportamento da memória, de um grupo de tarefas, do resto da sistema
- net_cls - Provém um interface para marcar pacotes de rede com um identificador de classe
- net_prio - Provém um interface que permite a um administrador configurar dinamicamente a prioridade de um tráfico rede
- resource_counter - Deve facilitar o gerenciamento de recursos pelos controladores, provendo ferramentas em comum para contabilização
Container vs Imagem
Container é uma imagem com uma camada temporária de leitura e escrita. Isso permite que a mesma imagem seja reutilizada, alterando somente a camada e leitura e escrita, o que torna o processo do container ainda mais leve.
Tipos de persistência
Bind mounts
Gerenciados pelo file system
docker run -it -v /volume-dk:/app ubuntu
docker run -it --mount type=bind,source=/home/viniciusflv/Documents/codes/app-exemplo/volume-dk,target=/app ubuntu
Volumes
Gerenciados pelo docker
docker volume create [name]
docker run -it -v meu-volume:/app ubuntu
docker run -it --mount source=meu-volume,target=/app ubuntu
tmpfs
Não é escrito na camada de leitura e escrita
docker run -it --tmpfs=/app ubuntu
docker run -it --mount type=tmpfs,destination=/app ubuntu
Comunicação através de redes
Lista redes
docker network ls
Bridge
Cria um canal de redes
Cria redes
docker network create --driver bridge [netname]
Nomes de redes
docker run -it --name [name] --network [netname] [image] [cmd]
None
Remove a interface de rede
Host
Remove o isolamento da rede do container e sistema
Instalando o docker no linux
Atualizando programas
sudo apt update
Instalando dependências
sudo apt install \ ca-certificates \ curl \ gnupg \ lsb-release
Fazendo o download
sudo mkdir -p /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Adicionando a chave de assinatura
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Instalando o Docker CE
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Dando permissão de execução da CLI para o usuário
sudo usermod -aG docker $USER
Executando um container
Para executar um container podemos acessar o Docker Hub, que é um repositório de imagens de código aberto publicadas, e procurar uma imagem. Vou começar escolhendo a imagem oficial do Ubuntu.
docker run ubuntu
Sempre que executar um container o seguinte fluxo irá acontecer:
Como foi a primeira execução você vai notar que os seguintes logs aparecerão no seu terminal:
Unable to find image 'ubuntu:latest' locallylatest: Pulling from library/ubuntue96e057aae67: Already existsDigest: sha256:4b1d0c4a2d2aaf63b37111f34eb9fa89fa1bf53dd6e4ca954d47caebca4005c2Status: Downloaded newer image for ubuntu:latest
Também vai notar que nada acontece, mesmo rodando o comando outra vez. Isso é porque o padrão do docker é encerar a execução do container caso não tenha nenhum processo rodando.
Podemos executar um comando do container declarando ele na frente do id da imagem:
docker run ubuntu echo Olá mundo
Listando imagens e containers em execução
Agora que já fizemos o download da nossa primeira imagem podemos listá-las com o comando:
docker images
Para listar os containers em execução vamos primeiro executar o bash em modo interativo:
docker run -it ubuntu bash
E em outro terminal execute o comando:
docker ps
Deletando imagens e containers
Deleta um container
docker container rm -f [container]
Deleta todos os containers
docker container rm -f $(docker container list -q)
Deleta uma imagem
docker image rm -f [image]
Construindo uma imagem
Para construir uma imagem é necessária a criação de um arquivo Dockerfile. Nesse arquivo será declarado uma série de instruções que irão configurar a imagem.
FROM
Todo Dockerfile deve ser precedido pela instrução FROM seguido do id da imagem pai. Ela serve de base para podermos construir nossa camada customizada da imagem.
FROM ubuntu
RUN
Podemos rodar comandos dentro da imagem através da instrução RUN. O resultado desses comandos serão atribuídos a imagem de maneira sequencial.
RUN echo Hello World
LABEL
Adicionam metadados a uma imagem.
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
CMD
O propósito principal da instrução CMD é prover argumentos padrões para a execução de um ENTRYPOINT.
CMD ["cd", "./app"]
EXPOSE
Expõe uma porta de execução de uma aplicação.
EXPOSE 3000
ENV
Declara uma variável de ambiente.
ENV PORT=3000
ARG
Define variáveis que usuários podem passar em build-time com o comando docker build
através da flag --build-arg <varname>=<value>
.
ENV PORT=3000
ADD
Copia arquivos remotos ou compactados e adiciona ao sistema de arquivos da imagem.
ADD hom* /mydir/
COPY
Copia arquivos locais e adiciona ao sistema de arquivos da imagem.
COPY hom* /mydir/
VOLUME
Cria um ponto de montagem de disco, com um nome especifico, e marca ele como montado externamente para outros volumes ou containers.
VOLUME ["/data"]
USER
Instrução que cria um nome de usuário (ou UID), e opcionalmente o grupo do usuário (ou GID), para ser usado como padrão do restante do estágio atual.
USER node
WORKDIR
Instrução que declara o diretório de trabalho para as instruções RUN, CMD, ENTRYPOINT, COPY e ADD.
WORKDIR /path/to/workdir
ENTRYPOINT
Define o comando de entrada do container executável.
ENTRYPOINT ["npm", "run", "dev"]
ONBUILD
Instruções a serem executadas quando a imagem é usada de base para outro build.
ONBUILD ADD . /app/srcONBUILD RUN /usr/local/bin/python-build --dir /app/src
STOPSIGNAL
Altera o sinal de parada padrão do docker.
STOPSIGNAL signal
HEALTHCHECK
Instrução que diz ao docker como testar se o container ainda está funcional.
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
SHELL
Instrução permite alterar o shell padrão usado para rodar os comandos.
SHELL ["powershell", "-command"]
Subindo uma imagem no docker hub?
- Crie sua conta no Docker Hub

- Use o comando abaixo para logar
docker login -u [username]
- Crie uma imagem com o nome concatenando o username e o nome da imagem separados por ”/” [username]/[imagename]
docker build username/imagename:1.0.0
- Execute o comando de publicação
docker push username/imagename:1.0.0