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 分钟前
影响交换机箱体使用寿命的几个关键因素
运维·服务器·网络·python
无限进步_32 分钟前
Linux进程终止——退出码、exit与_exit
linux·运维·服务器
小蜗子1 小时前
Windows 11 + RTX 5060 + WSL2 Ubuntu + NVIDIA DGL 容器
linux·运维·ubuntu
枕星而眠1 小时前
C++ 面向对象核心机制深度解析:多态性、虚函数、虚继承与 final 类
运维·开发语言·c++·后端
着迷不白1 小时前
八、shell脚本
linux·运维
tobias.b1 小时前
JumpServer4\.10\.16离线部署\+外部Nginx反向代理 解决30分钟空闲断开WebSocket超时(延长10天)
运维·websocket·nginx
流浪0012 小时前
Linux系统篇(四):一文吃透 Linux 虚拟地址空间:从页表映射到内核结构体全链路拆解
linux·运维·服务器
Jacob程序员2 小时前
WebSSH技术实现全解析
linux·运维·服务器·websocket
暗冰ཏོ2 小时前
运维岗位完整学习指南:从 Linux 基础到 DevOps / SRE 实战
linux·运维·服务器·ubuntu·运维开发·devops
龙泉寺天下行走2 小时前
bash (())奇怪的返回码
linux·运维·服务器