diff --git a/source/pages/guides/docker-fundamentals.md b/source/pages/guides/docker-fundamentals.md index c55873adf7b0e89473f88053b787d7ffb3d8c4c2..5b096623ecef25a7de5af557b103fde65542fed5 100644 --- a/source/pages/guides/docker-fundamentals.md +++ b/source/pages/guides/docker-fundamentals.md @@ -1,5 +1,8 @@ # 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 + +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 -TODO: falar de `docker container create` e etc. +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