Docker容器创建好后修改容器配置

创建好容器后,如果想要修改配置,例如环境变量,可以通过直接修改/var/lib/docker/container中的json配置文件来实现,避免重新创建容器。因为重新创建容器会造成原来的数据丢失,而如果容器中的数据很多,例如几百GB,备份数据就会非常耗时,所以直接修改json就更方便,但这种方法有风险且不规范。这篇文章记录了问题的解决过程,但不推荐这种方法。

背景

在Ubuntu 22.04 server中执行sudo ubuntu-drivers install --gpgpu nvidia:580-server命令安装了显卡驱动,进入容器后运行某程序报错,排查问题过程中执行了ldconfig -p | grep -E 'libEGL_nvidia|libnvidia-eglcore|libnvidia-glcore'命令找不到libnvidia-glcore.solibnvidia-eglcore.solibEGL_nvidia.so,且宿主机中的库文件版本是565。

在执行sudo apt install libnvidia-gl-580-server安装库后,容器内依然找不到这些库。排查到container的runtime时,发现runtime不是nvidia而是runc,导致一些GPU相关的功能无法正常使用。

为了不备份并重新创建容器,采用了修改容器的json配置文件的方式来解决问题。具体是将runtime改为nvidia,并添加两个环境变量:NVIDIA_VISIBLE_DEVICES=allNVIDIA_DRIVER_CAPABILITIES=all

解决过程

  1. 记录容器ID和配置文件路径,your_container替换为容器的实际名称
bash 复制代码
CONTAINER=your_container

CID=$(docker inspect --format '{{.Id}}' "$CONTAINER")
ROOT=$(docker info --format '{{.DockerRootDir}}')

CFG="$ROOT/containers/$CID/config.v2.json"
HOSTCFG="$ROOT/containers/$CID/hostconfig.json"

echo "$CFG"
echo "$HOSTCFG"
  1. 停止容器和docker服务
bash 复制代码
docker stop "$CONTAINER"
sudo systemctl stop docker.socket
sudo systemctl stop docker.service
  1. 备份配置文件
bash 复制代码
sudo cp "$CFG" "$CFG.bak"
sudo cp "$HOSTCFG" "$HOSTCFG.bak"
  1. 生成新的hostconfig.json并验证,如果输出是"nvidia"则正确
bash 复制代码
sudo cat "$HOSTCFG" \
| jq '.Runtime = "nvidia"' \
| sudo tee "$HOSTCFG.new" > /dev/null
bash 复制代码
sudo cat "$HOSTCFG.new" | jq empty
sudo cat "$HOSTCFG.new" | jq '.Runtime'
  1. 生成新的config.v2.json并验证,如果输出NVIDIA_VISIBLE_DEVICES=allNVIDIA_DRIVER_CAPABILITIES=all则正确
bash 复制代码
sudo cat "$CFG" \
| jq '
  .Config.Env =
    (
      (.Config.Env // [])
      | map(
          select(
            (
              startswith("NVIDIA_VISIBLE_DEVICES=") or
              startswith("NVIDIA_DRIVER_CAPABILITIES=")
            )
            | not
          )
        )
      + [
          "NVIDIA_VISIBLE_DEVICES=all",
          "NVIDIA_DRIVER_CAPABILITIES=all"
        ]
    )
' \
| sudo tee "$CFG.new" > /dev/null
bash 复制代码
sudo cat "$CFG.new" | jq empty

sudo cat "$CFG.new" \
| jq -r '.Config.Env[]? | select(startswith("NVIDIA_"))'
  1. 覆盖原配置文件
bash 复制代码
sudo mv "$HOSTCFG.new" "$HOSTCFG"
sudo mv "$CFG.new" "$CFG"
  1. 重启电脑,然后启动docker服务
bash 复制代码
sudo systemctl start docker.service
sudo systemctl start docker.socket
相关推荐
吴声子夜歌26 分钟前
Shell编程实例——编写安全的shell脚本(二)
linux·运维·shell
悠悠121381 小时前
微服务通信别只看性能:REST 与 gRPC 的 6 个选型判断和一次 502 故障复盘
运维·服务器
zx_741484813 小时前
【Linux入门】Shell 函数、正则表达式与文本处理:cut 与 awk
linux·运维·正则表达式
Zenova EdgeOS3 小时前
Linux dmesg 工业边缘实战:内核日志过滤、持久化与故障定位
linux·运维·边缘计算·工业边缘·dmesg·内核日志
九皇叔叔3 小时前
K8S 资源菜单
docker·容器·kubernetes·k8s
wdfk_prog4 小时前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
Zhu7584 小时前
docker环境快速部署postgresql数据库18及以上版本
postgresql·容器
做运维的阿瑞4 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
zoutao985 小时前
Gitea Actions 自定义 Runner 镜像与自动化部署实战
ci/cd·docker·gitea
日常筹谋记5 小时前
自动化仓储安全防护工况评估:明治传感器AS-33C技术适配性分析
大数据·运维·创业创新·业界资讯