1. 前情提要
此前第一个项目中,我主要负责将一个视频质量评估程序封装到Docker容器镜像内,然后交给后端部署。
但是此前因为没有足够的文档意识,导致学了一遍菜鸟教程中的Docker后,就考"面向互联网编程"实现了。
但是如今甲方又需要将Python版本从3.7提升到3.12(甲方真的NT,非要我们修改镜像里的Python版本,但是又不得不做,所以特此记录一下,下次再次使用Docker容器时,可以以此为参考。)
2. 安装Docker
因为我已经不再使用原来的Ubuntu服务器,换了一台机器,所以需要重新安装Docker,
Bash
curl -fsSL https://test.docker.com -o test-docker.sh # 下载脚本
sudo sh test-docker.sh # 执行脚本安装
这就遇到了第一个坑:
2.1. Q1:执行不了官方脚本
2.1.1. 锁被其他进程拿着
我直接一个kill
把这个进程干掉,只要我与服务器的SSH连接不断,管他是什么进程。
Bash
sudo kill 4975
于是 好家伙,一波刚平,一波又起。
2.1.2. 没有找到cudnn的一个Release文件
参考链接:t.csdn.cn/KbD5V
这是有可能Shell脚本里面执行了类似:
Bash
sudo apt-get update
得到的结果
解决方法实际上就是把这个对应的搜索索引删掉,不让它找了。
Bash
cd /etc/apt/sources.list.d
ls -a
sudo rm -rf cudnn-local-ubuntu2204-8.6.0.163.list
sudo apt-get update
果然避开了这个坑。
2.2. 终于安装成功!
Bash
(base) ➜ sudo sh test-docker.sh
# Executing docker install script, commit: e5543d473431b782227f8908005543bb4389b8de
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c install -m 0755 -d /etc/apt/keyrings
+ sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
+ sh -c chmod a+r /etc/apt/keyrings/docker.gpg
+ sh -c echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy test" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-ce-rootless-extras docker-buildx-plugin >/dev/null
+ sh -c docker version
Client: Docker Engine - Community
Version: 24.0.6
API version: 1.43
Go version: go1.20.7
Git commit: ed223bc
Built: Mon Sep 4 12:31:44 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.6
API version: 1.43 (minimum version 1.12)
Go version: go1.20.7
Git commit: 1a79695
Built: Mon Sep 4 12:31:44 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.22
GitCommit: 8165feabfdfe38c65b599c4993d227328c231fca
runc:
Version: 1.1.8
GitCommit: v1.1.8-0-g82f18fe
docker-init:
Version: 0.19.0
GitCommit: de40ad0
================================================================================
To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:
dockerd-rootless-setuptool.sh install
Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/
WARNING: Access to the remote API on a privileged Docker daemon is equivalent
to root access on the host. Refer to the 'Docker daemon attack surface'
documentation for details: https://docs.docker.com/go/attack-surface/
================================================================================
验证一下,如果是下面这样说明是对了:
Bash
(base) ➜ sudo docker run hello-world
[sudo] neon 的密码:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Pull complete
Digest: sha256:4f53e2564790c8e7856ec08e384732aa38dc43c52f02952483e3f003afbf23db
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
3. 下载现成的Docker镜像
我并不是从0开始构建自己的镜像的,而是从网上down一个基本的镜像,然后在上面堆东西。 那么查找现成镜像的网址是:hub.docker.com/search?q= 因为我们的项目是依赖于C++版本的OpenCV的, 所以我直接反手拉一个opencv-docker
。
bash
sudo docker pull opencvcourses/opencv-docker
太烦了,先不管,先试试能不能在原始镜像中装Python3.12:
4. 尝试在原始镜像中换Python版本
这时候需要一大堆的依赖,所以要一个一个安装:
bash
apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget
4.1. E: Unale to locate package xxxx
但是遇到很多下面的这种Error:
Bash
E: Unale to locate package xxxx
所以我们先解决这个问题, 参考: t.csdn.cn/18xut 把ubuntu主系统中的/etc/apt/sources.list文件复制进docker的/etc/apt/sources.list,然后更新源即可。
bash
apt update
这下就可以了。
4.2. 下载Python的压缩包
t.csdn.cn/1PGDJ 然后通过docker的文件传输命令, 将这个压缩包放进docker里。
4.3. 解压与安装
bash
tar -xf Python-3.12.0.0a1.tar.xz
cd Python-3.12.0.0a1
./configure --enable-optimizations
make -j 2
make altinstall
非常意外的没什么报错,众所周知cmake is a bullshit.
安装的位置如果没有特别指定的话应该就是$HOME/.python
所以我们直接用最美丽的方法来指定版本:
bash
update-alternatives --install /usr/local/bin/python3 python3 $HOME/.python/3.12.0/bin/python3 100
然后通过
bash
python --version
就可以看到了我们的python的版本就切换好了。
但是奇怪的是虽然在控制台显示Python版本是正确的,但是在执行python脚本时还是优先选择原来的Python3.7.8的依赖库,所以我一怒之下,直接删除了/usr/local/lib/python3.7
这个目录。
就可以了好像。 具体更科学的方法还是之后有时间再探索吧。
5. 打包原来的容器得到新镜像
exit
之后,
bash
sudo docker ps -a # 查找所有正在运行的容器,复制id。
sudo docker commit -m="python1.12" -a="neonho" 0ba001f9a3a2 neon_vqa1:1.3 # 生成1.3版本的镜像。
同样的, 我们用这个镜像实例化一个容器,进入这个容器,并执行我们的功能发现没有问题。
对镜像进行打包。
bash
sudo docker save > neon_vqa1-3.tar neon_vqa1:1.3
然后就是等。。。好像我的镜像变大了好多, 不知道是什么原因。 还是tar导出后再看看吧。