目标:
学习怎样在docker中安装部署FastAPI,完成项目结构的搭建以及hello world的运行
背景:
公司内服务器资源有限,为了共享算力资源,同时又能隔离运行环境,因此采用了docker部署的方式,进行各种开发测试。网上虽然已有集成fastapi+uvicorn+gunicorn,自己动手,可以了解更多细节,以及更深度的定制,从而学习怎样自定义镜像文件以及启动docker。
实现过程:
1、安装docker(系统已默认安装,可参照网上教程,以后另外再补记)
2、安装python。选用了3.11版
3、安装pycharm 社区版。
4、建立项目文件夹
project:my_fastapi
====app (目录)
----main.py
----requirements.txt
====docker (目录)
----Dockerfile
----docker-compose.yaml
5、编辑 main.py
import os
import sys
from multiprocessing import freeze_support
import uvicorn
from fastapi import FastAPI, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
upload_files_save_path = os.environ["UPLOAD_FILE"] if "UPLOAD_FILE" in os.environ else "/upload"
@asynccontextmanager
async def lifespan(app: FastAPI):
# 初始化阶段
print('初始化成功..')
yield
# 清理阶段
print('卸载成功..')
app = FastAPI(root_path="/aiCentre"
, lifespan=lifespan
) # aicentre为nginx中api路由名
# 启用CORS支持
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"], # 或者只列出 ["POST", "GET", "OPTIONS", ...] 等
allow_headers=["*"],
)
# 路由
@app.get("/")
async def read_root():
return {"message": "Hello World!"}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
file_location = f"files/{file.filename}"
with open(file_location, "wb+") as file_object:
file_object.write(await file.read())
return {"info": f"file '{file.filename}' saved at '{file_location}'",}
if __name__ == "__main__":
freeze_support()
uvicorn.run('main:app', host="0.0.0.0", port=8080, reload=True, workers=1)
#current_dir = os.path.dirname(os.path.realpath(__file__))
# 将项目根目录添加到 Python 路径中
#sys.path.append(current_dir)
# print(upload_files_save_path)
6、用pip freeze命令生成python库文件列表,用于移植。
pip freeze > requirements.txt
annotated-types==0.7.0 anyio==4.9.0 click==8.1.8 colorama==0.4.6 fastapi==0.115.12 h11==0.14.0 idna==3.10 pydantic==2.11.1 pydantic_core==2.33.0 python-multipart==0.0.20 sniffio==1.3.1 starlette==0.46.1 typing-inspection==0.4.0 typing_extensions==4.13.0 uvicorn==0.34.0
7、编写 Dockerfile
# 建立 python3.11 环境 # FROM python:3.11 FROM docker.1ms.run/python:3.11 # 设置pip源为国内源 # COPY pip.conf /root/.pip/pip.conf # 镜像作者云无碍 LABEL maintainer="yunwuai <xxx@yyyy.zzzzz>" # 在容器内/var/www/html/下创建 mysite1文件夹 # RUN mkdir -p /var/www/html/mysite1 # 将当前目录文件加入到容器工作目录中(. 表示当前宿主机目录) # ADD . /var/www/html/mysite1 RUN mkdir -p /app RUN mkdir -p /upload COPY . /app # 设置容器内工作目录 WORKDIR /app # RUN echo $PWD # 利用 pip 安装依赖 # 设置安装依赖包的镜像以及安装相关的依赖包,需要安装的依赖包以及版本提前在requirements.txt文件里写出来 RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ RUN pip install -r /app/requirements.txt # RUN pip3 install pandas numpy moviepy pydub matplotlib python-multipart uvicorn # 设置 python 环境变量 ENV PYTHON_ENV_TEST=/app # Run the start script, it will check for an /app/prestart.sh script (e.g. for migrations) # And then will start Gunicorn with Uvicorn # 声明运行时的端口 EXPOSE 8080 # 运行Gunicorn服务器 # docker build -t my_fastapi . CMD ["python","/app/main.py"]
在app目录下运行
docker build -t my_fastapi:test -f ..\docker\Dockerfile .
(最后有一个“.”号,这个很重要,代表当前目录,小白复制网上的代码时,很容易遗漏)
或在项目目录下运行:
docker build -t my_fastapi:test -f docker\Dockerfile app
8、编写docker-compose.yaml
services: fastapi: image: my_fastapi:test ports: - 8181:8080 environment: ENV_PARAMS: test_param MODEL_NAME: fastmodel
启动docker
docker-compose.exe -f docker\docker-compose.yaml up -d
总结:
1、docker 运行时的端口镜像,前后顺序不要写错 是先宿主机再容器 即 -p 宿主机端口:容器内端口
2、docker build 时,最后一个参数为dockerfile中的“当前目录”,当出现文件无法复制或找不到文件时,一般都是当前路径设置有误.
3,启动docker-compose报错,很多时候是因为参数顺序搞错,把up -d放到 -f前面去了。up -d 一般在命令最后
4、fastAPI自带swagger功能,可以通过 http://127.0.0.1:8181/docs 和 http://127.0.0.1:8181/redoc进行访问和测试