Clone esse repositório do GitHub para acompanhar os slides e executar os scripts que serão demonstrados
$ git clone --recurse-sobmodules \
git@github.com:vcampitelli/workshop-containers.git
Instalando as ferramentas necessárias da linguagem direto em nossa máquina (exemplo: PHP, Java), as dependências envolvidas (bibliotecas e ferramentas) e suas configurações
Problemas:
Uma máquina virtual ou virtual machine (VM) é um ambiente virtualizado que funciona como um sistema de computação com sua própria CPU, memória, interface de rede e armazenamento. Um software chamado hipervisor separa do hardware os recursos utilizados pela máquina virtual e os provisiona adequadamente.Red Hat
A máquina física onde o hipervisor está instalado é chamada de host. As VMs que usam os recursos da máquina host são chamadas de guest. O hipervisor trata os recursos de computação (por exemplo, CPU, memória e armazenamento) como um pool que pode ser realocado com facilidade entre os guests existentes ou para novas máquinas virtuais.Red Hat
As máquinas virtuais são isoladas do restante do sistema, e várias delas podem coexistir em um único hardware, como um servidor. Dependendo da demanda, é possível migrá-las entre servidores host ou distribuir os recursos de maneira mais eficiente.Red Hat
Vantagens:
Problemas:
Os contêineres são unidades executáveis de software nas quais o código do aplicativo é empacotado, junto às suas bibliotecas e dependências, de maneira semelhante para que possa ser executado em qualquer lugar, seja no desktop, na estrutura de TI tradicional ou na cloud.IBM
Para isso, os contêineres utilizam um tipo de virtualização de sistema operacional (S.O.) na qual os recursos do S.O. (no caso do kernel do Linux, os namespaces e as primitivas de cgroups) são usados para ambos os processos isolados a fim de controlar a quantia de CPU, de memória e de disco à qual esses processos têm acesso.IBM
Lançado em agosto de 2008, Linux Containers (LXC) é um método de virtualização em nível de sistema operacional para executar vários sistemas Linux isolados (containers) em um host de controle usando um único kernel Linux.Wikipédia
Vantagens:
Problemas:
Docker is an open platform for developing, shipping, and running applications.docs.docker.com
Lançado em 2013, o Docker é uma plataforma completa para criação e gerenciamento de containers, criando abstrações dos recursos físicos do hardware para melhor compartilhamento e execução em ambientes distintos
Template com instruções para criar um container
Arquivo fonte para gerar uma imagem
Mecanismo para realizar a persistência de dados em um container
docs.docker.comRepositório que contém as imagens disponíveis para serem executadas
Quando criamos um container, especificamos a imagem para execução para que o Docker possa buscá-la nesse repositório
O registry oficial de imagens Docker é o Docker Hub, que é gratuito para repositórios públicos e possui planos pagos caso você queira hospedar imagens privadas
Existem imagens de Sistemas Operacionais, como Debian e Ubuntu, e das principais aplicações já instaladas, como MySQL e OpenJDK, que geralmente possuem versões para Sistemas Operacionais diferentes
Também é possível criar seu próprio registry (por exemplo, na rede de sua empresa) ou usar o serviço do seu provedor de Cloud, como:
docker ps
Lista os containers que estão em execução
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Informe o parâmetro -a
para listar todos os containers, inclusive os
parados
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd954dec23d0 hello-world "/hello" 11 minutes ago Exited (0) 11 minutes ago frosty_nightingale
docs.docker.com
docker run
Cria um container a partir da imagem especificada, executa o comando passado (ou o padrão da imagem) e para o container após o término do comando
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
docs.docker.com
docker run
Cria um container a partir da imagem especificada, executa o comando passado (ou o padrão da imagem) e para o container após o término do comando
$ docker run debian cat /etc/debian_version
11.6
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docs.docker.com
docker run
Após o término da execução, o container ficará parado, podendo ser visto ao
executar docker ps -a
e até mesmo reiniciado
Se quiser executar o comando do container e exclui-lo automaticamente ao final,
informe o parâmetro --rm
:
$ docker run --rm hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
docs.docker.com
docker run
Para manter o container rodando, você pode:
1. Executar tail -f /dev/null
passando o parâmetro -d
, que irá
executar o container em segundo plano e imprimir o ID criado
$ docker run -d debian tail -f /dev/null
4c5a4daf08e6ea1d9f80f8a95c52e0920b635e1497b906ec2f0f9fde36d45935
docs.docker.com
docker run
Para manter o container rodando, você pode:
2. Executar sleep infinity
passando o parâmetro -d
, que irá
executar o container em segundo plano e imprimir o ID criado (método
recomendado)
$ docker run -d debian sleep infinity
d27d85ce24d64a684468fc6b34a8c97c0f95b66a112a96e0ae5b5a0d9dcbfacb
docs.docker.com
docker run
Cada vez que um container é criado, o Docker irá gerar um nome aleatório para ele
(exemplo: frosty_nightingale
)
Para definir o nome do seu container, informe o parâmetro --name
:
$ docker run --name meu-nome hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53eb65021715 hello-world "/hello" 19 seconds ago Exited (0) 19 seconds ago meu-nome
docs.docker.com
docker run
Para disponibilizar um arquivo ou diretório dentro do container, devemos montar um
volume informando o parâmetro --volume
(ou -v
)
Esse argumento recebe basicamente dois argumentos separados por um dois-pontos: o diretório no host que você deseja montar e o caminho no container em que ele será disponibilizado
docker run
Para montar a pasta pessoal de seu usuário em um diretório /app
no
container, você pode executar:
$ docker run -it -v ~/:/app debian bash
root@abb014aeb5ae:/# ls -l /app
total 760140
drwxr-xr-x 2 1000 1000 4096 Jun 16 2021 Audio
drwxr-xr-x 2 1000 1000 4096 Jun 16 2021 Desktop
...
docs.docker.com
docker run
Se seu container possui um serviço que escuta alguma porta, você deve utilizar o
parâmetro --expose
(ou -p
) para mapear aquela porta para uma em
sua própria máquina
Para mapear a porta 80 do container à 8080 da sua máquina, execute:
$ docker run -d -p 8080:80 nginx:alpine
Sem esse mapeamento, você só conseguiria acessar esse serviço pelo IP interno do
container, que pode ser descoberto com
docker inspect <nome-do-container>
docker images
Lista as imagens disponíveis localmente, que são as "receitas" utilizadas para configurar containers
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
php 8.2-cli 56b3ddeba8af 3 weeks ago 92.1MB
node 18 c4f3fb5f722f 4 weeks ago 172MB
debian latest 4eacea30377a 5 weeks ago 124MB
docs.docker.com
docker build
Cria uma nova imagem a partir das informações provenientes do Dockerfile
(que iremos ver em breve)
$ docker build .
Sending build context to Docker daemon 105kB
Step 1/5 : FROM node:18-alpine
---> c4f3fb5f722f
Step 2/5 : WORKDIR /app
---> c1829ed5a713
Step 3/5 : COPY . .
---> 6e8d941cebb3
Step 4/5 : RUN npm install
---> Running in eb7561cda394
Removing intermediate container eb7561cda394
---> 18d0cbbb1c07
---> d59ad3ba42d0
Step 6/5 : CMD ["npm", "start"]
---> Running in c4b0e26044a1
Removing intermediate container c4b0e26044a1
---> df6a836541d6
Successfully built df6a836541d6
docs.docker.com
docker build
No exemplo anterior, a imagem df6a836541d6
foi criada, o que é uma
identificação não muito usável para um ser humano
Nesses casos, podemos criar uma tag para aquela imagem, dando um nome mais significativo a ela:
$ docker build -t nome-da-imagem:versao .
Para criar uma tag em uma imagem já existente, use o comando:
$ docker image tag df6a836541d6 nome-da-imagem:versao
docs.docker.com
docker start
Inicializa o container especificado, executando o mesmo comando com que ele foi criado
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd954dec23d0 hello-world "/hello" 11 minutes ago Exited (0) 11 minutes ago helloworld
$ docker start -i helloworld
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
docs.docker.com
docker stop
Para o container especificado, primeiro enviando o sinal SIGTERM
para que
ele possa finalizar seu processamento atual e, após 10 segundos, um sinal SIGKILL
para forçar a parada
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0808f1377a11 debian "sleep infinity" 16 minutes ago Up 16 minutes meu-container
$ docker stop -t 1 meu-container
meu-container
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docs.docker.com
•
signal(7) — Linux manual page
docker rm
Remove um ou mais containers, opcionalmente forçando a parada se especificado o
parâmetro -f
e também seus volumes ao passar -v
$ docker rm meu-container
Error response from daemon: You cannot remove a running container 0808f1377a11b7a9287593eb0e3319ff69b81b7c9be2ab1f6ed312131ea3cffa. Stop the container before attempting removal or force remove
$ docker rm -fv meu-container
meu-container
docs.docker.com
docker rmi
Remove uma ou mais imagens, opcionalmente forçando a remoção de imagens que estão em uso por
algum container se especificado o parâmetro -f
$ docker rmi df6a836541d6
Deleted: sha256:df6a836541d6da56a0678c439fbbb514fa443ccf6f9d83f56459320d5a064852
Deleted: sha256:d59ad3ba42d0738624804c0ac1b1240ca6868af8d487806e287336a829b5f702
Deleted: sha256:18d0cbbb1c0799afa06659260338f301157a7cf80748b81840340f910ef951c5
Deleted: sha256:eed0b1938739c1b4457b925121fef64622b3425b38b507760c20c0b3f399685a
Deleted: sha256:6e8d941cebb35ca2e56e7ebb89298b2a5716d838b9fbaee3b7e6d70eef6f2891
Deleted: sha256:3cfa372ac00348475b481d88a0b7647df6a41cd50e16ce43047d40f05b97ada4
$ docker rmi debian:latest
Error response from daemon: conflict: unable to remove repository reference "debian:latest" (must force) - container 0808f1377a11 is using its referenced image d2780094a226
$ docker rmi -f debian:latest
Untagged: debian:latest
Untagged: debian@sha256:859ea45db307402ee024b153c7a63ad4888eb4751921abbef68679fc73c4c739
docs.docker.com
docker exec
Executa o comando no container especificado, podendo receber também alguns dos
parâmetros do docker run
, como -d
para rodar em segundo plano,
-i
para ler as entradas do STDIN
e -t
para alocar um
pseudo-tty
$ docker exec meu-container cat /etc/debian_version
11.6
$ docker exec -it meu-container bash
root@0808f1377a11:/#
docs.docker.com
Arquivo com um conjunto de instruções para que o Docker possa fazer o build da imagem, sendo basicamente composto por:
debian:11
php -S 0.0.0.0:80 -t public/
FROM <imagem>
Define a imagem que servirá de base para seu ambiente
Exemplos:
FROM debian:11
# ou
FROM php:8.2-cli-alpine
WORKDIR /pasta/raiz
Caminho base onde as operações seguintes irão executar, que será automaticamente criado se não existir
Exemplos:
# Todos os comandos a seguir serão executados em /app
WORKDIR /app
COPY <fonte> <destino>
Copia o arquivo (ou a pasta) da fonte para o destino
Exemplos:
COPY . ./
COPY arquivo.conf /etc/
COPY arquivo1 arquivo2 arquivo3 /destino/
RUN <comando-a-ser-executado>
Comandos de configuração do ambiente
Exemplos:
RUN apt-get update && apt-get install -y php8.2-xml
RUN composer install
EXPOSE <porta>
Porta(s) que seu container escuta com caráter informativo para quem está lendo o arquivo, já que não resulta em ações pelo Docker
Exemplo:
EXPOSE 80 443
CMD [<comando>, <argumento>, <argumento>]
Comando principal a ser executado ao iniciar o container, só podendo
existir um por Dockerfile
, onde o <comando>
deve ser um caminho
para um executável
Exemplo:
CMD ["composer", "start"]
# ou
CMD php -S 0.0.0.0:80 -t public/
CMD [<argumento-para-o-entrypoint>, <argumento-para-o-entrypoint>]
Nesse formato, em que o primeiro parâmetro do CMD
não é um executável, o Docker
assume que a lista inteira é composta de argumentos que serão passados para o
entrypoint (que veremos a seguir)
Exemplo:
CMD ["start"]
ENTRYPOINT <comando-principal>
Executável principal que irá receber o comando do CMD
ou o informado
pelo docker run
O padrão é /bin/sh -c
, significando que ao passar um comando
php
, por exemplo, será executado /bin/sh -c php
Exemplo:
ENTRYPOINT ["/usr/local/bin/meu-entrypoint.sh"]
Exemplo de um Dockerfile
simples
# Imagem base
FROM php:8.2-cli-alpine
# Diretório raiz da aplicação
WORKDIR /app
# Copiando todos os arquivos do contexto para /app
COPY . ./
# Instalando dependências
RUN apt-get update && \
apt-get -y install php8.2-xml && \
composer install
# Informando o parâmetro padrão para o entrypoint
CMD ["composer", "start"]
As instruções RUN
, COPY
e ADD
criam layers e
as outras criam apenas imagens temporárias, não aumentando o tamanho do build.
Ao gerar um container, uma layer escrevível é criada, recebendo todas as modificações no sistema de arquivos.
docs.docker.com
Se possível, combine comandos em instruções RUN
em uma só:
RUN apt-get update
RUN apt-get install php8.2-pdo
RUN composer install
Irá criar 3 layers
RUN apt-get update && \
apt-get install php8.2-pdo && \
composer install
Irá criar 1 layer
Ferramenta utilizada para gerenciar containers, geralmente em cenários que a aplicação é constituída por sistemas diferentes (como banco de dados e aplicação)
docs.docker.comTambém é útil para configurar políticas de reinicialização caso haja algum erro, facilitar a montagem de volumes, publicação de portas e dependências entre containers (por exemplo, que a aplicação deve aguardar o banco de dados ficar disponível primeiro)
docs.docker.comApesar de ser possível utilizá-lo em ambientes de produção, não é recomendável em situações com grandes necessidades de escala, sendo preferível usar soluções como Kubernetes ou, se estiver rodando em cloud, as próprias soluções disponíveis nela, como o Amazon ECS
docs.docker.com
Sua configuração é feita através de um arquivo compose.yaml
, como o do
exemplo a seguir, que gerencia um container com uma aplicação em PHP e outro com um
banco de dados MySQL:
services:
# Aplicação
app:
image: php:8.2-cli-alpine
working_dir: /app
volumes:
- ./backend:/app
env_file:
- .env
depends_on:
- db
ports:
- "8080:8080"
# Banco de Dados
db:
image: mariadb:10
volumes:
- dbVolume:/var/lib/mysql
env_file:
- db.env
volumes:
dbVolume:
driver: local
compose.yaml
docs.docker.com/compose
Os comandos são executados como docker compose [comando]
e devem ser executados
dentro da pasta onde o arquivo compose.yaml
se encontra
Para executar de outra pasta, você pode fornecer o caminho para o arquivo .yml
com docker compose -f /caminho/para/o/compose.yaml [comando]
A versão 1 do Docker Compose utilizava um utilitário separado, então era preciso baixá-lo e
executar docker-compose [comando]
A versão 2 transformou-o em um plugin embutido no binário, sendo acessível pelo subcomando
docker compose
Inicializar serviços em primeiro plano:
docker compose up
Inicializar serviços em segundo plano:
docker compose up -d
Parar serviços:
docker compose stop
Verificar o estado dos serviços:
docker compose ps
Executar o comando em um serviço:
docker compose exec <serviço> <commando>
Acompanhar os logs:
docker compose logs -f <serviço>