Docker构建时RUN指令未创建SQLite数据库(Python/PDM)问题排查
问题:Docker构建时RUN指令无法创建SQLite数据库文件,但容器内手动执行可成功
我期望启动容器时自动创建新的SQLite数据库文件,但构建镜像时执行RUN pdm run -v src/db_setup.py步骤未生成该文件。不过进入容器后手动执行pdm run src/db_setup.py可成功创建数据库文件。
启动容器使用的命令:
docker run --name de_pdm_container -p 8080:8080 -dt -v .:/app de_pdm
Dockerfile
FROM python:3.11-bookworm WORKDIR /app # install PDM RUN pip install -U pdm # disable update check ENV PDM_CHECK_UPDATE=false COPY pdm.lock pyproject.toml ./ RUN pdm install COPY ./src ./src COPY ./tests ./tests COPY .devcontainer .devcontainer RUN apt-get update RUN apt-get install -y sqlite3 libsqlite3-dev RUN pdm run -v src/db_setup.py EXPOSE 8080 CMD ["pdm", "run", "uvicorn", "src.de_pdm.__init__:app", "--host", "0.0.0.0", "--port", "8080", "--reload"]
db_setup.py
import sqlite3 con = sqlite3.connect("test.db") cursor = con.cursor() con.set_trace_callback(print) cursor.execute("DROP TABLE IF EXISTS tb;") con.commit() cursor.execute(""" CREATE TABLE tb( country VARCHAR(50), country_code VARCHAR(2), year INT, estimated_population_number INT, estimated_prevalence INT ); """) con.commit() con.close()
原因及解决办法
- 核心原因:你启动容器时用了
-v .:/app本地目录挂载,这个操作会把容器内/app目录的所有内容替换成你主机本地的目录。构建镜像时RUN指令生成的test.db是存在镜像的/app目录里的,但挂载后容器内的/app被本地目录覆盖,所以看不到这个文件。 - 验证方法:去掉
-v .:/app参数启动容器,进入容器后就能找到test.db,这说明构建时确实生成了文件,只是被挂载覆盖了。 - 解决思路:
- 若不需要本地挂载同步代码,直接删掉
-v .:/app参数即可,容器会使用镜像内的/app目录,构建时生成的数据库文件会保留。 - 若需要本地挂载,把数据库文件放到挂载目录外的路径,比如修改
db_setup.py里的连接路径为/data/test.db,同时在Dockerfile里加一行RUN mkdir /data,这样构建生成的数据库就不会被挂载覆盖;也可以在启动容器时单独挂载数据库目录:-v ./data:/data。 - 把数据库创建逻辑放到容器启动时执行,修改CMD指令,先执行建库脚本再启动服务,这样每次启动容器都会重新创建数据库,也不受挂载影响:
CMD ["sh", "-c", "pdm run src/db_setup.py && pdm run uvicorn src.de_pdm.__init__:app --host 0.0.0.0 --port 8080 --reload"]
- 若不需要本地挂载同步代码,直接删掉
内容的提问来源于stack exchange,提问作者A. L
相关产品推荐
相关产品推荐

