在Ubuntu中使用Docker打包程序(Conda, pip)
使用docker打包开发完的包和程序,有一个很大的好处是,把系统当前的配置环境都完整保存下来。这样只要把docker的image文件发到其他电脑里,就可以快速部署,完全不需要考虑环境配置的问题,特别对于python的程序来说,环境配置一直是个头疼的问题。
1. Docker 安装
有两种选项,一种是默认存储库在Ubuntu上的Docker,另一种是官方存储库的Docker。
建议使用官方存储库的Docker,两种方法我都用过,第一种方法,很多时候在pull对应环境时,会出现名称不匹配的情况,找不到对应的库,但是用回官方的就没这个问题,少踩些坑。
以下配置过程是在Ubuntu18.04上测试的,其他版本可以搜一下,挺多的。
1)更新本地的软件列表数据库
sudo apt-get update
2)下载依赖项
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
- 添加GPG钥匙
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
4)安装Docker存储库
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
5)安装最新版Docker
sudo apt-get install docker-ce
6)测试
安装完后,可以运行一下docker指令
sudo docker --version
如果有返回当前版本说明安装应该没什么问题,也可以运行sudo docker images查看当前的镜像,但是刚装的docker,应该什么镜像也没有
2. 制作镜像image
在制作镜像前,需要三样东西:
- Package files: 就是你的程序,整个文件夹,接下来我都会以
GPT-SoVITS这个项目做列子 - environment.yml:由conda输出的环境配置文件,里面会列出所有用到的依赖项,当然里面会有些多余的,这个后面再说
- Dockerfile: 这个是一个脚本,怎么一步步把依赖库和启动程序构建好,别人run我们的image时,就会根据这个脚本启动
最终在同一路径下,有如图所示的这三个文件:

2.1 准备文件
然后说一下怎么准备上面这些文件:
1)首先第一个是package,这个就是我们的整个项目文件
2)然后是environment.yml,先进入conda的虚拟环境
conda activate your_env_name
然后使用指令输出环境配置文件
conda env export > environment.yml
这时第二个文件也准备好了。
3)写Dockerfile,先建一个Dockerfile,可以直接用指令touch Dockerfile,也可以手动自己添加,要注意的是,不需要加后缀,就用Dockerfile这个名字就行. 然后是内容,用我现在写的脚本做例子,也是有很多技巧的,以后可以慢慢学习,知道大概流程就行
# 使用一个轻量级的Miniconda基础镜像
FROM continuumio/miniconda3:latest# 设置工作目录在容器内
WORKDIR /app# 将从conda导出的 environment.yml 文件复制到容器的当前目录
COPY environment.yml .# 利用复制的配置文件创建Conda环境
RUN conda env create -f environment.yml# 激活环境并设置PATH,这样后续命令都会在使用此环境的前提下执行
# 将 `your_env_name` 替换为你的环境名
ENV PATH /opt/conda/envs/your_env_name/bin:$PATH# 将你的package源代码复制到容器的 /app 目录下
COPY . .# 设置容器启动时默认执行的命令,例如运行你的package
# 请根据你的package修改此命令,例如 `CMD ["python", "-m", "your_package"]`
WORKDIR /app/GPT-SoVITS
CMD ["python", "api.py", "-d", "cpu", "-a", "0.0.0.0", "-p", "9880", "-dr", "./test_data/test_video.wav", "-dt", "希望以后没有bug。", "-dl", "zh"]
上面的脚本注释里有说明。
PS:要注意的地方是,最后CMD里面,如果需要加入参数的,要用双引号“”一个个添加
同时,如果需要通过ip地址和端口处理服务的,如上面的 127.0.0.1:9880,要注意了,docker在容器内对外网卡地址是0.0.0.0,所以在写制作镜像时要注意把程序内部的地址改成0.0.0.0,不然就没办法通讯上了。
2.2 开始制作
1)先进入到上面准备好的三个文件所在的目录,然后运行以下指令制作镜像,-t后面的是这个镜像的名称,只能加一个/,不能加两个,一般前面是签名,后面写版本,最后:后面的是版本号
sudo docker build -t gptsovits/ubuntu18_py310:v1.0 .
其实在上面这个过程,会报各种依赖项无法安装,有些是ROS的依赖项和工具包,这些其实不是我上面这个包需要的依赖项,很奇怪,我配的这个conda环境是新建的,应该没包括ROS的东西才对,然后就需要把这些不需要的包,一个个去掉,这里也费了些功夫。
2)制作完镜像后,使用指令sudo docker images就可以查看这个镜像了

