- 由 虚拟的现实创建于3月 06, 2025 需要 3 分钟阅读时间
简介
不知不觉,Docker 已经诞生十二年了。作为容器化技术的先驱,它早已成为了众多开发者和企业的必备工具。然而,随着 Docker 的不断发展,版本更新频繁带来的问题也日益凸显。
很多开发者可能都遇到过这样的困扰:明明之前运行得好好的容器,在更新 Docker 版本后突然就出现了各种奇怪的问题。有时是配置文件不兼容,有时是命令参数变化,有时甚至会影响到整个应用的稳定性。
更让人头疼的是,当你想要解决这些问题时,网上搜索到的许多文章要么已经过时,要么就是简单地复制粘贴一些错误的或者已经失效的命令。这不仅无法解决问题,反而会浪费大量的时间。(在使用这些命令的时候,是否想过它们真的靠谱吗?)
操作步骤
查找 Docker 依赖软件包
可以使用 dpkg-query 命令来查询系统中已安装的软件包,并用 grep 筛选出 Docker 相关的内容。
为了避免手动复制粘贴可能带来的错误,我们可以使用 awk 命令来提取包名。使用命令获取软件包名还有一个好处,后续 docker 软件依赖发生变化后,相比较手动“复制粘贴”,使用命令也可以自适应解决问题。
dpkg-query -l | grep docker dpkg-query -l | grep docker | awk '{print $2}'
了解 Docker 软件包依赖关系
在研究 Docker 的子依赖时,我们可以使用 apt-cache depends 结合 xargs 来进行分析。
- 先获取相关软件包的依赖情况。这个命令会为我们展示详细的依赖信息,包括:必需依赖(Depends)、推荐安装(Recommends)、冲突包(Conflicts)、替换包(Replaces)等。重点应该放在 Depends 和 Recommends 这两类依赖上
从输出结果中,能够看到非常清晰的依赖关系,其中主要包括:基础组件:containerd.io、iptables、libseccomp2,系统库:libc6、libsystemd0,工具包:docker-ce-cli、docker-buildx-plugin,安全相关:apparmor、ca-certificates,其他工具:git、kmod、pigz、procps
dpkg-query -l | grep docker | awk '{print $2}' | xargs -I {} apt-cache depends {} dpkg-query -l | grep docker | awk '{print $2}' | xargs -I {} apt-cache depends {} | grep -E "Depends|Recommends" dpkg-query -l | grep docker | awk '{print $2}' | xargs -I {} apt-cache depends {} | grep -E "Depends|Recommends" | grep -v ":any" | sed 's/^[[:space:]]*\(Depends\|Recommends\): //'
编写软件包获取脚本程序
可以写一个更完整的脚本,来获取所有软件包的依赖列表。这对我们后续锁定特定软件包会很有帮助。
# !/bin/bash # 创建临时文件存储所有依赖 temp_file=$(mktemp) # 获取所有 docker 相关包的依赖 dpkg-query -l | grep docker | awk '{print $2}' | while read pkg; do echo "=== Dependencies for $pkg ===" >> "$temp_file" apt-cache depends "$pkg" | grep -E "Depends:|Recommends:" | \ grep -v "<" | \ grep -v ":any" | \ sed 's/^[[:space:]]*\(Depends\|Recommends\): //' >> "$temp_file" echo >> "$temp_file" done # 显示所有依赖(带包名标题) cat "$temp_file" echo -e "\n=== Unique dependencies (sorted) ===" # 提取唯一的依赖项并排序 grep -v "^===" "$temp_file" | \ grep -v "^$" | \ sort -u # 清理临时文件 rm "$temp_file"
将上面的内容保存为 docker-deps.sh,当我们使用 bash docker-deps.sh 运行这个脚本后,它会先按照每个包分类显示其依赖项,然后给出一个去重后的完整依赖列表。下面是运行结果的示例
=== Dependencies for docker-buildx-plugin ===
=== Dependencies for docker-ce ===
containerd.io
docker-ce-cli
iptables
libc6
libsystemd0
apparmor
ca-certificates
docker-ce-rootless-extras
git
libltdl7
pigz
procps
xz-utils=== Dependencies for docker-ce-cli ===
libc6
docker-buildx-plugin
docker-compose-plugin=== Dependencies for docker-ce-rootless-extras ===
dbus-user-session
libc6
slirp4netns=== Dependencies for docker-compose-plugin ===
docker-buildx-plugin
=== Unique dependencies (sorted) ===
apparmor
ca-certificates
containerd.io
dbus-user-session
docker-buildx-plugin
docker-ce-cli
docker-ce-rootless-extras
docker-compose-plugin
git
iptables
libc6
libltdl7
libsystemd0
pigz
procps
slirp4netns
xz-utils
可以从这个列表中清晰的对 Docker 进行全面的了解:Docker CE 本身依赖了一些基础组件,比如 containerd.io、iptables 等。而 Docker CLI 则需要 buildx 和 compose 插件的支持。对于 rootless 模式,还需要 dbus-user-session 和 slirp4netns。如果用到了 Python SDK,python3-requests 等几个 Python 包也是依赖项之一。
筛选需要关注的依赖
从前面的命令输出中,我们看到 Docker 依赖了不少系统组件。如果你追求极致的环境稳定性,并且不打算对宿主机做任何补丁更新,当然可以把所有相关的软件包都锁定版本。
不过建议三思。将所有程序都锁定版本,可能会导致错过 Ubuntu 系统的重要安全更新,也可能错过一些系统稳定性的改进。所以建议是:只锁定 Docker 直接相关的软件包,其他系统组件就交给系统的包管理器去维护。
为了实现这个目标,可以改进一下脚本,筛选出真正需要锁定的 docker 相关包。在改进脚本之前,回忆下之前的文章中,我们的 Docker 安装命令是这样的(一共四个依赖):
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
改进的脚本如下
# !/bin/bash # 创建临时文件存储所有依赖 temp_file=$(mktemp) # 获取所有 docker 相关包的依赖 dpkg-query -l | grep docker | awk '{print $2}' | while read pkg; do echo "=== Dependencies for $pkg ===" >> "$temp_file" apt-cache depends "$pkg" | grep -E "Depends:|Recommends:" | \ grep -v "<" | \ grep -v ":any" | \ sed 's/^[[:space:]]*\(Depends\|Recommends\): //' >> "$temp_file" echo >> "$temp_file" done temp_file2=$(mktemp) # 提取唯一的依赖项并排序 grep -v "^===" "$temp_file" | \ grep -v "^$" | \ sort -u > "$temp_file2" dpkg-query -l | grep docker | awk '{print $2}' >> "$temp_file2" cat "$temp_file2" | sort | uniq | grep -E "docker|container" # 清理临时文件 rm "$temp_file" rm "$temp_file2"
进行软件包版本锁定
echo $(bash docker-deps.sh) | tr ' ' '\n' | xargs -I {} sudo apt-mark hold {} apt-mark showhold
- 无标签
添加评论