docker(2) -- 启动后修改目录和网络

1. 前言

docker启动前是image文件,启动后是container文件,启动的时候我们可以指定容器的挂载目录以及网络类型,但启动后,这些信息都以配置文件的形式保存在container中,container重新启动时无法重新指定这些信息,这些文件可以修改,但需要停止容器以及容器服务的运行,并需要按照既定的格式进行修改。

2. 查看配置文件

  1. 创建三个容器,容器0不挂载目录,容器1挂载1个目录,容器挂载3个目录,分别对比它们的配置文件。
# 此处使用-itd参数,容器启动会自动后台运行,之后可以使用"docker attach"进入容器交互,主机的目录可以不存在,docker会自动创建
$ docker run -itd --name test0 ubuntu_base
$ docker run -itd --name test1 -v ./test1:/test1 ubuntu_base
$ docker run -itd --name test2 -v ./test1:/test1 -v ./test2:/test2 ubuntu_base
$ docker ps
CONTAINER ID   IMAGE         COMMAND       CREATED          STATUS         PORTS    NAMES
a9a40a34abad   ubuntu_base   "/bin/bash"   8 seconds ago    Up 3 seconds            test2
3ed594b52a9e   ubuntu_base   "/bin/bash"   20 seconds ago   Up 15 seconds           test1
718b9c1d54c6   ubuntu_base   "/bin/bash"   50 seconds ago   Up 40 seconds           test0
  1. docker inspect 可以查看一些底层的信息。
# 查看test0的信息,其中可以看到一些path路径,‘/var/lib/docker/containers/’开头的就是容器的配置文件路径,该路径需要管理员权限来访问
$ docker inspect test0
...
"ResolvConfPath": "/var/lib/docker/containers/718b9c1d54c6089d4294627c1661657a77072aa378d269ba0a7bfa906f2e40eb/resolv.conf",
...
# 查看该目录下的所有文件,我们主要关注config.v2.json和hostconfig.json文件
$ sudo ls /var/lib/docker/containers/718b9c1d54c6089d4294627c1661657a77072aa378d269ba0a7bfa906f2e40eb/
718b9c1d54c6089d4294627c1661657a77072aa378d269ba0a7bfa906f2e40eb-json.log
config.v2.json
hostname
mounts
resolv.conf.hash
checkpoints
hostconfig.json
hosts
resolv.conf
  1. 安装jq工具,它是一个json的读写工具,稍后我们使用它格式化docker命令的输出。
$ sudo apt install jq
# hostconfig.json是挤在一行,没有缩进的,不便于查看,可以使用"jq"工具进行格式化
$ sudo cat /var/lib/docker/containers/718b9c1d54c6089d4294627c1661657a77072aa378d269ba0a7bfa906f2e40eb/hostconfig.json | jq
# python也自带有json工具,下面这种方式也能实现json的格式化输出
$ sudo cat /var/lib/docker/containers/718b9c1d54c6089d4294627c1661657a77072aa378d269ba0a7bfa906f2e40eb/hostconfig.json | python3 -m json.tool
  1. 将三个容器的hostconfig.json配置文件进行对比,可以看出其中的区别。
    hostconfig.json
  2. 将三个容器的config.v2.json配置文件进行对比,可以看出其中的区别。
    config.v2.json

3. 修改挂载的脚本

python比较适合处理json文件,此处就编写一个python脚本文件docker_path.py,用于向容器中新增挂载的目录或文件,删除的挂载目录的动作不常用就不实现了。

