uv管理的python项目怎么打包成docker部署发布上线
一、问题和需求
uv管理的Python项目打包成docker报错,问了AI得到下面的结论。
解决思路:把uv管理的python项目,导出成普通的 requirements.txt 文件,然后在容器里面按照pip安装包的项目来操作。
二、解决步骤
2.1 获取requirements.txt
在你的项目根目录下,打开终端,确保你已经激活了 uv 创建的虚拟环境(如果之前使用了的话),然后执行:
uv pip freeze > requirements.txt
这个命令会将当前虚拟环境中所有已安装的包及其精确版本导出到项目目录的 requirements.txt
文件中
2.2 构建dockerfile
比如我的uv 管理的python项目,正常启动项目是 先到~/myproject 这个工作目录,使用 uv run -m mian 命令直接启动。然后就可以启动对应的端口8001。这样的话,我们已经把这个项目变成了pip 管理的项目,就不用uv 了,按照正常的pip项目的话,启动命令应该改成python -m main
# 确定Python环境
FROM python:3.10-slim# 设置容器内的绝对工作目录,替代您本地的 ~/myproject
WORKDIR /myproject# 先将依赖文件复制到工作目录
COPY requirements.txt .# 安装项目依赖包(使用国内镜像源可加速下载)
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple# 将当前目录下的所有项目文件复制到容器的 /myproject 目录
COPY . .# 暴露应用运行的端口 (8001)
EXPOSE 8001# 定义容器启动后在工作目录 /myproject 下执行的命令
CMD ["python", "-m", "main"]
这里使用官方 Python 精简版作为基础镜像会让镜像小很多。实测从1.8G变成0.8G。
Dockerfile 指令 | 作用 | 当前示例说明 |
---|---|---|
| 指定构建所基于的基础镜像 | 使用官方 |
| 设置容器内部的工作目录,后续指令将在此目录下执行 | 设置为 |
| 将宿主机上的文件或目录复制到镜像中 | 先将 |
| 在构建过程中执行命令,常用于安装软件包、配置环境等 | 根据 |
| 再次使用,复制项目所有文件 | 将当前目录所有文件复制到镜像的 |
| 声明容器运行时打算监听的网络端口 | 声明容器内应用使用 8001 端口 |
| 指定容器启动时执行的默认命令 (Dockerfile 中多个 CMD 仅最后一个生效) | 容器启动时执行 |
2.3 创建.dockerignore文件
在项目根目录创建 .dockerignore
文件,排除不必要的文件,能有效减小镜像体积,加速构建过程
常见的忽略文件如下:
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv
*.log
.git
.gitignore
.DS_Store
.env
2.4 构建 Docker 镜像
在包含 Dockerfile
的项目根目录下执行:
docker build -t myproject:2.0.0 .
-
-t
myproject:2.0.0为镜像指定名称和标签。 -
.
表示构建上下文是当前目录。
2.5 构建容器
docker run -d -p 8001:8001 --name my-bot myproject:2.0.0
# -d: 后台运行
# -p 8001:8001: 将宿主机的8001端口映射到容器的8001端口
# --name my-bot: 给容器起个名字
运行后,你可以通过 docker logs my-bot
查看容器日志,确认应用是否正常启动并在 8001 端口监听。
2.6 检查docker容器
docker ps -a
三、 遇到问题
3.1 容器占用
构建容器的时候遇到容器占用的问题
docker: Error response from daemon: Conflict. The container name "/my-bot" is already in use by container "52add4f9995f5a66d9ff2d7a415373a7a6dbd528347cbd5a9c6f5da5e8d49c97". You have to remove (or rename) that container to be able to reuse that name. See 'docker run --help'.
# 强制删除名为 my-bot 的容器(包括正在运行的) 这样会造成虚挂镜像的问题
docker rm -f my-bot
# 删除后,再次尝试运行你的容器
docker run -d -p 8001:8001 --name my-bot myproject:2.0.0
3.2 出现 <none>
镜像
为什么出现 <none> 镜像?
当构建一个新的 Docker 镜像,并且指定的标签与本地已有的镜像重名时,Docker 会将旧的镜像的标签替换为 <none>,使得旧镜像成为悬挂镜像。
在 Docker 构建过程中,如果某一步失败,Docker 可能会留下一个空的镜像,这也是 <none> 镜像的一个来源。
如果您使用 docker save 保存镜像时没有指定镜像名称和标签,而是使用的镜像ID,那么加载(docker load)这个镜像后,它的 REPOSITORY 和 TAG 都会变成 <none>。
如果您强制删除了正在被容器使用的镜像,那么这个镜像也会变成 <none>。
您可以使用 docker images -f "dangling=true"
命令来查找所有的悬挂镜像。
docker images -f "dangling=true"
docker rmi $(docker images -f "dangling=true" -q)
3.3 删除镜像
列出镜像
docker images
# 删除单个镜像
docker rmi <镜像ID或名称>
# 示例:docker rmi d1e017099d5e# 删除多个镜像
docker rmi <镜像ID1> <镜像ID2> <镜像ID3>
如果镜像无法删除,大概率是镜像的示例容器正在使用
docker ps
docker inspect <容器ID或名称> # 可以查看容器的信息,由哪个镜像实例化的
docker stop <容器ID或名称>
docker rm <容器ID或名称>
四、参考文章
Python项目打包并部署到Docker详细步骤_python_脚本之家
Dockerfile指令全解-CSDN博客
Docker中出现tag显示none镜像的处理方法_docker tag none-CSDN博客