然后可以尝试运行它
sudo docker run -it --rm -p 9880:9880 gptsovits/ubuntu18_py310:v1.0
一切如预期运行就最好啦,当然如果发现启动没成功,其实可以进入到容器里debug,很多时候是因为路径问题,这个需要慢慢检查,使用如下指令就可以建立一个临时的docker容器进行debug,同时退出时缓存会被清除
sudo docker run -it --rm -p 9880:9880 --name gptsovits_debug gptsovits/ubuntu18_py310:v1.0 /bin/bash
2.3 保存和分享镜像
制作完成后,就可以把镜像打包,发送给别人了,也可以上传的docker hub上面
两个方案:
- 方案一:离线迁移
在源电脑上导出镜像
使用 docker save命令将镜像导出为一个 tar 归档文件。-o参数用于指定输出文件的路径和名称
sudo docker save -o my-image.tar <你的镜像名>:<标签>
示例:如果用我上面的镜像名为 gptsovits/ubuntu18_py310,标签为 v1.0,则命令为:
sudo docker save -o gptsovits-ubuntu18-py310-v1.0.tar gptsovits/ubuntu18_py310:v1.0
然后把压缩文件发到别的电脑即可。
在另一台电脑运行
sudo docker load -i gptsovits-ubuntu18-py310-v1.0.tar
解压完后,使用sudo docker images看看有没有加载成功,加载成功后,可以尝试运行它
sudo docker run -it --rm -p 9880:9880 gptsovits/ubuntu18_py310:v1.0
- 方案二:在线迁移
首先在源电脑上推送镜像到 Docker Hub
此时,需要先注册一个Docker Hub的账号,点这里进入官网
注册完后,还要先创建一个仓库,然后需要用到username和仓库名。
a. 登录 Docker Hub
在终端中执行以下命令,并输入你的 Docker Hub 用户名和密码进行登录sudo docker login
b. 为镜像打标签
为了能推送到 Docker Hub,你的镜像名称必须符合 你的用户名/仓库名:标签的格式。使用 docker tag命令为本地镜像创建一个符合要求的新标签
sudo docker tag <原镜像名>:<原标签> <你的DockerHub用户名>/<仓库名>:<标签>
示例:
sudo docker tag gptsovits/ubuntu18_py310:v1.0 yourusername/gptsovits-app:latest
c. 推送镜像
使用 docker push命令将打好标签的镜像推送到 Docker Hub
sudo docker push yourusername/gptsovits-app:latest
然后在目标电脑上拉取镜像
在目标电脑上,只需一条命令即可从 Docker Hub 拉取镜像
sudo docker pull yourusername/gptsovits-app:latest
3. 维护
3.1 管理存储空间
大家在使用过程中,会发现,一个image的size是很大的,所以如何管理docker的存储空间也是个重要的维护任务
| 清理目标 | 推荐命令 | 主要作用与注意事项 |
|---|---|---|
| 全面检查 | docker system df | 查看 Docker 整体磁盘使用情况,帮助定位哪个区域占用空间最多 |
| 构建缓存 | docker builder prune | 清理效果通常最显著。删除构建镜像时产生的中间缓存层 |
| 悬空镜像 | docker image prune | 删除标签为 的镜像(通常由新旧镜像替换产生) |
| 已停止的容器 | docker container prune | 删除所有已停止(Exited)的容器,一般可安全清理 |
| 未使用的数据卷 | docker volume prune | 清理前请确认,卷通常用于持久化重要数据(如数据库文件) |
| 一键清理(谨慎) | docker system prune | 一次性清理上述所有类型的未使用资源(镜像、容器、网络、构建缓存),不删除数据卷 |
3.2 删除镜像
查找所有容器(包括已停止的)
sudo docker ps -a
停止并删除与旧镜像相关的容器(将 <container_id> 替换为实际的容器ID)
sudo docker stop <container_id>
sudo docker rm <container_id>
删除镜像(将 <image_name> 和 替换为你的镜像名称和标签)
例如:sudo docker rmi my-app:latest
sudo docker rmi <image_name>:<tag>
