]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md` (#5663)
authorAyrton Freeman <ayrton@riseup.net>
Sun, 27 Nov 2022 14:13:50 +0000 (11:13 -0300)
committerGitHub <noreply@github.com>
Sun, 27 Nov 2022 14:13:50 +0000 (14:13 +0000)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: SebastiĂĄn RamĂ­rez <tiangolo@gmail.com>
docs/pt/docs/deployment/docker.md [new file with mode: 0644]
docs/pt/mkdocs.yml

diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md
new file mode 100644 (file)
index 0000000..42c31db
--- /dev/null
@@ -0,0 +1,701 @@
+# FastAPI em contĂȘineres - Docker
+
+Ao fazer o deploy de aplicaçÔes FastAPI uma abordagem comum Ă© construir uma **imagem de contĂȘiner Linux**. Isso normalmente Ă© feito usando o <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. VocĂȘ pode a partir disso fazer o deploy dessa imagem de algumas maneiras.
+
+Usando contĂȘineres Linux vocĂȘ tem diversas vantagens incluindo **segurança**, **replicabilidade**, **simplicidade**, entre outras.
+
+!!! Dica
+    EstĂĄ com pressa e jĂĄ sabe dessas coisas? Pode ir direto para [`Dockerfile` abaixo đŸ‘‡](#build-a-docker-image-for-fastapi).
+
+
+<details>
+<summary>Visualização do Dockerfile đŸ‘€</summary>
+
+```Dockerfile
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+COPY ./app /code/app
+
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+
+# If running behind a proxy like Nginx or Traefik add --proxy-headers
+# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]
+```
+
+</details>
+
+## O que Ă© um ContĂȘiner
+
+ContĂȘineres (especificamente contĂȘineres Linux) sĂŁo um jeito muito **leve** de empacotar aplicaçÔes contendo todas as dependĂȘncias e arquivos necessĂĄrios enquanto os mantĂ©m isolados de outros contĂȘineres (outras aplicaçÔes ou componentes) no mesmo sistema.
+
+ContĂȘineres Linux rodam usando o mesmo kernel Linux do hospedeiro (mĂĄquina, mĂĄquina virtual, servidor na nuvem, etc). Isso simplesmente significa que eles sĂŁo muito leves (comparados com mĂĄquinas virtuais emulando um sistema operacional completo).
+
+Dessa forma, contĂȘineres consomem **poucos recursos**, uma quantidade comparĂĄvel com rodar os processos diretamente (uma mĂĄquina virtual consumiria muito mais).
+
+ContĂȘineres tambĂ©m possuem seus prĂłprios processos (comumente um Ășnico processo), sistema de arquivos e rede **isolados** simplificando deploy, segurança, desenvolvimento, etc.
+
+## O que Ă© uma Imagem de ContĂȘiner
+
+Um **contĂȘiner** roda a partir de uma **imagem de contĂȘiner**.
+
+Uma imagem de contĂȘiner Ă© uma versĂŁo **estĂĄtica** de todos os arquivos, variĂĄveis de ambiente e do comando/programa padrĂŁo que deve estar presente num contĂȘiner. **EstĂĄtica** aqui significa que a **imagem** de contĂȘiner nĂŁo estĂĄ rodando, nĂŁo estĂĄ sendo executada, somente contĂ©m os arquivos e metadados empacotados.
+
+Em contraste com a "**imagem de contĂȘiner**" que contĂ©m os conteĂșdos estĂĄticos armazenados, um "**contĂȘiner**" normalmente se refere Ă  instĂąncia rodando, a coisa que estĂĄ sendo **executada**.
+
+Quando o **contĂȘiner** Ă© iniciado e estĂĄ rodando (iniciado a partir de uma **imagem de contĂȘiner**), ele pode criar ou modificar arquivos, variĂĄveis de ambiente, etc. Essas mudanças vĂŁo existir somente nesse contĂȘiner, mas nĂŁo persistirĂŁo na imagem subjacente do container (nĂŁo serĂŁo salvas no disco).
+
+Uma imagem de contĂȘiner Ă© comparĂĄvel ao arquivo de **programa** e seus conteĂșdos, ex.: `python` e algum arquivo `main.py`.
+
+E o **contĂȘiner** em si (em contraste Ă  **imagem de contĂȘiner**) Ă© a prĂłpria instĂąncia da imagem rodando, comparĂĄvel a um **processo**. Na verdade, um contĂȘiner estĂĄ rodando somente quando hĂĄ um **processo rodando** (e normalmente Ă© somente um processo). O contĂȘiner finaliza quando nĂŁo hĂĄ um processo rodando nele.
+
+## Imagens de contĂȘiner
+
+Docker tem sido uma das principais ferramentas para criar e gerenciar **imagens de contĂȘiner** e **contĂȘineres**.
+
+E existe um <a href="https://hub.docker.com/" class="external-link" target="_blank">Docker Hub</a> pĂșblico com **imagens de contĂȘiner oficiais** prĂ©-prontas para diversas ferramentas, ambientes, bancos de dados e aplicaçÔes.
+
+Por exemplo, hĂĄ uma <a href="https://hub.docker.com/_/python" class="external-link" target="_blank">Imagem Python</a> oficial.
+
+E existe muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo:
+
+* <a href="https://hub.docker.com/_/postgres" class="external-link" target="_blank">PostgreSQL</a>
+* <a href="https://hub.docker.com/_/mysql" class="external-link" target="_blank">MySQL</a>
+* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
+* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a>, etc.
+
+Usando imagens de contĂȘiner prĂ©-prontas Ă© muito fĂĄcil **combinar** e usar diferentes ferramentas. Por exemplo, para testar um novo banco de dados. Em muitos casos, vocĂȘ pode usar as **imagens oficiais** precisando somente de variĂĄveis de ambiente para configurĂĄ-las.
+
+Dessa forma, em muitos casos vocĂȘ pode aprender sobre contĂȘineres e Docker e re-usar essa experiĂȘncia com diversos componentes e ferramentas.
+
+EntĂŁo, vocĂȘ rodaria **vĂĄrios contĂȘineres** com coisas diferentes, como um banco de dados, uma aplicação Python, um servidor web com uma aplicação frontend React, e conectĂĄ-los juntos via sua rede interna.
+
+Todos os sistemas de gerenciamento de contĂȘineres (como Docker ou Kubernetes) possuem essas funcionalidades de rede integradas a eles.
+
+## ContĂȘineres e Processos
+
+Uma **imagem de contĂȘiner** normalmente inclui em seus metadados o programa padrĂŁo ou comando que deve ser executado quando o **contĂȘiner** Ă© iniciado e os parĂąmetros a serem passados para esse programa. Muito similar ao que seria se estivesse na linha de comando.
+
+Quando um **contĂȘiner** Ă© iniciado, ele irĂĄ rodar esse comando/programa (embora vocĂȘ possa sobrescrevĂȘ-lo e fazer com que ele rode um comando/programa diferente).
+
+Um contĂȘiner estĂĄ rodando enquanto o **processo principal** (comando ou programa) estiver rodando.
+
+Um contĂȘiner normalmente tem um **Ășnico processo**, mas tambĂ©m Ă© possĂ­vel iniciar sub-processos a partir do processo principal, e dessa forma vocĂȘ terĂĄ **vĂĄrios processos** no mesmo contĂȘiner.
+
+Mas nĂŁo Ă© possĂ­vel ter um contĂȘiner rodando sem **pelo menos um processo rodando**. Se o processo principal parar, o contĂȘiner tambĂ©m para.
+
+## Construindo uma Imagem Docker para FastAPI
+
+Okay, vamos construir algo agora! đŸš€
+
+Eu vou mostrar como construir uma **imagem Docker** para FastAPI **do zero**, baseado na **imagem oficial do Python**.
+
+Isso Ă© o que vocĂȘ quer fazer na **maioria dos casos**, por exemplo:
+
+* Usando **Kubernetes** ou ferramentas similares
+* Quando rodando em uma **Raspberry Pi**
+* Usando um serviço em nuvem que irĂĄ rodar uma imagem de contĂȘiner para vocĂȘ, etc.
+
+### O Pacote Requirements
+
+VocĂȘ normalmente teria os **requisitos do pacote** para sua aplicação em algum arquivo.
+
+Isso pode depender principalmente da ferramenta que vocĂȘ usa para **instalar** esses requisitos.
+
+O caminho mais comum de fazer isso Ă© ter um arquivo `requirements.txt` com os nomes dos pacotes e suas versĂ”es, um por linha.
+
+VocĂȘ, naturalmente, usaria as mesmas ideias que vocĂȘ leu em [Sobre VersĂ”es do FastAPI](./versions.md){.internal-link target=_blank} para definir os intervalos de versĂ”es.
+
+Por exemplo, seu `requirements.txt` poderia parecer com:
+
+```
+fastapi>=0.68.0,<0.69.0
+pydantic>=1.8.0,<2.0.0
+uvicorn>=0.15.0,<0.16.0
+```
+
+E vocĂȘ normalmente instalaria essas dependĂȘncias de pacote com `pip`, por exemplo:
+
+<div class="termy">
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic uvicorn
+```
+
+</div>
+
+!!! info
+    HĂĄ outros formatos e ferramentas para definir e instalar dependĂȘncias de pacote.
+
+    Eu vou mostrar um exemplo depois usando Poetry em uma seção abaixo. đŸ‘‡
+
+### Criando o CĂłdigo do **FastAPI**
+
+* Crie um diretĂłrio `app` e entre nele.
+* Crie um arquivo vazio `__init__.py`.
+* Crie um arquivo `main.py` com:
+
+```Python
+from typing import Optional
+
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def read_root():
+    return {"Hello": "World"}
+
+
+@app.get("/items/{item_id}")
+def read_item(item_id: int, q: Union[str, None] = None):
+    return {"item_id": item_id, "q": q}
+```
+
+### Dockerfile
+
+Agora, no mesmo diretĂłrio do projeto, crie um arquivo `Dockerfile` com:
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9
+
+# (2)
+WORKDIR /code
+
+# (3)
+COPY ./requirements.txt /code/requirements.txt
+
+# (4)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (5)
+COPY ./app /code/app
+
+# (6)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. Inicie a partir da imagem base oficial do Python.
+
+2. Defina o diretĂłrio de trabalho atual para `/code`.
+
+    Esse Ă© o diretĂłrio onde colocaremos o arquivo `requirements.txt` e o diretĂłrio `app`.
+
+3. Copie o arquivo com os requisitos para o diretĂłrio `/code`.
+
+    Copie **somente** o arquivo com os requisitos primeiro, nĂŁo o resto do cĂłdigo.
+
+    Como esse arquivo **nĂŁo muda com frequĂȘncia**, o Docker irĂĄ detectĂĄ-lo e usar o **cache** para esse passo, habilitando o cache para o prĂłximo passo tambĂ©m.
+
+4. Instale as dependĂȘncias de pacote vindas do arquivo de requisitos.
+
+    A opção `--no-cache-dir` diz ao `pip` para nĂŁo salvar os pacotes baixados localmente, pois isso sĂł aconteceria se `pip` fosse executado novamente para instalar os mesmos pacotes, mas esse nĂŁo Ă© o caso quando trabalhamos com contĂȘineres.
+
+    !!! note
+        `--no-cache-dir` Ă© apenas relacionado ao `pip`, nĂŁo tem nada a ver com Docker ou contĂȘineres.
+
+    A opção `--upgrade` diz ao `pip` para atualizar os pacotes se eles jĂĄ estiverem instalados.
+
+    Por causa do passo anterior de copiar o arquivo, ele pode ser detectado pelo **cache do Docker**, esse passo tambĂ©m **usarĂĄ o cache do Docker** quando disponĂ­vel.
+
+    Usando o cache nesse passo irĂĄ **salvar** muito **tempo** quando vocĂȘ for construir a imagem repetidas vezes durante o desenvolvimento, ao invĂ©s de **baixar e instalar** todas as dependĂȘncias **toda vez**.
+
+5. Copie o diretĂłrio `./app` dentro do diretĂłrio `/code`.
+
+    Como isso tem todo o cĂłdigo contendo o que **muda com mais frequĂȘncia**, o **cache do Docker** nĂŁo serĂĄ usado para esse passo ou para **qualquer passo seguinte** facilmente.
+
+    EntĂŁo, Ă© importante colocar isso **perto do final** do `Dockerfile`, para otimizar o tempo de construção da imagem do contĂȘiner.
+
+6. Defina o **comando** para rodar o servidor `uvicorn`.
+
+    `CMD` recebe uma lista de strings, cada uma dessas strings Ă© o que vocĂȘ digitaria na linha de comando separado por espaços.
+
+    Esse comando serĂĄ executado a partir do **diretĂłrio de trabalho atual**, o mesmo diretĂłrio `/code` que vocĂȘ definiu acima com `WORKDIR /code`.
+
+    Porque o programa serĂĄ iniciado em `/code` e dentro dele estĂĄ o diretĂłrio `./app` com seu cĂłdigo, o **Uvicorn** serĂĄ capaz de ver e **importar** `app` de `app.main`.
+
+!!! tip
+    Revise o que cada linha faz clicando em cada bolha com o nĂșmero no cĂłdigo. đŸ‘†
+
+Agora vocĂȘ deve ter uma estrutura de diretĂłrio como:
+
+```
+.
+├── app
+│   â”œâ”€â”€ __init__.py
+│   â””── main.py
+├── Dockerfile
+└── requirements.txt
+```
+
+#### Por TrĂĄs de um Proxy de Terminação TLS
+
+Se vocĂȘ estĂĄ executando seu contĂȘiner atrĂĄs de um Proxy de Terminação TLS (load balancer) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso farĂĄ com que o Uvicorn confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo estĂĄ sendo executado atrĂĄs do HTTPS, etc.
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+#### Cache Docker
+
+Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo com as dependĂȘncias sozinho**, nĂŁo o resto do cĂłdigo. Deixe-me te contar o porquĂȘ disso.
+
+```Dockerfile
+COPY ./requirements.txt /code/requirements.txt
+```
+
+Docker e outras ferramentas **constrĂłem** essas imagens de contĂȘiner **incrementalmente**, adicionando **uma camada em cima da outra**, começando do topo do `Dockerfile` e adicionando qualquer arquivo criado por cada uma das instruçÔes do `Dockerfile`.
+
+Docker e ferramentas similares tambĂ©m usam um **cache interno** ao construir a imagem, se um arquivo nĂŁo mudou desde a Ășltima vez que a imagem do contĂȘiner foi construĂ­da, entĂŁo ele irĂĄ **reutilizar a mesma camada** criada na Ășltima vez, ao invĂ©s de copiar o arquivo novamente e criar uma nova camada do zero.
+
+Somente evitar a cĂłpia de arquivos nĂŁo melhora muito as coisas, mas porque ele usou o cache para esse passo, ele pode **usar o cache para o prĂłximo passo**. Por exemplo, ele pode usar o cache para a instrução que instala as dependĂȘncias com:
+
+```Dockerfile
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+```
+
+O arquivo com os requisitos de pacote **nĂŁo muda com frequĂȘncia**. EntĂŁo, ao copiar apenas esse arquivo, o Docker serĂĄ capaz de **usar o cache** para esse passo.
+
+E entĂŁo, o Docker serĂĄ capaz de **usar o cache para o prĂłximo passo** que baixa e instala essas dependĂȘncias. E Ă© aqui que **salvamos muito tempo**. âœš ...e evitamos tĂ©dio esperando. đŸ˜Ș😆
+
+Baixar e instalar as dependĂȘncias do pacote **pode levar minutos**, mas usando o **cache** leva **segundos** no mĂĄximo.
+
+E como vocĂȘ estaria construindo a imagem do contĂȘiner novamente e novamente durante o desenvolvimento para verificar se suas alteraçÔes de cĂłdigo estĂŁo funcionando, hĂĄ muito tempo acumulado que isso economizaria.
+
+A partir daĂ­, perto do final do `Dockerfile`, copiamos todo o cĂłdigo. Como isso Ă© o que **muda com mais frequĂȘncia**, colocamos perto do final, porque quase sempre, qualquer coisa depois desse passo nĂŁo serĂĄ capaz de usar o cache.
+
+```Dockerfile
+COPY ./app /code/app
+```
+
+### Construindo a Imagem Docker
+
+Agora que todos os arquivos estĂŁo no lugar, vamos construir a imagem do contĂȘiner.
+
+* VĂĄ para o diretĂłrio do projeto (onde estĂĄ o seu `Dockerfile`, contendo o diretĂłrio `app`).
+* Construa sua imagem FastAPI:
+
+<div class="termy">
+
+```console
+$ docker build -t myimage .
+
+---> 100%
+```
+
+</div>
+
+!!! tip
+    Note o `.` no final, Ă© equivalente a `./`, ele diz ao Docker o diretĂłrio a ser usado para construir a imagem do contĂȘiner.
+
+    Nesse caso, Ă© o mesmo diretĂłrio atual (`.`).
+
+### Inicie o contĂȘiner Docker
+
+* Execute um contĂȘiner baseado na sua imagem:
+
+<div class="termy">
+
+```console
+$ docker run -d --name mycontĂȘiner -p 80:80 myimage
+```
+
+</div>
+
+## Verifique
+
+VocĂȘ deve ser capaz de verificar isso no URL do seu contĂȘiner Docker, por exemplo: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou equivalente, usando seu host Docker).
+
+VocĂȘ verĂĄ algo como:
+
+```JSON
+{"item_id": 5, "q": "somequery"}
+```
+
+## Documentação interativa da API
+
+Agora vocĂȘ pode ir para <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou equivalente, usando seu host Docker).
+
+VocĂȘ verĂĄ a documentação interativa automĂĄtica da API (fornecida pelo <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
+
+![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
+
+## Documentação alternativa da API
+
+E vocĂȘ tambĂ©m pode ir para <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou equivalente, usando seu host Docker).
+
+VocĂȘ verĂĄ a documentação alternativa automĂĄtica (fornecida pela <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
+
+![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
+
+## Construindo uma Imagem Docker com um Arquivo Ăšnico FastAPI
+
+Se seu FastAPI for um Ășnico arquivo, por exemplo, `main.py` sem um diretĂłrio `./app`, sua estrutura de arquivos poderia ser assim:
+
+```
+.
+├── Dockerfile
+├── main.py
+└── requirements.txt
+```
+
+EntĂŁo vocĂȘ sĂł teria que alterar os caminhos correspondentes para copiar o arquivo dentro do `Dockerfile`:
+
+```{ .dockerfile .annotate hl_lines="10  13" }
+FROM python:3.9
+
+WORKDIR /code
+
+COPY ./requirements.txt /code/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (1)
+COPY ./main.py /code/
+
+# (2)
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. Copie o arquivo `main.py` para o diretĂłrio `/code` diretamente (sem nenhum diretĂłrio `./app`).
+
+2. Execute o Uvicorn e diga a ele para importar o objeto `app` de `main` (em vez de importar de `app.main`).
+
+EntĂŁo ajuste o comando Uvicorn para usar o novo mĂłdulo `main` em vez de `app.main` para importar o objeto FastAPI `app`.
+
+## Conceitos de Implantação
+
+Vamos falar novamente sobre alguns dos mesmos [Conceitos de Implantação](./concepts.md){.internal-link target=_blank} em termos de contĂȘineres.
+
+ContĂȘineres sĂŁo principalmente uma ferramenta para simplificar o processo de **construção e implantação** de um aplicativo, mas eles nĂŁo impĂ”em uma abordagem particular para lidar com esses **conceitos de implantação** e existem vĂĄrias estratĂ©gias possĂ­veis.
+
+A **boa notĂ­cia** Ă© que com cada estratĂ©gia diferente hĂĄ uma maneira de cobrir todos os conceitos de implantação. đŸŽ‰
+
+Vamos revisar esses **conceitos de implantação** em termos de contĂȘineres:
+
+* HTTPS
+* Executando na inicialização
+* ReinicializaçÔes
+* Replicação (nĂșmero de processos rodando)
+* MemĂłria
+* Passos anteriores antes de começar
+
+## HTTPS
+
+Se nos concentrarmos apenas na **imagem do contĂȘiner** para um aplicativo FastAPI (e posteriormente no **contĂȘiner** em execução), o HTTPS normalmente seria tratado **externamente** por outra ferramenta.
+
+Isso poderia ser outro contĂȘiner, por exemplo, com <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>, lidando com **HTTPS** e aquisição **automĂĄtica** de **certificados**.
+
+!!! tip
+    Traefik tem integraçÔes com Docker, Kubernetes e outros, portanto, Ă© muito fĂĄcil configurar e configurar o HTTPS para seus contĂȘineres com ele.
+
+Alternativamente, o HTTPS poderia ser tratado por um provedor de nuvem como um de seus serviços (enquanto ainda executasse o aplicativo em um contĂȘiner).
+
+## Executando na inicialização e reinicializaçÔes
+
+Normalmente, outra ferramenta Ă© responsĂĄvel por **iniciar e executar** seu contĂȘiner.
+
+Ela poderia ser o **Docker** diretamente, **Docker Compose**, **Kubernetes**, um **serviço de nuvem**, etc.
+
+Na maioria (ou em todos) os casos, hĂĄ uma opção simples para habilitar a execução do contĂȘiner na inicialização e habilitar reinicializaçÔes em falhas. Por exemplo, no Docker, Ă© a opção de linha de comando `--restart`.
+
+Sem usar contĂȘineres, fazer aplicativos executarem na inicialização e com reinicializaçÔes pode ser trabalhoso e difĂ­cil. Mas quando **trabalhando com contĂȘineres** em muitos casos essa funcionalidade Ă© incluĂ­da por padrĂŁo. âœš
+
+## Replicação - NĂșmero de Processos
+
+Se vocĂȘ tiver um <abbr title="Um grupo de mĂĄquinas que sĂŁo configuradas para estarem conectadas e trabalharem juntas de alguma forma">cluster</abbr> de mĂĄquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contĂȘineres distribuĂ­dos em vĂĄrias mĂĄquinas, entĂŁo provavelmente desejarĂĄ **lidar com a replicação** no **nĂ­vel do cluster** em vez de usar um **gerenciador de processos** (como o Gunicorn com workers) em cada contĂȘiner.
+
+Um desses sistemas de gerenciamento de contĂȘineres distribuĂ­dos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contĂȘineres** enquanto ainda oferece **balanceamento de carga** para as solicitaçÔes recebidas. Tudo no **nĂ­vel do cluster**.
+
+Nesses casos, vocĂȘ provavelmente desejarĂĄ criar uma **imagem do contĂȘiner do zero** como [explicado acima](#dockerfile), instalando suas dependĂȘncias e executando **um Ășnico processo Uvicorn** em vez de executar algo como Gunicorn com trabalhadores Uvicorn.
+
+### Balanceamento de Carga
+
+Quando usando contĂȘineres, normalmente vocĂȘ terĂĄ algum componente **escutando na porta principal**. Poderia ser outro contĂȘiner que tambĂ©m Ă© um **Proxy de Terminação TLS** para lidar com **HTTPS** ou alguma ferramenta semelhante.
+
+Como esse componente assumiria a **carga** de solicitaçÔes e distribuiria isso entre os trabalhadores de uma maneira (esperançosamente) **balanceada**, ele tambĂ©m Ă© comumente chamado de **Balanceador de Carga**.
+
+!!! tip
+    O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente tambĂ©m seria um **Balanceador de Carga**.
+
+E quando trabalhar com contĂȘineres, o mesmo sistema que vocĂȘ usa para iniciar e gerenciĂĄ-los jĂĄ terĂĄ ferramentas internas para transmitir a **comunicação de rede** (por exemplo, solicitaçÔes HTTP) do **balanceador de carga** (que tambĂ©m pode ser um **Proxy de Terminação TLS**) para o(s) contĂȘiner(es) com seu aplicativo.
+
+### Um Balanceador de Carga - MĂșltiplos ContĂȘineres de Workers
+
+Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contĂȘiner distribuĂ­do, usando seus mecanismos de rede internos permitiria que o Ășnico **balanceador de carga** que estivesse escutando na **porta principal** transmitisse comunicação (solicitaçÔes) para possivelmente **mĂșltiplos contĂȘineres** executando seu aplicativo.
+
+Cada um desses contĂȘineres executando seu aplicativo normalmente teria **apenas um processo** (ex.: um processo Uvicorn executando seu aplicativo FastAPI). Todos seriam **contĂȘineres idĂȘnticos**, executando a mesma coisa, mas cada um com seu prĂłprio processo, memĂłria, etc. Dessa forma, vocĂȘ aproveitaria a **paralelização** em **nĂșcleos diferentes** da CPU, ou atĂ© mesmo em **mĂĄquinas diferentes**.
+
+E o sistema de contĂȘiner com o **balanceador de carga** iria **distribuir as solicitaçÔes** para cada um dos contĂȘineres com seu aplicativo **em turnos**. Portanto, cada solicitação poderia ser tratada por um dos mĂșltiplos **contĂȘineres replicados** executando seu aplicativo.
+
+E normalmente esse **balanceador de carga** seria capaz de lidar com solicitaçÔes que vĂŁo para *outros* aplicativos em seu cluster (por exemplo, para um domĂ­nio diferente, ou sob um prefixo de URL diferente), e transmitiria essa comunicação para os contĂȘineres certos para *esse outro* aplicativo em execução em seu cluster.
+
+### Um Processo por ContĂȘiner
+
+Nesse tipo de cenĂĄrio, provavelmente vocĂȘ desejarĂĄ ter **um Ășnico processo (Uvicorn) por contĂȘiner**, pois jĂĄ estaria lidando com a replicação no nĂ­vel do cluster.
+
+EntĂŁo, nesse caso, vocĂȘ **nĂŁo** desejarĂĄ ter um gerenciador de processos como o Gunicorn com trabalhadores Uvicorn, ou o Uvicorn usando seus prĂłprios trabalhadores Uvicorn. VocĂȘ desejarĂĄ ter apenas um **Ășnico processo Uvicorn** por contĂȘiner (mas provavelmente vĂĄrios contĂȘineres).
+
+Tendo outro gerenciador de processos dentro do contĂȘiner (como seria com o Gunicorn ou o Uvicorn gerenciando trabalhadores Uvicorn) sĂł adicionaria **complexidade desnecessĂĄria** que vocĂȘ provavelmente jĂĄ estĂĄ cuidando com seu sistema de cluster.
+
+### ContĂȘineres com MĂșltiplos Processos e Casos Especiais
+
+Claro, existem **casos especiais** em que vocĂȘ pode querer ter um **contĂȘiner** com um **gerenciador de processos Gunicorn** iniciando vĂĄrios **processos trabalhadores Uvicorn** dentro.
+
+Nesses casos, vocĂȘ pode usar a **imagem oficial do Docker** que inclui o **Gunicorn** como um gerenciador de processos executando vĂĄrios **processos trabalhadores Uvicorn**, e algumas configuraçÔes padrĂŁo para ajustar o nĂșmero de trabalhadores com base nos atuais nĂșcleos da CPU automaticamente. Eu vou te contar mais sobre isso abaixo em [Imagem Oficial do Docker com Gunicorn - Uvicorn](#imagem-oficial-do-docker-com-gunicorn-uvicorn).
+
+Aqui estĂŁo alguns exemplos de quando isso pode fazer sentido:
+
+#### Um Aplicativo Simples
+
+VocĂȘ pode querer um gerenciador de processos no contĂȘiner se seu aplicativo for **simples o suficiente** para que vocĂȘ nĂŁo precise (pelo menos nĂŁo agora) ajustar muito o nĂșmero de processos, e vocĂȘ pode simplesmente usar um padrĂŁo automatizado (com a imagem oficial do Docker), e vocĂȘ estĂĄ executando em um **Ășnico servidor**, nĂŁo em um cluster.
+
+#### Docker Compose
+
+VocĂȘ pode estar implantando em um **Ășnico servidor** (nĂŁo em um cluster) com o **Docker Compose**, entĂŁo vocĂȘ nĂŁo teria uma maneira fĂĄcil de gerenciar a replicação de contĂȘineres (com o Docker Compose) enquanto preserva a rede compartilhada e o **balanceamento de carga**.
+
+EntĂŁo vocĂȘ pode querer ter **um Ășnico contĂȘiner** com um **gerenciador de processos** iniciando **vĂĄrios processos trabalhadores** dentro.
+
+#### Prometheus and Outros Motivos
+
+VocĂȘ tambĂ©m pode ter **outros motivos** que tornariam mais fĂĄcil ter um **Ășnico contĂȘiner** com **mĂșltiplos processos** em vez de ter **mĂșltiplos contĂȘineres** com **um Ășnico processo** em cada um deles.
+
+Por exemplo (dependendo de sua configuração), vocĂȘ poderia ter alguma ferramenta como um exportador do Prometheus no mesmo contĂȘiner que deve ter acesso a **cada uma das solicitaçÔes** que chegam.
+
+Nesse caso, se vocĂȘ tivesse **mĂșltiplos contĂȘineres**, por padrĂŁo, quando o Prometheus fosse **ler as mĂ©tricas**, ele receberia as mĂ©tricas de **um Ășnico contĂȘiner cada vez** (para o contĂȘiner que tratou essa solicitação especĂ­fica), em vez de receber as **mĂ©tricas acumuladas** de todos os contĂȘineres replicados.
+
+EntĂŁo, nesse caso, poderia ser mais simples ter **um Ășnico contĂȘiner** com **mĂșltiplos processos**, e uma ferramenta local (por exemplo, um exportador do Prometheus) no mesmo contĂȘiner coletando mĂ©tricas do Prometheus para todos os processos internos e expor essas mĂ©tricas no Ășnico contĂȘiner.
+
+---
+
+O ponto principal Ă© que **nenhum** desses sĂŁo **regras escritas em pedra** que vocĂȘ deve seguir cegamente. VocĂȘ pode usar essas idĂ©ias para **avaliar seu prĂłprio caso de uso** e decidir qual Ă© a melhor abordagem para seu sistema, verificando como gerenciar os conceitos de:
+
+* Segurança - HTTPS
+* Executando na inicialização
+* ReinicializaçÔes
+* Replicação (o nĂșmero de processos em execução)
+* MemĂłria
+* Passos anteriores antes de inicializar
+
+## MemĂłria
+
+Se vocĂȘ executar **um Ășnico processo por contĂȘiner**, terĂĄ uma quantidade mais ou menos bem definida, estĂĄvel e limitada de memĂłria consumida por cada um desses contĂȘineres (mais de um se eles forem replicados).
+
+E entĂŁo vocĂȘ pode definir esses mesmos limites e requisitos de memĂłria em suas configuraçÔes para seu sistema de gerenciamento de contĂȘineres (por exemplo, no **Kubernetes**). Dessa forma, ele poderĂĄ **replicar os contĂȘineres** nas **mĂĄquinas disponĂ­veis** levando em consideração a quantidade de memĂłria necessĂĄria por eles e a quantidade disponĂ­vel nas mĂĄquinas no cluster.
+
+Se sua aplicação for **simples**, isso provavelmente **nĂŁo serĂĄ um problema**, e vocĂȘ pode nĂŁo precisar especificar limites de memĂłria rĂ­gidos. Mas se vocĂȘ estiver **usando muita memĂłria** (por exemplo, com **modelos de aprendizado de mĂĄquina**), deve verificar quanta memĂłria estĂĄ consumindo e ajustar o **nĂșmero de contĂȘineres** que executa em **cada mĂĄquina** (e talvez adicionar mais mĂĄquinas ao seu cluster).
+
+Se vocĂȘ executar **mĂșltiplos processos por contĂȘiner** (por exemplo, com a imagem oficial do Docker), deve garantir que o nĂșmero de processos iniciados nĂŁo **consuma mais memĂłria** do que o disponĂ­vel.
+
+## Passos anteriores antes de inicializar e contĂȘineres
+
+Se vocĂȘ estiver usando contĂȘineres (por exemplo, Docker, Kubernetes), existem duas abordagens principais que vocĂȘ pode usar.
+
+### ContĂȘineres MĂșltiplos
+
+Se vocĂȘ tiver **mĂșltiplos contĂȘineres**, provavelmente cada um executando um **Ășnico processo** (por exemplo, em um cluster do **Kubernetes**), entĂŁo provavelmente vocĂȘ gostaria de ter um **contĂȘiner separado** fazendo o trabalho dos **passos anteriores** em um Ășnico contĂȘiner, executando um Ășnico processo, **antes** de executar os contĂȘineres trabalhadores replicados.
+
+!!! info
+    Se vocĂȘ estiver usando o Kubernetes, provavelmente serĂĄ um <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>.
+
+Se no seu caso de uso nĂŁo houver problema em executar esses passos anteriores **em paralelo vĂĄrias vezes** (por exemplo, se vocĂȘ nĂŁo estiver executando migraçÔes de banco de dados, mas apenas verificando se o banco de dados estĂĄ pronto), entĂŁo vocĂȘ tambĂ©m pode colocĂĄ-los em cada contĂȘiner logo antes de iniciar o processo principal.
+
+### ContĂȘiner Ăšnico
+
+Se vocĂȘ tiver uma configuração simples, com um **Ășnico contĂȘiner** que entĂŁo inicia vĂĄrios **processos trabalhadores** (ou tambĂ©m apenas um processo), entĂŁo poderia executar esses passos anteriores no mesmo contĂȘiner, logo antes de iniciar o processo com o aplicativo. A imagem oficial do Docker suporta isso internamente.
+
+## Imagem Oficial do Docker com Gunicorn - Uvicorn
+
+HĂĄ uma imagem oficial do Docker que inclui o Gunicorn executando com trabalhadores Uvicorn, conforme detalhado em um capĂ­tulo anterior: [Server Workers - Gunicorn com Uvicorn](./server-workers.md){.internal-link target=_blank}.
+
+Essa imagem seria Ăștil principalmente nas situaçÔes descritas acima em: [ContĂȘineres com MĂșltiplos Processos e Casos Especiais](#contĂȘineres-com-mĂșltiplos-processos-e-casos-Especiais).
+
+* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
+
+!!! warning
+    Existe uma grande chance de que vocĂȘ **nĂŁo** precise dessa imagem base ou de qualquer outra semelhante, e seria melhor construir a imagem do zero, como [descrito acima em: Construa uma Imagem Docker para o FastAPI](#construa-uma-imagem-docker-para-o-fastapi).
+
+Essa imagem tem um mecanismo de **auto-ajuste** incluĂ­do para definir o **nĂșmero de processos trabalhadores** com base nos nĂșcleos de CPU disponĂ­veis.
+
+Isso tem **padrĂ”es sensĂ­veis**, mas vocĂȘ ainda pode alterar e atualizar todas as configuraçÔes com **variĂĄveis de ambiente** ou arquivos de configuração.
+
+HĂĄ tambĂ©m suporte para executar <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#pre_start_path" class="external-link" target="_blank">**passos anteriores antes de iniciar**</a> com um script.
+
+!!! tip
+    Para ver todas as configuraçÔes e opçÔes, vĂĄ para a pĂĄgina da imagem Docker:  <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
+
+### NĂșmero de Processos na Imagem Oficial do Docker
+
+O **nĂșmero de processos** nesta imagem Ă© **calculado automaticamente** a partir dos **nĂșcleos de CPU** disponĂ­veis.
+
+Isso significa que ele tentarĂĄ **aproveitar** o mĂĄximo de **desempenho** da CPU possĂ­vel.
+
+VocĂȘ tambĂ©m pode ajustĂĄ-lo com as configuraçÔes usando **variĂĄveis de ambiente**, etc.
+
+Mas isso tambĂ©m significa que, como o nĂșmero de processos depende da CPU do contĂȘiner em execução, a **quantidade de memĂłria consumida** tambĂ©m dependerĂĄ disso.
+
+EntĂŁo, se seu aplicativo consumir muito memĂłria (por exemplo, com modelos de aprendizado de mĂĄquina), e seu servidor tiver muitos nĂșcleos de CPU **mas pouca memĂłria**, entĂŁo seu contĂȘiner pode acabar tentando usar mais memĂłria do que estĂĄ disponĂ­vel e degradar o desempenho muito (ou atĂ© mesmo travar). đŸšš
+
+### Criando um `Dockerfile`
+
+Aqui estĂĄ como vocĂȘ criaria um `Dockerfile` baseado nessa imagem:
+
+```Dockerfile
+FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
+
+COPY ./requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+
+COPY ./app /app
+```
+
+### AplicaçÔes Maiores
+
+Se vocĂȘ seguiu a seção sobre a criação de [AplicaçÔes Maiores com MĂșltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}, seu `Dockerfile` pode parecer com isso:
+
+```Dockerfile
+
+```Dockerfile hl_lines="7"
+FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
+
+COPY ./requirements.txt /app/requirements.txt
+
+RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
+
+COPY ./app /app/app
+```
+
+### Quando Usar
+
+VocĂȘ provavelmente **nĂŁo** deve usar essa imagem base oficial (ou qualquer outra semelhante) se estiver usando **Kubernetes** (ou outros) e jĂĄ estiver definindo **replicação** no nĂ­vel do cluster, com vĂĄrios **contĂȘineres**. Nesses casos, Ă© melhor **construir uma imagem do zero** conforme descrito acima: [Construindo uma Imagem Docker para FastAPI](#construindo-uma-imagem-docker-para-fastapi).
+
+Essa imagem seria Ăștil principalmente nos casos especiais descritos acima em [ContĂȘineres com MĂșltiplos Processos e Casos Especiais](#contĂȘineres-com-mĂșltiplos-processos-e-casos-Especiais). Por exemplo, se sua aplicação for **simples o suficiente** para que a configuração padrĂŁo de nĂșmero de processos com base na CPU funcione bem, vocĂȘ nĂŁo quer se preocupar com a configuração manual da replicação no nĂ­vel do cluster e nĂŁo estĂĄ executando mais de um contĂȘiner com seu aplicativo. Ou se vocĂȘ estiver implantando com **Docker Compose**, executando em um Ășnico servidor, etc.
+
+## Deploy da Imagem do ContĂȘiner
+
+Depois de ter uma imagem de contĂȘiner (Docker), existem vĂĄrias maneiras de implantĂĄ-la.
+
+Por exemplo:
+
+* Com **Docker Compose** em um Ășnico servidor
+* Com um cluster **Kubernetes**
+* Com um cluster Docker Swarm Mode
+* Com outra ferramenta como o Nomad
+* Com um serviço de nuvem que pega sua imagem de contĂȘiner e a implanta
+
+## Imagem Docker com Poetry
+
+Se vocĂȘ usa <a href="https://python-poetry.org/" class="external-link" target="_blank">Poetry</a> para gerenciar as dependĂȘncias do seu projeto, pode usar a construção multi-estĂĄgio do Docker:
+
+```{ .dockerfile .annotate }
+# (1)
+FROM python:3.9 as requirements-stage
+
+# (2)
+WORKDIR /tmp
+
+# (3)
+RUN pip install poetry
+
+# (4)
+COPY ./pyproject.toml ./poetry.lock* /tmp/
+
+# (5)
+RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
+
+# (6)
+FROM python:3.9
+
+# (7)
+WORKDIR /code
+
+# (8)
+COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt
+
+# (9)
+RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
+
+# (10)
+COPY ./app /code/app
+
+# (11)
+CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
+```
+
+1. Esse Ă© o primeiro estĂĄgio, ele Ă© chamado `requirements-stage`.
+
+2. Defina `/tmp` como o diretĂłrio de trabalho atual.
+
+    Aqui Ă© onde geraremos o arquivo `requirements.txt`
+
+3. Instale o Poetry nesse estĂĄgio do Docker.
+
+4. Copie os arquivos `pyproject.toml` e `poetry.lock` para o diretĂłrio `/tmp`.
+
+    Porque estĂĄ usando `./poetry.lock*` (terminando com um `*`), nĂŁo irĂĄ falhar se esse arquivo ainda nĂŁo estiver disponĂ­vel.
+
+5. Gere o arquivo `requirements.txt`.
+
+6. Este Ă© o estĂĄgio final, tudo aqui serĂĄ preservado na imagem final do contĂȘiner.
+
+7. Defina o diretĂłrio de trabalho atual como `/code`.
+
+8. Copie o arquivo `requirements.txt` para o diretĂłrio `/code`.
+
+    Essse arquivo sĂł existe no estĂĄgio anterior do Docker, Ă© por isso que usamos `--from-requirements-stage` para copiĂĄ-lo.
+
+9. Instale as dependĂȘncias de pacote do arquivo `requirements.txt` gerado.
+
+10. Copie o diretĂłrio `app` para o diretĂłrio `/code`.
+
+11. Execute o comando `uvicorn`, informando-o para usar o objeto `app` importado de `app.main`.
+
+!!! tip
+    Clique nos nĂșmeros das bolhas para ver o que cada linha faz.
+
+Um **estĂĄgio do Docker** Ă© uma parte de um `Dockerfile` que funciona como uma **imagem temporĂĄria do contĂȘiner** que sĂł Ă© usada para gerar alguns arquivos para serem usados posteriormente.
+
+O primeiro estĂĄgio serĂĄ usado apenas para **instalar Poetry** e para **gerar o `requirements.txt`** com as dependĂȘncias do seu projeto a partir do arquivo `pyproject.toml` do Poetry.
+
+Esse arquivo `requirements.txt` serĂĄ usado com `pip` mais tarde no **prĂłximo estĂĄgio**.
+
+Na imagem final do contĂȘiner, **somente o estĂĄgio final** Ă© preservado. Os estĂĄgios anteriores serĂŁo descartados.
+
+Quando usar Poetry, faz sentido usar **construçÔes multi-estĂĄgio do Docker** porque vocĂȘ realmente nĂŁo precisa ter o Poetry e suas dependĂȘncias instaladas na imagem final do contĂȘiner, vocĂȘ **apenas precisa** ter o arquivo `requirements.txt` gerado para instalar as dependĂȘncias do seu projeto.
+
+EntĂŁo, no prĂłximo (e Ășltimo) estĂĄgio, vocĂȘ construiria a imagem mais ou menos da mesma maneira descrita anteriormente.
+
+### Por trĂĄs de um proxy de terminação TLS - Poetry
+
+Novamente, se vocĂȘ estiver executando seu contĂȘiner atrĂĄs de um proxy de terminação TLS (balanceador de carga) como Nginx ou Traefik, adicione a opção `--proxy-headers` ao comando:
+
+```Dockerfile
+CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
+```
+
+## Recapitulando
+
+Usando sistemas de contĂȘiner (por exemplo, com **Docker** e **Kubernetes**), torna-se bastante simples lidar com todos os **conceitos de implantação**:
+
+* HTTPS
+* Executando na inicialização
+* ReinĂ­cios
+* Replicação (o nĂșmero de processos rodando)
+* MemĂłria
+* Passos anteriores antes de inicializar
+
+Na maioria dos casos, vocĂȘ provavelmente nĂŁo desejarĂĄ usar nenhuma imagem base e, em vez disso, **construir uma imagem de contĂȘiner do zero** baseada na imagem oficial do Docker Python.
+
+Tendo cuidado com a **ordem** das instruçÔes no `Dockerfile` e o **cache do Docker**, vocĂȘ pode **minimizar os tempos de construção**, para maximizar sua produtividade (e evitar a tĂ©dio). đŸ˜Ž
+
+Em alguns casos especiais, vocĂȘ pode querer usar a imagem oficial do Docker para o FastAPI. đŸ€“
index fdef810fa17daf187b2dab8992824c317b0322d5..0858de0624183d91360d0a467ebb7b0b68bc7223 100644 (file)
@@ -87,6 +87,7 @@ nav:
   - deployment/versions.md
   - deployment/https.md
   - deployment/deta.md
+  - deployment/docker.md
 - alternatives.md
 - history-design-future.md
 - external-links.md