diff --git a/source/pages/guides/docker-fundamentals.md b/source/pages/guides/docker-fundamentals.md index 6623b8e7eda970a62a8a9e06507825c0a8bcbf43..aad5bf3e223f9519358704d0889537aadad9a616 100644 --- a/source/pages/guides/docker-fundamentals.md +++ b/source/pages/guides/docker-fundamentals.md @@ -402,6 +402,8 @@ CMD [ "npm", "start" ] Sumarizando (veremos cada comando em detalhes à frente), +TODO: terminar aqui + :::{caution} A imagem escolhida é `node:lts`. Para usos além de testes locais é sempre bom mudar a tag `lts` para uma versão específica da imagem. @@ -485,7 +487,11 @@ Um pouco sobre o buildx será comentado na seção [Docker Compose](docker-compo Vamos analisar esse output: -............................................................................ +1. A mensagem `DEPRECATED`: +2. `Sending build context to Docker daemon`: +3. Os `STEP`s: +4. `Successfully built` e `tagged`: +TODO: terminar aqui Com isso devemos ter uma imagem local chamada `teste-node`. Podemos verificar isso com `docker image ls`: @@ -569,6 +575,12 @@ Para parar esse contêiner é só rodar `docker stop <identificador>` em outro terminal. #### Mapeando portas +:::{note} +É esperado que o leitor tenha algum conhecimento de redes, em particular do +conceito de 'portas', TCP e UDP idealmente. + +Ainda, é interessante ter conhecimento dos comandos `netstat` e `ss`. +::: 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 @@ -590,148 +602,79 @@ 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`. +para o host. Essa flag é `--publish <PORTA_HOST>:<PORTA_CONTAINER>`. O `--publish` +pode ser abreviado para `-p`. Vejamos um exemplo: ``` -``` +root@devops:~/node-test# docker run --rm -p 3000:3000 --name meu-container teste-node -Agora +> docker-tutorial@1.0.0 start +> node app.js +Escutando na porta 3000 ``` -``` - -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 -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. - -###### O Dockerfile fornecido -Para que saber isso? Simples. O Dockerfile fornecido logo acima não necessariamente -o ideal. Por quê? Pois a instrução `COPY . /app/` vem antes da `RUN npm install`. -Isso implica em sempre que o código for modificado e a imagem for reconstruída o -Docker vai re-executar o `npm install`, que no geral é bem demorado. - -Faça um teste: modifique a seguinte linha de código do arquivo `app.js`: - -```javascript - const text = `O contador eh ${counter}`; +Nada de diferente no output, mas se você verificar com `netstat -tnlp`, em +algum lugar do output linhas similares às seguintes devem estar presentes: ``` - -Para algo como: - -```javascript - const text = `Contador = ${counter}`; +tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN - +tcp6 0 0 :::3000 :::* LISTEN - ``` -Depois disso execute `docker build . -t <nome-para-imagem>` de novo. O output deve -ser similar ao seguinte: +Por fim, basta fazer operações como +[anteriormente](#executando-o-programa-localmente), e verifica-se que o +resultado é o mesmo. ``` -root@devops:~/node-test# docker build . -t teste-node -DEPRECATED: The legacy builder is deprecated and will be removed in a future release. - Install the buildx component to build images with BuildKit: - https://docs.docker.com/go/buildx/ - -Sending build context to Docker daemon 2.651MB -Step 1/7 : FROM node:lts - ---> 2e805f601f2b -Step 2/7 : WORKDIR /app/ - ---> Running in 5aa80a980286 - ---> Removed intermediate container 5aa80a980286 - ---> aa3ebb863e52 -Step 3/7 : EXPOSE 3000 - ---> Running in f67d61f55aec - ---> Removed intermediate container f67d61f55aec - ---> dcec86fcce1a -Step 4/7 : COPY package.json /app/package.json - ---> 9967b38a43c7 -Step 5/7 : RUN npm install - ---> Running in 88bad8fe183f - -added 64 packages, and audited 65 packages in 2s - -12 packages are looking for funding - run `npm fund` for details - -found 0 vulnerabilities -npm notice -npm notice New minor version of npm available! 10.2.4 -> 10.5.0 -npm notice Changelog: <https://github.com/npm/cli/releases/tag/v10.5.0> -npm notice Run `npm install -g npm@10.5.0` to update! -npm notice - ---> Removed intermediate container 88bad8fe183f - ---> ee748f133f4b -Step 6/7 : COPY . /app/ - ---> bc09849bf32c -Step 7/7 : CMD [ "npm", "start" ] - ---> Running in ba583883c65f - ---> Removed intermediate container ba583883c65f - ---> 86f79ca5082a -Successfully built 86f79ca5082a -Successfully tagged teste-node:latest -root@devops:~/node-test# +root@devops: ~/node-test# curl -w '\n' localhost:3000/ler +{"texto":"O arquivo nao foi modificado!","contador":0} +root@devops: ~/node-test# ``` -Perceba que ........................... - -Vamos agora mudar a ordem das camadas no Dockerfile: - -```Dockerfile -FROM node:lts - -WORKDIR /app/ +E ou output no terminal do servidor deve ser: -COPY package.json /app/package.json +``` +Escutando na porta 3000 +[LEITURA] contador eh 0 +``` -EXPOSE 3000 +Pronto! Conseguimos criar uma imagem Docker para uma aplicação NodeJS! -COPY . /app/ +Entretanto, antes de vermos como melhorar a interação com os contêineres +vamos dar uma olhada em alguns detalhes que deixamos passar. -RUN npm install +##### Ordenando as camadas +Você deve ter percebido já que as camadas de um `Dockerfile` são sequenciais, +executadas 'de cima para baixo'. -CMD [ "npm", "start" ] -``` +Não só isso, se você já tem certa experiência com Docker ou brincou bastante +com o exemplo fornecido anteriormente deve ter percebido que nem todas as +camadas da imagem são refeitas durante um `build`. -Faremos o primeiro `build`. Ele servirá para termos a base. No output você deve -perceber que tudo desde ls .......................... -TODO: o resto +Isso é uma questão de otimização. Não é necessário refazer uma camada se as +dependências dela não foram modificadas. -:::{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. +Mas há um porém: Toda camada depende das anteriores, portanto se você colocar +uma camada pesada, como um `npm install` depois de outra que será modificada +bastante mas não fizer diferença, você pode deixar o `npm install` antes. -> 'Ah... mas se no final o efeito é o mesmo, só não é tão eficiente, então não -> faz diferença'. +Um exemplo disso é a ordenação `COPY . /app/` e `RUN npm install`. Quando se trabalha +com código os arquivos que serão copiados vão sempre mudar, pelo menos alguns, mas +nem sempre as dependências que serão instaladas foram modificadas. Portanto o ideal +para um projeto NodeJS é que `COPY. /app/` seja feito depois de `RUN npm install`. -Vai achar o que fazer, vai. +:::{admonition} **Docker build cache** +:class: seealso +Para ver em detalhes como é feito o cache de camadas do Docker na hora do +`build` dê uma olhada na documentação oficial[^cite_docker_cache]. ::: #### ARG e ENV +TODO: :) #### COPY e RUN -TODO: eventualmente comentar do .dockerignore :::{tip} Vamos supor que você só precisa de um pequeno conjunto de seus arquivos @@ -744,13 +687,19 @@ cada um dos arquivos necessários, ou diretórios se tudo neles for necessário. Se você já tem familiaridade com o Git provavelmente conhece o arquivo `.gitignore`. Com docker existe o arquivo `.dockerignore` para arquivos -não serem copiados com a instrução `COPY`. +não serem copiados com a instrução `COPY` + +Veja mais sobre `.dockerignore` na documentação oficial[^cite_dockerignore]. ::: #### CMD vs ENTRYPOINT :::{seealso} -TODO: Uma instrução particularmente interessante é a `HEALTHCHECK`. +A documentação oficial de Docker tem todas as instruções aceitas pelo +Dockerfile[^cite_dockerfile]. Uma instrução particularmente interessante é a +`HEALTHCHECK`. + +Vale a pena estudar a fundo como são feitas imagens para seus fins específicos. ::: ### Interagindo com contêineres @@ -766,6 +715,10 @@ TODO: Uma instrução particularmente interessante é a `HEALTHCHECK`. #### Bind Mounts ## Uma introdução às **redes** +6 tipos de rede lesgoooooo (ou 7, a default tem gente que diz que eh diferente) + +## Docker plugins +TODO: compose e buildx entram aqui ## Docker Compose Como orquestrar múltiplos contêineres elegantemente? @@ -810,7 +763,7 @@ não há por que mexer ninguém irá mexer. ::: ### O arquivo `docker-compose.yml` -Aqui vamos longe. +TODO: Aqui vamos longe. ### Por que agora? Por que ver toda a parte difícil antes de `compose`? @@ -848,16 +801,8 @@ qualquer *merge* na branch `main`, por exemplo. ## TODO: Fernando comentou sobre docker debian12 em host debian9 -> estudar -## TODO: Colinha de Docker -- `docker run <nome-da-imagem>:<tag>`: Cria e executa um contêiner com base na imagem com - versão especificada pela *tag*. -- `docker pull <nome-da-imagem>:<tag>`: Faz *download* da imagem especificada - com a versão da *tag*. -- `docker ps`: Lista contêineres em execução. -- `docker ps -a`: Lista todos os contêineres na máquina (tanto parados quanto - em execução). -- `docker ps -q`: Lista IDs dos contêineres em execução. -- `docker stop $(docker ps -q)`: Para **todos** os contêineres em execução. +## TODO: Pesquisando por conta +... [^cite_docker_concepts]: [Conceitos básicos de Docker](../concepts/docker.md). @@ -867,3 +812,6 @@ qualquer *merge* na branch `main`, por exemplo. [^cite_docker_hub]: [DockerHub](https://hub.docker.com/). [^cite_expose]: [Instrução EXPOSE](https://docs.docker.com/reference/dockerfile/#expose). [^cite_lts]: [Long Term Support](https://en.wikipedia.org/wiki/Long-term_support). +[^cite_docker_cache]: [Docker build cache](https://docs.docker.com/build/cache/). +[^cite_dockerignore]: [Arquivos `.dockerignore`](https://docs.docker.com/build/building/context/#dockerignore-files). +[^cite_dockerfile]: [Referência Dockerfile](https://docs.docker.com/reference/dockerfile/).