如何将带预制数据的SQLite与FastAPI应用打包到同一Docker容器
最优方案选型:直接使用内置SQLite数据库(优先推荐)
你的业务场景为纯只读查询,无写入需求,该方案是最适配需求的选择:
- SQLite不需要额外运行独立的数据库服务进程,容器内仅需运行FastAPI/Uvicorn单个进程,资源开销更低,运行稳定性更高
- 数据库本身为单个独立文件,直接打包到镜像内即可,100%不依赖任何外部资源,完全符合EC2/Fargate黑盒部署的要求
- 千万行级别的数据量SQLite完全可以支撑,提前做好查询索引优化后,性能完全可以匹配原有MySQL的只读查询效率
具体实现步骤
- 先在本地生成包含完整表结构和700-1000万行数据的SQLite数据库文件(可命名为
data.db),根据你的业务查询逻辑提前建好对应索引,本地测试查询性能符合要求后再进行打包操作 - 将
data.db放到你的FastAPI项目根目录下,修改数据库连接配置,直接指向本地SQLite文件即可,Python中连接字符串示例:sqlite:///./data.db - 编写Dockerfile直接将所有依赖、代码、数据库文件打包到镜像内即可,不需要额外配置数据库启动逻辑,参考Dockerfile如下:
# 基于官方Python slim镜像构建,控制镜像体积 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 先拷贝依赖文件安装,利用Docker层缓存减少重复构建耗时 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 拷贝项目代码、SQLite数据库文件到镜像内部 COPY . . # 暴露服务端口 EXPOSE 8000 # 启动Uvicorn服务 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
如果数据库文件体积较大,也可以把数据导入逻辑放到Docker构建阶段,直接在构建过程中从原MySQL导出数据并生成SQLite文件,不需要本地提前生成再拷贝。
保留MySQL的备选方案
如果因为查询语法兼容性等原因不想切换为SQLite,也可以将MySQL内置到同一个容器中,需要用进程管理工具同时管理MySQL和Uvicorn进程:
- 镜像构建阶段先安装MySQL服务,启动临时MySQL实例完成全量数据导入,关闭实例后将MySQL数据目录内置到镜像中
- 安装supervisor作为进程管理工具,配置同时启动MySQL和Uvicorn的规则,设置进程异常自动重启
- 调整MySQL配置,关闭二进制日志、禁用持久化刷盘等写入相关功能,提升只读性能,同时避免运行过程中修改数据
该方案的缺点是镜像体积更大、进程管理复杂度更高、资源开销更高,稳定性和易用性低于SQLite方案。
部署注意事项
- 镜像推送到AWS ECR后,EC2/Fargate部署不需要挂载任何外部存储卷,直接启动镜像即可正常运行,完全不依赖外部资源
- 只读场景下SQLite天然支持并发读安全,不需要担心多请求访问的冲突问题
- 后续需要更新数据时,仅需替换SQLite文件重新构建镜像,推送新版本部署即可
内容的提问来源于stack exchange,提问作者Carlos Alanis
相关产品推荐
相关产品推荐