#!/usr/bin/python3import json
import os
import subprocess
import sys# json类型  python类型
#  对象{}     字典{}
#  数组[]     列表[]# 打印帮助信息,不返回
def usage() -> object:print("docker_path [docker name] [host-path:docker-path]")exit(-1)# 检测当前脚本是否具有管理员权限
if os.getuid() != 0:# 重新使用sudo执行脚本,终端会自动提示输入密码subprocess.run(['sudo'] + sys.argv)exit()# 判断参数个数,第0个参数是脚本本身
if len(sys.argv) != 3:print("Two parameters are required")usage()# 第1个参数是容器名称
docker_name = sys.argv[1]
# 此处未指定shell,因此需要将程序和每个参数都分开成列表项
# stdout=subprocess.PIPE表示程序的标准输出重定向到ret中
# stderr=subprocess.DEVNULL表示将程序的标准错误输出丢弃
ret = subprocess.run(['docker', 'inspect', '-f', 'json', '--type', 'container', docker_name], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
# 若容器不存在,则返回1
if ret.returncode != 0:print('Container [' + docker_name + '] isn\'t exist')usage()# 将docker inspect的输出转换为python对象
inspect = json.loads(ret.stdout)# 提取参数中的路径信息,使用‘:’分割
dir_idx = sys.argv[2].find(':')
# 未找到':'即错误
if dir_idx == -1:print(sys.argv[2] + ' should be in "host-path:docker-path" format')usage()# 提取主机路径和容器路径
host_dir = os.path.abspath(sys.argv[2][:dir_idx])
docker_dir = sys.argv[2][dir_idx + 1:]# 主机路径不存时,容器启动后会自行创建, 此处仅打印警告,不退出
if os.path.exists(host_dir) == False:print('Host path [' + sys.argv[2][:dir_idx] + '] isn\'t exist')#usage()# [0]表示列表中的第一个元素
# ['HostsPath']表示字典中的键值HostsPath
# 使用os.path.dirname提取配置文件的目录
conf_path = os.path.dirname(inspect[0]['HostsPath']) + '/'# 判断容器是否正在运行
if inspect[0]['State']['Status'] == 'running':# 正在运行的容器需要先停止kill = input('Docker [' + docker_name + '] is running, do you want to stop [yes/no]: ')if kill == 'yes':print('It takes some time to close the container')if os.system('docker stop ' + docker_name) != 0:print('Docker stop error, exit')exit()else:print('Exit with nothing')exit()# 判断当前运行中的容器数量
ret = subprocess.run(['docker', 'info', '-f', 'json'], stdout=subprocess.PIPE)
if ret.returncode == 0:info = json.loads(ret.stdout)# 如果有其他容器正在运行,则退出if info['ContainersRunning'] != 0:print('Other containers are running, please close them and try again, exit')exit()# 停止docker服务,停止后不需要手动开启,执行docker命令时会自动开启,该动作需要管理员权限
ret = subprocess.run(['systemctl', 'stop', 'docker'], stderr=subprocess.DEVNULL)
if ret.returncode != 0:print('Stop docker service error, exit')exit()# 读取容器的config.v2.json配置文件,该动作需要管理员权限
with open(conf_path + 'config.v2.json', 'r', encoding='utf-8') as f:config = json.load(f)# 备份要修改的文件,如果脚本运行失败,则需要手动恢复一下,否者容器可能无法在docker ps -a中查看到
os.replace(conf_path + 'config.v2.json', conf_path + 'config.v2.json.bak')# 向MountPoints字典中添加一个目录映射
config['MountPoints'][docker_dir] = {'Source': host_dir,'Destination': docker_dir,'RW': True,'Name': '','Driver': '','Type': 'bind','Propagation': 'rprivate','Spec': {'Type': 'bind','Source': host_dir,'Target': docker_dir,},'SkipMountpointCreation': False,
}# 写入容器的config.v2.json配置文件,该动作需要管理员权限
with open(conf_path + 'config.v2.json', 'w', encoding='utf-8') as f:json.dump(config, f)# 读取容器的hostconfig.json配置文件,该动作需要管理员权限
with open(conf_path + 'hostconfig.json', 'r', encoding='utf-8') as f:config = json.load(f)# 备份要修改的文件,如果脚本运行失败,则需要手动恢复一下,否者容器可能无法在docker ps -a中查看到
os.replace(conf_path + 'hostconfig.json', conf_path + 'hostconfig.json.bak')# 当容器没有绑定过目录时,该键值是null,对应python的None,需要使用'=',当有
# 过绑定时,该键值有值是json的数组,对应python的列表,使用'+='
if config['Binds'] is None:config['Binds'] = [host_dir + ':' + docker_dir]
else:config['Binds'] += [host_dir + ':' + docker_dir]# 写入容器的hostconfig.json配置文件,该动作需要管理员权限
with open(conf_path + 'hostconfig.json', 'w', encoding='utf-8') as f:json.dump(config, f)

4. 修改网络的脚本

根据上面的经验编写一个修改网络类型的脚本docker_net.py

#!/usr/bin/python3import json
import os
import subprocess
import sys# json类型  python类型
#  对象{}     字典{}
#  数组[]     列表[]# 打印帮助信息,不返回
def usage() -> object:print("docker_net [docker name] [host/bridge]")exit(-1)# 检测当前脚本是否具有管理员权限
if os.getuid() != 0:# 重新使用sudo执行脚本,终端会自动提示输入密码subprocess.run(['sudo'] + sys.argv)exit()# 判断参数个数,第0个参数是脚本本身
if len(sys.argv) != 3:print("Two parameters are required")usage()# 第1个参数是容器名称
docker_name = sys.argv[1]
# 此处未指定shell,因此需要将程序和每个参数都分开成列表项
# stdout=subprocess.PIPE表示程序的标准输出重定向到ret中
# stderr=subprocess.DEVNULL表示将程序的标准错误输出丢弃
ret = subprocess.run(['docker', 'inspect', '-f', 'json', '--type', 'container', docker_name], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
# 若容器不存在,则返回1
if ret.returncode != 0:print('Container [' + docker_name + '] isn\'t exist')usage()# 将docker inspect的输出转换为python对象
inspect = json.loads(ret.stdout)# 第2个参数是host或bridge表示要修改的类型
docker_net = sys.argv[2]
if docker_net not in ['host', 'bridge']:print('Network [' + docker_net + '] is not support, exit')usage()# [0]表示列表中的第一个元素
# ['HostsPath']表示字典中的键值HostsPath
# 使用os.path.dirname提取配置文件的目录
conf_path = os.path.dirname(inspect[0]['HostsPath']) + '/'# 读取容器的hostconfig.json配置文件,该动作需要管理员权限
with open(conf_path + 'hostconfig.json', 'r', encoding='utf-8') as f:config = json.load(f)# 判断网络类型是否需要修改
if config['NetworkMode'] == docker_net:print('Network doesn\'t need change, do nothing')exit()
# 记录老的网络模型
docker_net_old = config['NetworkMode']# 判断容器是否正在运行
if inspect[0]['State']['Status'] == 'running':# 正在运行的容器需要先停止kill = input('Docker [' + docker_name + '] is running, do you want to stop [yes/no]: ')if kill == 'yes':print('It takes some time to close the container')if os.system('docker stop ' + docker_name) != 0:print('Docker stop error, exit')exit()else:print('Exit with nothing')exit()# 判断当前运行中的容器数量
ret = subprocess.run(['docker', 'info', '-f', 'json'], stdout=subprocess.PIPE)
if ret.returncode == 0:info = json.loads(ret.stdout)# 如果有其他容器正在运行,则退出if info['ContainersRunning'] != 0:print('Other containers are running, please close them and try again, exit')exit()# 停止docker服务,停止后不需要手动开启,执行docker命令时会自动开启,该动作需要管理员权限
ret = subprocess.run(['systemctl', 'stop', 'docker'], stderr=subprocess.DEVNULL)
if ret.returncode != 0:print('Stop docker service error, exit')exit()# 备份要修改的文件,如果脚本运行失败,则需要手动恢复一下,否者容器可能无法在docker ps -a中查看到
os.replace(conf_path + 'hostconfig.json', conf_path + 'hostconfig.json.bak')# 修改网络类型,之前已经读取过hostconfig.json,此处不在重新读取
config['NetworkMode'] = docker_net# 写入容器的hostconfig.json配置文件,该动作需要管理员权限
with open(conf_path + 'hostconfig.json', 'w', encoding='utf-8') as f:json.dump(config, f)# 读取容器的config.v2.json配置文件,该动作需要管理员权限
with open(conf_path + 'config.v2.json', 'r', encoding='utf-8') as f:config = json.load(f)# 备份要修改的文件,如果脚本运行失败,则需要手动恢复一下,否者容器可能无法在docker ps -a中查看到
os.replace(conf_path + 'config.v2.json', conf_path + 'config.v2.json.bak')# 向Networks字典中更换键名
config['NetworkSettings']['Networks'][docker_net] = config['NetworkSettings']['Networks'].pop(docker_net_old)# 写入容器的config.v2.json配置文件,该动作需要管理员权限
with open(conf_path + 'config.v2.json', 'w', encoding='utf-8') as f:json.dump(config, f)

5. 定义命令别名

docker_path.pydocker_net.py放到~/tools/python/目录下,并设置可执行权限,修改~/tools/tools.sh,增加别名定义。

# 设置文件可执行权限
$ chmod +x docker_path.py docker_net.py
# 定义别名
$ alias docker_path="~/tools/python/docker_path.py"
$ alias docker_net="~/tools/python/docker_net.py"

6. 过程中的问题

  1. python脚本中不能使用\r\n换行,否者直接在Linux的shell中执行会报错。
# 在脚本所在目录执行py脚本
$ ./docker_path.py
-bash: ./docker_path.py: cannot execute: required file not found
# 使用vim -b打开文件可以看到每行尾都有^M,即为\r,使用":s/\r//g"即可删除所有\r
$ vi -b docker_path.py
#!/usr/bin/python3^M
...
  1. 关闭docker服务时,会报警告,这句话意思是docker服务已停止,但是socket仍然在运行,后续执行docker命令时会自动启动docker服务。
$ sudo systemctl stop docker
Stopping 'docker.service', but its triggering units are still active:
docker.socket

上一篇:docker(1) – centos镜像
下一篇:docker(2) – 启动后修改目录和网络
目录:文章合集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/43072.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter开发中如何避免UI显示溢出的问题

文章目录 1. 使用灵活的布局组件2. 允许内容滚动3. 处理文本溢出4. 检查父容器约束5. 使用自适应布局6. 调试工具7. 其他技巧总结 在 Flutter 开发中,UI 溢出(如 A RenderFlex overflowed 错误)通常是由于布局空间不足或子组件尺寸超出父容器…

使用FastExcel时的单个和批量插入的问题

在我们用excel表进行插入导出的时候,通常使用easyexcel或者FastExcel,而fastexcel是easy的升级版本,今天我们就对使用FastExcel时往数据库插入数据的业务场景做出一个详细的剖析 场景1 现在我们数据库有一张组织表,组织表的字段…

【力扣刷题|第十七天】0-1 背包 完全背包

目标和 力扣题目网址:目标和 这道题我们先用回溯的思想来做。首先我们设正数和为S,数组和为N,目标值为T,那么S-(N-S)T化简之后可以得S(TN)/2即选择的正数个数为偶数,而且NT也为偶数,那么第一个判断条件我们就有了&…

深入浅出 Embedding

1. 什么是 Embedding? Embedding(嵌入)是一种将高维数据映射到低维连续空间的技术,用于表达数据的语义关系。简单来说,它是一种向量化表示,将文本、图像、用户行为等信息转换为数值向量,使得相似的数据在向量空间中距离更近。 2. 如何理解 Embedding? 2.1 浅显易懂的…

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft Fabric 服务器搭建,Fabric 模组详细搭建教程

【云服务器】在Linux CentOS 7上快速搭建我的世界 Minecraft Fabric 服务器搭建,Fabric 模组详细搭建教程 一、 服务器介绍二、安装 JDK 21三、搭建 Minecraft 服务端四、本地测试连接五、如何添加模组(mods)六、添加服务,并设置开…

【MLP-BEV(10)】BEVPooling V1和BEVPooling V2的view_transformer,进行鱼眼图片实践

文章目录 先说说 BEVPoolv1步骤1:3D点生成步骤2 2D特征采样和BEV特征生成特点再谈谈BEVPoolv2步骤1:3D点生成步骤2: 计算索引关系步骤3: `voxel_pooling`计算鱼眼图片进行实践步骤1、3D点生成(基于Kannala-Brandt 进行调整)步骤2、2D特征采样和BEV特征生成(1) 体素化 (Voxe…

鸿蒙项目源码-天气预报app-原创!原创!原创!

鸿蒙天气预报项目源码包运行成功含文档ArkTS语言。 我半个月写的原创作品,请尊重原创。 原创作品,盗版必究!!!! 原创作品,盗版必究!!!! 原创作品…

告别桌面杂乱与充电焦虑,移速165W百变桌面充电站首发体验

告别桌面杂乱与充电焦虑,移速165W百变桌面充电站首发体验 哈喽小伙伴们好,我是Stark-C~ 先如今,家里的电子产品越来越多,手机、平板、电脑三件套已经是基础配置,还有相机、Switch、智能手表等,这些产品用…

skill插件教程——skill程序的组成以及调用方法

skill程序的基本组成 1、基础的程序文件 插件运行的基础——就是你写程序的文件,格式为il文件,就是文本文件格式 2、调用程序的文件——allegro.ilint 文件申明在那个位置——在这个文件夹下,写入你调用的函数。 例如load(“…

解决Dubbo3调用Springcloud接口报No provider available from registry RegistryDirectory

解决Dubbo调用Springcloud接口报No provider available from registry RegistryDirectory 问题发现问题解决 问题发现 在学习Dubbo过程中,Dubbo官网有一篇文章《微服务最佳实践,零改造实现 Spring Cloud & Apache Dubbo 互通》,跟着示例…

基于RFID技术建筑物资材料智能管理解决方案

建筑行业仓库和物资材料管理面临诸多挑战,如工程设备重复利用的管理需求、物资出入库管理不规范、账物不符、物资丢失等问题。特别是在复杂多变的工地环境中,对物资进行科学规范的管理难度极大。上海岳冉基于RFID技术的建筑物资材料智能管理解决方案聚焦…

WSL系统找不到指定的文件

问题介绍 在尝试使用linux子系统时,发现无法打开 在尝试使用docker时无法使用 在命令行cmd或者powershell使用wls相关命令时,报错 相关错误提示均为: 系统找不到指定的文件 解决方法 试了各种方法无效。 直接到github下载最新版的wsl安装…

海量数据处理

1.海量数据处理问题 给两个文件,分别有100亿个query,只有1G内存,如何找到两个文件交集? 解决方案一: 可以先用布隆过滤器,一个文件的query放进布隆过滤器,另一个文件依次查找,在的…

英伟达GB300新宠:新型LPDDR5X SOCAMM内存

随着人工智能(AI)、机器学习(ML)和高性能计算(HPC)应用的快速发展,对于高效能、大容量且低延迟内存的需求日益增长。NVIDIA在其GB系列GPU中引入了不同的内存模块设计,以满足这些严格…

PC名词解释-笔记本的S0,S1,S2,S3,S4,S5状态

​🎓作者简介:程序员转项目管理领域优质创作者 💌个人邮箱:[2707492172qq.com] 🌐PMP资料导航:PM菜鸟(查阅PMP大纲考点) 💡座右铭:上善若水,水善利…

群体智能优化算法-算术优化算法(Arithmetic Optimization Algorithm, AOA,含Matlab源代码)

摘要 算术优化算法(Arithmetic Optimization Algorithm, AOA)是一种新颖的群体智能优化算法,灵感来源于加、减、乘、除四种基本算术运算。在优化过程中,AOA 通过乘除操作实现全局探索,通过加减操作强化局部开发&#…

Centos7安装cat美化工具lolcat

Centos7安装cat美化工具lolcat Centos7安装lolcat使用ruby安装lolcat配置cat系统别名 结果验证 Centos7安装lolcat lolcat :一个在Linux 终端中输出彩虹特效的命令行工具 使用ruby安装lolcat # 安装ruby和zip yum install -y ruby# 查看ruby版本 ruby --version# …

vue在线录音系统

说明: 用vue做一款录音系统 1.点击按钮,开始录制音频 2.录制过程中,可以暂停和停止录制 有时长显示 3.点击停止录制 可以保存音频,保存在本地 4.找到刚刚保存的音频路径,可以点击播放 ,需要显示音频总时…

参量编码LPC:原理分析与仿真实践

参量编码LPC:原理分析与仿真实践 在早期通信系统中,带宽资源有限,而波形编码要精确重现语音波形,这就需要较高的码率来传输大量数据,这在带宽不足的情况下就成了阻碍语音传输的大难题。随着通信技术不断进步&#xff…

猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果

我的罗里吧嗦的,根据小朋友的要求,边听边写边输入的提示词: 请生成一段完整的在网页中用html5和javascript代码模拟“我的世界”中游戏场景的互动画面,要求提供若干人物选项可以选择,请自行选择需要使用哪些库或框架来…