Skip to content
Snippets Groups Projects
Commit fb9ff3d6 authored by MarcusVRP's avatar MarcusVRP
Browse files

feat(docker-fundamentals): im tired


Signed-off-by: default avatarMarcus V. <mvrp21@inf.ufpr.br>
parent 8c3ea57f
No related branches found
No related tags found
No related merge requests found
# Fundamentos do Docker
TODO: rever tudo com calma, acho que usei um monte de terminologias que não são
as 'oficiais' e que tirei da cabeça.
Assume-se que quem ler essa documentação é familiarizado com os conceitos
básicos de Docker[^cite_docker_concepts].
......@@ -337,6 +340,11 @@ root@devops:~/node-test#
O terminal acima é o que chamamos de 'cliente'.
:::{note}
Você pode acessar essas URLs no navegador ao invés de usar curl no terminal.
Mas não tem tanta graça ;)
:::
Voltando ao primeiro terminal, o output deve ser similar a esse:
```
......@@ -469,7 +477,7 @@ Um pouco sobre o buildx será comentado na seção [Docker Compose](docker-compo
Vamos analisar esse output:
TODO: analisar o output asjkdajksdjkasjkd.
............................................................................
Com isso devemos ter uma imagem local chamada `teste-node`. Podemos verificar isso
com `docker image ls`:
......@@ -481,11 +489,58 @@ teste-node latest 094c7152f58d 15 minutes ago 1.11GB
root@devops:~/node-test#
```
##### Criando o contêiner
Do mesmo jeito que criamos e executamos contêineres antes faremos agora, mas
passaremos mais argumentos para o comando pois eles ainda não foram demonstrados:
##### Criando e usando o contêiner
TODO: falar de `docker container create` e etc.
Para criar um contêiner com base em uma imagem sem executá-lo imediatamente
existe o comando `docker container create <imagem>`, e sua versão curta:
`docker create <imagem>`.
```
root@devops:~/node-test# docker create --name nome-legal teste-node
```
No caso acima também escolhemos um nome para o contêiner com `--name`, mas
esse argumento não é necessário para o comando. Podemos ver esse contêiner
com `docker ps -a`:
```
root@devops:~/node-test# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa97dfc3c078 teste-node "docker-entrypoint.s…" 10 minutes ago Created nome-legal
root@devops:~/node-test#
```
Como colocá-lo em execução?
Qualquer contêiner que estiver parado pode ser iniciado com o comando `docker
start <identificador>`:
```
root@devops:~/node-test# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa97dfc3c078 teste-node "docker-entrypoint.s…" 26 minutes ago Created nome-legal
root@devops:~/node-test# docker start nome-legal
nome-legal
root@devops:~/node-test# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa97dfc3c078 teste-node "docker-entrypoint.s…" 26 minutes ago Up 1 second 3000/tcp nome-legal
root@devops:~/node-test#
```
:::{admonition} Socorro! Não consigo dar `Ctrl + C`!!!
:class: danger
Sim, por padrão seu terminal ficará preso aos logs do contêiner. Veremos logo à
frente como mudar esse comportamento.
Em outro terminal você deve executar `docker stop <identificador>`. Pode levar
uns segundos mas o contêiner vai parar e seu terminal será devolvido.
:::
###### Fazendo como antes
Também é possível executar contêineres do mesmo jeito de antes. Dessa vez
passaremos mais argumentos para o comando pois eles ainda não foram
demonstrados:
```
root@devops:~/node-test# docker run --rm --name meu-container teste-node
......@@ -502,11 +557,21 @@ contêiner e `--name` para que o nome do contêiner seja um criado por nós, nã
um escolhido pelo Docker.
:::
...
Para parar esse contêiner é só rodar `docker stop <identificador>` em outro
terminal.
#### Mapeando portas
:::{attention}
Se você é curioso e já sabe como o programa deveria funcionar, deve ter
percebido que acessar `localhost:3000/ler` ou `localhost:3000/escrever` não
funciona. Isso pois a porta está aberta no contêiner, mas não no host.
Na verdade, podemos ver quais portas estão sendo utilizadas no sistema com
`netstat -tnlp`. A menos que outro programa esteja utilizando a porta 3000
não deve haver nenhuma linha do output com a porta 3000.
:::{admonition} Mas e a instrução `EXPOSE` que vimos antes?
:class: attention
A instrução `EXPOSE <PORTA>`[^cite_expose] **não expõe** de verdade as portas,
isso pois por mais que uma porta seja utilizada no contêiner o host pode querer
mapeá-la para outra.
......@@ -516,8 +581,62 @@ utilizando a imagem quais portas devem ser 'publicadas'. Ela serve como uma
espécie de **documentação**.
:::
O que precisamos é passar um argumento ou flag para mapear a porta do contêiner
para o host. Essa flag é `--port <PORTAHOST>:<PORTACONTAINER>`. O `--port` pode
ser abreviado para `-p`.
Vejamos um exemplo:
```
```
Agora
```
```
Pronto! Conseguimos criar uma imagem Docker para uma aplicação NodeJS!
Entretanto, antes de vermos como melhorar a interação com os contêineres
vamos dar uma olhada em alguns detalhes que deixamos passar.
##### Ordenando as camadas
TODO: mostrar trocas de camadas
TODO: MUCHO TEXTO. Tem que ter um subway surfers e mostrar 4 palavras por
vez pras pessoas acompanharem.
Talvez você já tenha criado o mesmo contêiner mais de uma vez e percebeu no
output que o Docker é 'inteligente'. Ele não perderá tempo refazendo passos,
afinal isso não é eficiente.
Uma camada de uma imagem pode depender de algo. Por exemplo uma camada que se
refere a uma instrução `COPY` depende dos arquivos que serão copiados. Se nenhum
arquivo for modificado então o contêiner criado com aquela imagem já tem os
arquivos necessários, logo não há porque fazer a cópia.
Entretanto, caso um arquivo seja modificado a instrução `COPY` deve executar
de novo, naturalmente.
O que isso implica nas demais camadas? Por questões de simplificação **todas**
as camadas **após** a camada que foi alterada (ou teve dependências alteradas).
Assim não é necessário ficar buscando dependências entre camadas, e a ordenação
ideal delas fica a encargo do usuário.
Para que saber isso? Simples. O Dockerfile fornecido logo acima não necessariamente
o ideal. Por quê? Pois a instrução `EXPOSE`
........................................................ to achando q o exemplo do expose n é dos melhores
:::{admonition} No fim das contas o resultado é o mesmo.
Mudar isso não altera o contêiner final, apenas pode acelerar o `build` em casos
que essa ordenação.
> 'Ah... mas se no final o efeito é o mesmo, só não é tão eficiente, então não
> faz diferença'.
Vai achar o que fazer, vai.
:::
#### ARG e ENV
#### COPY e RUN
......@@ -525,8 +644,8 @@ TODO: eventualmente comentar do .dockerignore
#### CMD vs ENTRYPOINT
:::{note}
Uma instrução particularmente interessante é a `HEALTHCHECK`.
:::{seealso}
TODO: Uma instrução particularmente interessante é a `HEALTHCHECK`.
:::
### Interagindo com contêineres
......@@ -534,9 +653,12 @@ Uma instrução particularmente interessante é a `HEALTHCHECK`.
#### Vendo Logs
#### Utilizando `docker exec`
## Disco persistente com **volumes**
### Tipos de volumes
#### Bind Mounts
## Uma introdução às **redes**
......@@ -544,7 +666,7 @@ Uma instrução particularmente interessante é a `HEALTHCHECK`.
Como orquestrar múltiplos contêineres elegantemente?
Vamos supor que desejamos executar aquele mesmo contêiner com base na imagem do
Dockerfile que foi criado logo acima. Seria necessária a seguinte sequência de
Dockerfile que foi criado logo acima. Seria necessára a seguinte sequência de
comandos longos:
```
......@@ -564,15 +686,44 @@ compose`.
docker-compose vs. docker compose
:::
### `docker-compose.yml`
...
Na verdade, mesmo com um único contêiner, para o caso de uso para os projetos do
C3SL ainda é melhor usar `compose`. Isso pois ele é mais simples de executar, tem
um arquivo de configuração descritivo e no geral facilita a vida de quem usa.
:::{attention}
O problema com isso é que geralmente uma única pessoa aprende o suficiente de
Docker para fazer essa configuração inicial, e depois todos aceitam que funciona
e usam, mas eventualmente quem fez e conhece Docker sai.
Um dia algum problema surge, com ele a necessidade de mexer no Dockerfile ou no
docker-compose.yml, e muito tempo é perdido tentando arrumar algo que deveria
facilitaria o trabalho caso todos conhecessem.
Isso não é problema com Docker em si, mas sim com não conhecer uma tecnologia
essencial para o projeto. O que é relativamente compreensível, se funciona e
não há por que mexer ninguém irá mexer.
:::
### O arquivo `docker-compose.yml`
Aqui vamos longe;
### Por que agora?
Por que ver toda a parte difícil antes de `compose`?
Para entender como ele funciona, por que ele existe e o que acontece por
debaixo dos panos. Além disso saber `compose` não exclui a necessidade de saber
o 'docker puro'.
Por exemplo, se você tem uma aplicação com vários contêineres e precisa atualizar
algo dentro de um deles, você (idealmente) não vai parar todos os outros com
`docker compose down`, mas vai parar apenas o necessário com `docker stop`.
## TODO: Utilizando um registry
Falar de `pull`, `login`, `push` e etc.
## Exemplo de *deploy* manual
TODO: fazer o exemplo
TODO: fazer o exemplo (quadro de avisos????)
:::{admonition} Esse não é necessariamente o melhor método.
:class: note
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment