diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md
new file mode 100644
index 000000000..42c31db29
--- /dev/null
+++ b/docs/pt/docs/deployment/docker.md
@@ -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 **Docker**. 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).
+
+
+
+Visualização do Dockerfile đ
+
+```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"]
+```
+
+
+
+## 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
Docker Hub pĂșblico com **imagens de contĂȘiner oficiais** prĂ©-prontas para diversas ferramentas, ambientes, bancos de dados e aplicaçÔes.
+
+Por exemplo, hĂĄ uma
Imagem Python oficial.
+
+E existe muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo:
+
+*
PostgreSQL
+*
MySQL
+*
MongoDB
+*
Redis, 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:
+
+
+
+```console
+$ pip install -r requirements.txt
+---> 100%
+Successfully installed fastapi pydantic uvicorn
+```
+
+
+
+!!! 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:
+
+
+
+```console
+$ docker build -t myimage .
+
+---> 100%
+```
+
+
+
+!!! 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:
+
+
+
+```console
+$ docker run -d --name mycontĂȘiner -p 80:80 myimage
+```
+
+
+
+## Verifique
+
+VocĂȘ deve ser capaz de verificar isso no URL do seu contĂȘiner Docker, por exemplo:
http://192.168.99.100/items/5?q=somequery ou
http://127.0.0.1/items/5?q=somequery (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
http://192.168.99.100/docs ou
http://127.0.0.1/docs (ou equivalente, usando seu host Docker).
+
+VocĂȘ verĂĄ a documentação interativa automĂĄtica da API (fornecida pelo
Swagger UI):
+
+
+
+## Documentação alternativa da API
+
+E vocĂȘ tambĂ©m pode ir para
http://192.168.99.100/redoc ou
http://127.0.0.1/redoc (ou equivalente, usando seu host Docker).
+
+VocĂȘ verĂĄ a documentação alternativa automĂĄtica (fornecida pela
ReDoc):
+
+
+
+## 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
Traefik, 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
cluster 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
Init Container.
+
+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).
+
+*
tiangolo/uvicorn-gunicorn-fastapi.
+
+!!! 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
**passos anteriores antes de iniciar** com um script.
+
+!!! tip
+ Para ver todas as configuraçÔes e opçÔes, vå para a pågina da imagem Docker:
tiangolo/uvicorn-gunicorn-fastapi.
+
+### 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
Poetry 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. đ€
diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml
index fdef810fa..0858de062 100644
--- a/docs/pt/mkdocs.yml
+++ b/docs/pt/mkdocs.yml
@@ -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
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index afdc94874..037d9804b 100644
--- a/fastapi/__init__.py
+++ b/fastapi/__init__.py
@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
-__version__ = "0.87.0"
+__version__ = "0.88.0"
from starlette import status as status
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index 3df5ccfc8..4c817d5d0 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -105,10 +105,10 @@ def check_file_field(field: ModelField) -> None:
assert parse_options_header
except ImportError:
logger.error(multipart_incorrect_install_error)
- raise RuntimeError(multipart_incorrect_install_error)
+ raise RuntimeError(multipart_incorrect_install_error) from None
except ImportError:
logger.error(multipart_not_installed_error)
- raise RuntimeError(multipart_not_installed_error)
+ raise RuntimeError(multipart_not_installed_error) from None
def get_param_sub_dependant(
diff --git a/fastapi/encoders.py b/fastapi/encoders.py
index 6bde9f4ab..2f95bcbf6 100644
--- a/fastapi/encoders.py
+++ b/fastapi/encoders.py
@@ -157,7 +157,7 @@ def jsonable_encoder(
data = vars(obj)
except Exception as e:
errors.append(e)
- raise ValueError(errors)
+ raise ValueError(errors) from e
return jsonable_encoder(
data,
include=include,
diff --git a/fastapi/utils.py b/fastapi/utils.py
index b94dacecc..b15f6a2cf 100644
--- a/fastapi/utils.py
+++ b/fastapi/utils.py
@@ -89,7 +89,7 @@ def create_response_field(
except RuntimeError:
raise fastapi.exceptions.FastAPIError(
f"Invalid args for response field! Hint: check that {type_} is a valid pydantic field type"
- )
+ ) from None
def create_cloned_field(
diff --git a/pyproject.toml b/pyproject.toml
index 9549cc47d..be3080ae8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,7 +39,7 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP",
]
dependencies = [
- "starlette==0.21.0",
+ "starlette==0.22.0",
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0",
]
dynamic = ["version"]
@@ -53,7 +53,7 @@ test = [
"pytest >=7.1.3,<8.0.0",
"coverage[toml] >= 6.5.0,<7.0",
"mypy ==0.982",
- "ruff ==0.0.114",
+ "ruff ==0.0.138",
"black == 22.10.0",
"isort >=5.0.6,<6.0.0",
"httpx >=0.23.0,<0.24.0",
@@ -83,11 +83,11 @@ doc = [
"mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0",
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x
# "typer-cli >=0.0.12,<0.0.13",
- "typer[all] >=0.6.1,<0.7.0",
+ "typer[all] >=0.6.1,<0.8.0",
"pyyaml >=5.3.1,<7.0.0",
]
dev = [
- "ruff ==0.0.114",
+ "ruff ==0.0.138",
"uvicorn[standard] >=0.12.0,<0.19.0",
"pre-commit >=2.17.0,<3.0.0",
]
@@ -168,6 +168,7 @@ select = [
ignore = [
"E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults
+ "C901", # too complex
]
[tool.ruff.per-file-ignores]
@@ -178,7 +179,8 @@ ignore = [
"docs_src/dependencies/tutorial010.py" = ["F821"]
"docs_src/custom_response/tutorial007.py" = ["B007"]
"docs_src/dataclasses/tutorial003.py" = ["I001"]
-
+"docs_src/path_operation_advanced_configuration/tutorial007.py" = ["B904"]
+"docs_src/custom_request_and_route/tutorial002.py" = ["B904"]
[tool.ruff.isort]
known-third-party = ["fastapi", "pydantic", "starlette"]
diff --git a/scripts/docs.py b/scripts/docs.py
index 622ba9202..e0953b8ed 100644
--- a/scripts/docs.py
+++ b/scripts/docs.py
@@ -284,7 +284,9 @@ def build_all():
continue
langs.append(lang.name)
cpu_count = os.cpu_count() or 1
- with Pool(cpu_count * 2) as p:
+ process_pool_size = cpu_count * 4
+ typer.echo(f"Using process pool size: {process_pool_size}")
+ with Pool(process_pool_size) as p:
p.map(build_lang, langs)
diff --git a/tests/test_starlette_urlconvertors.py b/tests/test_starlette_urlconvertors.py
index 5a980cbf6..5ef1b819c 100644
--- a/tests/test_starlette_urlconvertors.py
+++ b/tests/test_starlette_urlconvertors.py
@@ -1,4 +1,4 @@
-from fastapi import FastAPI, Path
+from fastapi import FastAPI, Path, Query
from fastapi.testclient import TestClient
app = FastAPI()
@@ -19,6 +19,11 @@ def path_convertor(param: str = Path()):
return {"path": param}
+@app.get("/query/")
+def query_convertor(param: str = Query()):
+ return {"query": param}
+
+
client = TestClient(app)
@@ -45,6 +50,13 @@ def test_route_converters_path():
assert response.json() == {"path": "some/example"}
+def test_route_converters_query():
+ # Test query conversion
+ response = client.get("/query", params={"param": "Qué tal!"})
+ assert response.status_code == 200, response.text
+ assert response.json() == {"query": "Qué tal!"}
+
+
def test_url_path_for_path_convertor():
assert (
app.url_path_for("path_convertor", param="some/example") == "/path/some/example"