使用 Docker 构建和部署 FastAPI 程序,可以保证环境一致性,也方便程序扩展和移植。同时也可以用到官方预制的Docker镜像。

创建FastAPI 应用

初始应用的目录结构如下:

1
2
3
4
5
6
.
├── app
│   ├── __init__.py
│   └── main.py
├── Dockerfile
└── requirements.txt

main.py 示例程序如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from typing import Union

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文件内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 
FROM python:3.9

# 
WORKDIR /code

# 
COPY ./requirements.txt /code/requirements.txt

# 安装需求文件中的包依赖项。

# --no-cache-dir 选项告诉 pip 不要在本地保存下载的包,因为只有当 pip 再次运行以安装相同的包时才会这样,但在与容器一起工作时情况并非如此。

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"]

构建Docker镜像

1
docker build -t my-fastapi-app .

运行Docker容器

1
docker run -d -p 80:80 my-fastapi-app

FastAPI 官方 Docker 镜像

带有 Gunicorn 的官方 Docker 镜像 - Uvicorn

使用官方Docker镜像 tiangolo/uvicorn-gunicorn-fastapi 构建FastAPI应用

Dockerfile文件内容如下:

1
2
3
4
5
6
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

分阶段构建体积更小的镜像

分阶段来构建应用,分离构建环境和运行环境,减小最终应用镜像大小。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 阶段一:构建环境
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 阶段二:运行环境
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
COPY . /app
EXPOSE 80
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

Docker 中 FastAPI 的健康检查

在Docker镜像中添加健康检查机制,确保应用正常运行

1
2
3
4
5
6
7
FROM python:3.9-slim
WORKDIR /app
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl --fail http://localhost:80/ || exit 1
COPY . /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

HEALTHCHECK 指令设置容器健康,第30秒检查,每次10秒超时,连续失败3次,则执行exit 1

参考