Skip to content
Snippets Groups Projects
Commit 256f9636 authored by mvrp21's avatar mvrp21
Browse files

chore(docker-fundamentals): rework build cache section


Signed-off-by: default avatarMarcus V. <mvrp21@inf.ufpr.br>
parent 3c219cf5
Branches
Tags
No related merge requests found
...@@ -402,6 +402,8 @@ CMD [ "npm", "start" ] ...@@ -402,6 +402,8 @@ CMD [ "npm", "start" ]
Sumarizando (veremos cada comando em detalhes à frente), Sumarizando (veremos cada comando em detalhes à frente),
TODO: terminar aqui
:::{caution} :::{caution}
A imagem escolhida é `node:lts`. Para usos além de testes locais é sempre bom 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. 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 ...@@ -485,7 +487,11 @@ Um pouco sobre o buildx será comentado na seção [Docker Compose](docker-compo
Vamos analisar esse output: 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 isso devemos ter uma imagem local chamada `teste-node`. Podemos verificar isso
com `docker image ls`: com `docker image ls`:
...@@ -569,6 +575,12 @@ Para parar esse contêiner é só rodar `docker stop <identificador>` em outro ...@@ -569,6 +575,12 @@ Para parar esse contêiner é só rodar `docker stop <identificador>` em outro
terminal. terminal.
#### Mapeando portas #### 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 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 percebido que acessar `localhost:3000/ler` ou `localhost:3000/escrever` não
...@@ -590,148 +602,79 @@ espécie de **documentaçã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 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 para o host. Essa flag é `--publish <PORTA_HOST>:<PORTA_CONTAINER>`. O `--publish`
ser abreviado para `-p`. pode ser abreviado para `-p`.
Vejamos um exemplo: 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 Nada de diferente no output, mas se você verificar com `netstat -tnlp`, em
Para que saber isso? Simples. O Dockerfile fornecido logo acima não necessariamente algum lugar do output linhas similares às seguintes devem estar presentes:
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}`;
``` ```
tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN -
Para algo como: tcp6 0 0 :::3000 :::* LISTEN -
```javascript
const text = `Contador = ${counter}`;
``` ```
Depois disso execute `docker build . -t <nome-para-imagem>` de novo. O output deve Por fim, basta fazer operações como
ser similar ao seguinte: [anteriormente](#executando-o-programa-localmente), e verifica-se que o
resultado é o mesmo.
``` ```
root@devops:~/node-test# docker build . -t teste-node root@devops: ~/node-test# curl -w '\n' localhost:3000/ler
DEPRECATED: The legacy builder is deprecated and will be removed in a future release. {"texto":"O arquivo nao foi modificado!","contador":0}
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#
``` ```
Perceba que ........................... E ou output no terminal do servidor deve ser:
Vamos agora mudar a ordem das camadas no Dockerfile:
```Dockerfile
FROM node:lts
WORKDIR /app/
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 Isso é uma questão de otimização. Não é necessário refazer uma camada se as
perceber que tudo desde ls .......................... dependências dela não foram modificadas.
TODO: o resto
:::{admonition} No fim das contas o resultado é o mesmo. Mas há um porém: Toda camada depende das anteriores, portanto se você colocar
Mudar isso não altera o contêiner final, apenas pode acelerar o `build` em casos uma camada pesada, como um `npm install` depois de outra que será modificada
que essa ordenação. 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 Um exemplo disso é a ordenação `COPY . /app/` e `RUN npm install`. Quando se trabalha
> faz diferença'. 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 #### ARG e ENV
TODO: :)
#### COPY e RUN #### COPY e RUN
TODO: eventualmente comentar do .dockerignore
:::{tip} :::{tip}
Vamos supor que você só precisa de um pequeno conjunto de seus arquivos 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. ...@@ -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 Se você já tem familiaridade com o Git provavelmente conhece o arquivo
`.gitignore`. Com docker existe o arquivo `.dockerignore` para arquivos `.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 #### CMD vs ENTRYPOINT
:::{seealso} :::{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 ### Interagindo com contêineres
...@@ -766,6 +715,10 @@ TODO: Uma instrução particularmente interessante é a `HEALTHCHECK`. ...@@ -766,6 +715,10 @@ TODO: Uma instrução particularmente interessante é a `HEALTHCHECK`.
#### Bind Mounts #### Bind Mounts
## Uma introdução às **redes** ## 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 ## Docker Compose
Como orquestrar múltiplos contêineres elegantemente? Como orquestrar múltiplos contêineres elegantemente?
...@@ -810,7 +763,7 @@ não há por que mexer ninguém irá mexer. ...@@ -810,7 +763,7 @@ não há por que mexer ninguém irá mexer.
::: :::
### O arquivo `docker-compose.yml` ### O arquivo `docker-compose.yml`
Aqui vamos longe. TODO: Aqui vamos longe.
### Por que agora? ### Por que agora?
Por que ver toda a parte difícil antes de `compose`? Por que ver toda a parte difícil antes de `compose`?
...@@ -848,16 +801,8 @@ qualquer *merge* na branch `main`, por exemplo. ...@@ -848,16 +801,8 @@ qualquer *merge* na branch `main`, por exemplo.
## TODO: Fernando comentou sobre docker debian12 em host debian9 -> estudar ## TODO: Fernando comentou sobre docker debian12 em host debian9 -> estudar
## TODO: Colinha de Docker ## TODO: Pesquisando por conta
- `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.
[^cite_docker_concepts]: [Conceitos básicos de Docker](../concepts/docker.md). [^cite_docker_concepts]: [Conceitos básicos de Docker](../concepts/docker.md).
...@@ -867,3 +812,6 @@ qualquer *merge* na branch `main`, por exemplo. ...@@ -867,3 +812,6 @@ qualquer *merge* na branch `main`, por exemplo.
[^cite_docker_hub]: [DockerHub](https://hub.docker.com/). [^cite_docker_hub]: [DockerHub](https://hub.docker.com/).
[^cite_expose]: [Instrução EXPOSE](https://docs.docker.com/reference/dockerfile/#expose). [^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_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/).
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment