如何在docker 拷贝文件容器内外互相拷贝数据

Docker网络配置
查看: 13671|
评论: 0|原作者: oscfox, 徐继开, 地狱星星, --zxp, 无若, 昊翔, 繁华的落尽|来自: oschina
摘要: 当docker启动时,它会在宿主机器上创建一个名为docker0的虚拟网络接口。它会从RFC 1918定义的私有地址中随机选择一个主机不用的地址和子网掩码,并将它分配给docker0。例如当我启动docker几分钟后它选择了172.17.42. ...
  你可以在你的Docker主机上运行iptables命令,来观察FORWARD链是否有默认的ACCEPT或DROP策略#&When&--icc=false,&you&should&see&a&DROP&rule:$&sudo&iptables&-L&-n...Chain&FORWARD&(policy&ACCEPT)target&&&&&prot&opt&source&&&&&&&&&&&&&&&destination
DROP&&&&&&&all&&--&&0.0.0.0/0&&&&&&&&&&&&0.0.0.0/0...#&When&a&--link=&has&been&created&under&--icc=false,#&you&should&see&port-specific&ACCEPT&rules&overriding#&the&subsequent&DROP&policy&for&all&other&packets:$&sudo&iptables&-L&-n...Chain&FORWARD&(policy&ACCEPT)target&&&&&prot&opt&source&&&&&&&&&&&&&&&destination
ACCEPT&&&&&tcp&&--&&172.17.0.2&&&&&&&&&&&172.17.0.3&&&&&&&&&&&tcp&spt:80ACCEPT&&&&&tcp&&--&&172.17.0.3&&&&&&&&&&&172.17.0.2&&&&&&&&&&&tcp&dpt:80DROP&&&&&&&all&&--&&0.0.0.0/0&&&&&&&&&&&&0.0.0.0/0注意: Docker的iptables规则完全显示了容器相互间的原始IP地址,所以一个容器到另一个容器的连接,需要显示地显示出第一个容器的原始IP地址。为主机绑定容器端口  默认情况下,Docker容器可以连接到外部区域,但外部区域不能连接到容器。在Docker启动时,由于它在主机上创建了一个iptables伪装规则,使得每一个输出连接看起来都是由主机IP地址建立起来的。#&You&can&see&that&the&Docker&server&creates&a#&masquerade&rule&that&let&containers&connect#&to&IP&addresses&in&the&outside&world:$&sudo&iptables&-t&nat&-L&-n...Chain&POSTROUTING&(policy&ACCEPT)target&&&&&prot&opt&source&&&&&&&&&&&&&&&destination
MASQUERADE&&all&&--&&172.17.0.0/16&&&&&&&!172.17.0.0/16...  当调用docker run的时候,如果你想让容器接受输入连接,你需要提供特殊选项。这些选项的详细说明在&. &有两种方法可以实现。  首先,你可以提供 -P 或者&--publish-all=true|false 选项参数来执行 docker run 命令,这将会识别所有在dockerfile中暴露的端口,并且随机映射到
之间的主机端口。这看起来是一个很大的不便,当你要启动一个新的容器时你需要知道那个主机端口已经被映射。  更方便的操作是使用 -p SPEC 或者&--publish=SPEC 选项,这两个选项让你明确的指定docker容器的端口映射到任意的主机端口中,不局限于.  无论如何,你应该通过审查你的NAT表,去看看docker在你的网络占做了什么。#&What&your&NAT&rules&might&look&like&when&Docker
#&is&finished&setting&up&a&-P&forward:
$&iptables&-t&nat&-L&-n
DOCKER&(2&references)
target&&&&&prot&opt&source&&&&&&&&&&&&&&&destination
DNAT&&&&&&&tcp&&--&&0.0.0.0/0&&&&&&&&&&&&0.0.0.0/0&&&&&&&&&&&&tcp&dpt:49153&to:172.17.0.2:80
#&What&your&NAT&rules&might&look&like&when&Docker
#&is&finished&setting&up&a&-p&80:80&forward:
DOCKER&(2&references)
target&&&&&prot&opt&source&&&&&&&&&&&&&&&destination
DNAT&&&&&&&tcp&&--&&0.0.0.0/0&&&&&&&&&&&&0.0.0.0/0&&&&&&&&&&&&tcp&dpt:80&to:172.17.0.2:80  可以看到,docker暴露了这些容器的端口到通配IP地址:0.0.0.0 ,这个通配IP地址可以匹配宿主主机上任意一个可以进入的端口。如果你希望更多的限制,并且只允许容器服务通过特殊的宿主主机的外部网络接口来相互联系,那么你有两种选择。当你执行 docker run 命令时,你可以使用 -p IP:host_port:container_port 或者& -p IP::port&来明确地绑定外部接口。  或者如果你希望dokcer永远转发到一个特殊的IP地址上,你可以编辑你的docker系统设置文件(ubuntu系统的设置方法为:编辑 /etc/default/docker文件,改写DOCKER_OPTS参数),增加选项 --ip=IP_ADDRESS 。修改完之后记得重启你的docker服务。  如果你希望更详细的指导,请参考:&&.定制 docker0  默认地,docker服务会在linux内核新建一个网络桥接docker0,使得物理主机和其他虚拟网络接口之间可以传递发送数据包,因此,这表现如一个独立的网络。  docker0有一个IP地址和子网掩码,使得物理主机可以从容器的桥接网络接收和发送数据包。并且给这个桥接网络一个MTU(最大传输单元)或者说网络接口允许的最大包长度-例如1,500 bytes 或者从docker的宿主主机上的网络接口拷贝的数值。在服务启动的时候两者都是可配置的:  在ubuntu系统上,你可以增加以上的配置到&/etc/default/docker 文件中的DOCKER_OPTS参数中,然后重启docker服务。  当你有一个或多个正常运行的容器时,你可以通过在主机上运行brct1命令,观察interfaces列的输出,来确定Docker已经将这些容器正确地连接到docker0网桥。下面是一个连接了两个不同容器的主机:&#&Display&bridge&info$&sudo&brctl&show
bridge&name&&&&&bridge&id&&&&&&&&&&&&&&&STP&enabled&&&&&interfaces
docker0&&&&&&&&&d7362b4ee&&&&&&&no&&&&&&&&&&&&&&veth65f9
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&vethdda6  如果你的Docker主机还没安装brct1命令,那么你可以在Ubuntu上运行sudo apt-get install bridge-utils来安装它。  最后,每次新建一个容器的时候都会用到docker0 桥接网络。每次在执行docker run命令新建一个容器的时候,docker从可利用的桥接网络中随机选择一个未被使用的IP地址,以及使用桥接网络的子网掩码,用来配置容器 eth0网络接口。docker宿主主机的IP地址被docker容器作为默认的网关。#&The&network,&as&seen&from&a&container$&sudo&docker&run&-i&-t&--rm&base&/bin/bash
$$&ip&addr&show&eth024:&eth0:&&BROADCAST,UP,LOWER_UP&&mtu&1500&qdisc&pfifo_fast&state&UP&group&default&qlen&1000
&&&&link/ether&32:6f:e0:35:57:91&brd&ff:ff:ff:ff:ff:ff
&&&&inet&172.17.0.3/16&scope&global&eth0
&&&&&&&valid_lft&forever&preferred_lft&forever
&&&&inet6&fe80::306f:e0ff:fe35:5791/64&scope&link
&&&&&&&valid_lft&forever&preferred_lft&forever
$$&ip&routedefault&via&172.17.42.1&dev&eth.0/16&dev&eth0&&proto&kernel&&scope&link&&src&172.17.0.3$$&exit  记住docker的宿主主机无法转发docker容器的数据包到因特网上,除非它的ip_forward 系统设置为1,详情请看:&&。  建立你自己的桥接网络  如果你希望建立完整的自己的桥接网络,你可以在启动docker之前用&-b BRIDGE&或者&--bridge=BRIDGE选项参数高数docker使用你自己的桥接网络。如果你已经用docker0启动docker了,你需要停止docker服务然后移除docker0.#&Stopping&Docker&and&removing&docker0$&sudo&service&docker&stop
$&sudo&ip&link&set&dev&docker0&down
$&sudo&brctl&delbr&docker0  然后,在启动docker服务之前,新建你自己的桥接网络,写上你想要的配置。接下来我们新建一个简单的桥接网络,刚好用这些选项来定做docker0 ,这刚好足够说明这个技术。#&Create&our&own&bridge$&sudo&brctl&addbr&bridge0
$&sudo&ip&addr&add&192.168.5.1/24&dev&bridge0
$&sudo&ip&link&set&dev&bridge0&up#&Confirming&that&our&bridge&is&up&and&running$&ip&addr&show&bridge04:&bridge0:&&BROADCAST,MULTICAST&&mtu&1500&qdisc&noop&state&UP&group&default
&&&&link/ether&66:38:d0:0d:76:18&brd&ff:ff:ff:ff:ff:ff
&&&&inet&192.168.5.1/24&scope&global&bridge0
&&&&&&&valid_lft&forever&preferred_lft&forever#&Tell&Docker&about&it&and&restart&(on&Ubuntu)$&echo&'DOCKER_OPTS="-b=bridge0"'&&&&/etc/default/docker
$&sudo&service&docker&start  运行结构应该是docker服务成功启动,已经准备好绑定容器到桥接网络上。当核实好桥接网络的配置之后,尝试着新建一个容器,你将看到容器的IP地址是在你的新的桥接网络范围内的,这是docker自动检测的。  正如前文所述,可以用 brctl show 命令查看,新增或者移除网络接口,可以在docker容器中执行 ip addr 和 ip route 命令查看IP地址是否是从网桥IP段分配的,以及docker的宿主主机的IP是否被作为默认网关。
上一篇:下一篇:
快毕业了,没工作经验,
找份工作好难啊?
赶紧去人才芯片公司磨练吧!!如何在Docker容器内外互相拷贝数据_百度知道
如何在Docker容器内外互相拷贝数据
提问者采纳
path/to/target 从主机上拷贝文件到容器内 用-v挂载主机数据卷到容器内 [plain] view plaincopy docker run -v /file/container /path&#47.:/host&#47从容器内拷贝文件到主机上 [plain] view plaincopy docker cp :/within/hostdir.;mnt $path&#47
来自团队:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁给一个正在运行的Docker容器动态添加Volume
-------------
新增文件夹...
新增文件夹
(多个标签用逗号分隔)
之前有人问我Docker容器启动之后还能否再挂载卷,考虑到mnt命名空间的工作原理,我一开始认为这很难实现。不过现在Petazzoni通过使用nsenter和绑定挂载实现了这个需求,你可以在你的环境中测试下。
之前有人问我Docker容器启动之后还能否再挂载卷,考虑mnt命名空间的工作原理,我一开始认为这很难实现。不过现在我认为是它实现的。
简单来说,要想将磁盘卷挂载到正在运行的容器上,我们需要:
使用将包含这个磁盘卷的整个文件系统mount到临时挂载点上;
从我们想当作磁盘卷使用的特定文件夹中创建绑定挂载(bind mount)到这个磁盘卷的位置;
umount第一步创建的临时挂载点。
在下面的示例中,我故意包含了$符号来表示这是Shell命令行提示符,以帮助大家区分哪些是你需要输入的,哪些是机器回复的。有一些多行命令,我也继续用&。我知道这样使得例子里的命令无法轻易得被拷贝粘贴。如果你想要拷贝粘贴代码,请查看文章最后的示例脚本。
下面示例的前提是你已经使用如下命令启动了一个简单的名为charlie的容器:
$&docker&run&--name&charlie&-ti&ubuntu&bash
我们需要做的是将宿主文件夹/home/jpetazzo/Work/DOCKER/docker挂载到容器里的/src目录。好了,让我们开始吧。
首先,我们需要以及 docker-enter帮助脚本。为什么?因为我们要从容器中mount文件系统。由于安全性的考虑,容器不允许我们这么做。使用nsenter,我们可以突破上述安全限制,在容器的上下文(严格地说,是命名空间)中运行任意命令。当然,这必须要求拥有Docker宿主机的root权限。
最简单的安装方式是和docker-enter脚本关联执行:
$&docker&run&--rm&-v&/usr/local/bin:/target&jpetazzo/nsenter
更多细节,请查看项目主页。
找到文件系统
我们想要在容器里挂载包含宿主文件夹(/home/jpetazzo/Work/DOCKER/docker)的文件系统。那我们就需要找出哪个文件系统包含这个目录。
首先,我们需要canonicalize(或者解除引用)文件,以防这是一个符号链接,或者它的路径包含符号链接:
$&readlink&--canonicalize&/home/jpetazzo/Work/DOCKER/docker
/home/jpetazzo/go//docker/docker
哈,这的确是一个符号链接!让我们将其放入一个环境变量中:
$&HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
$&REALPATH=$(readlink&--canonicalize&$HOSTPATH)
接下来,我们需要找出哪个文件系统包含这个路径。我们使用一个有点让人意想不到的工具来做,它就是df:
$&df&$REALPATH
Filesystem&&&&&1K-blocks&&&&&&Used&Available&Use%&Mounted&on
/sda2&&&&&&&&&&%&/home/jpetazzo
使用-P参数(强制使用POSIX格式,以防是exotic df,或者是其他人在Solaris或者BSD系统上装Docker时运行的df),将结果也放到一个变量里:
$&FILESYS=$(df&-P&$REALPATH&|&tail&-n&1&|&awk&'{print&$6}')
找到文件系统的设备(和sub-root)
现在,系统里已经没有绑定挂载(bind mounts)和BTRFS子卷了,我们仅仅需要查看/proc/mounts,找到对应于/home/jpetazzo文件系统的设备就可以了。但是在我的系统里,/home/jpetazzo是BTRFS池的子卷,要想得到子卷的信息(或者bind mount信息),需要查看/proc/self/moutinfo。
如果你从来没有听说过mountinfo,可以查看内核文档的。
首先,得到文件系统设备信息:
$&while&read&DEV&MOUNT&JUNK
&&do&[&$MOUNT&=&$FILESYS&]&&&&break
&&done&&/proc/mounts
$&echo&$DEV
接下来,得到sub-root信息(比如,已挂载文件系统的路径):
$&while&read&A&B&C&SUBROOT&MOUNT&JUNK
&&do&[&$MOUNT&=&$FILESYS&]&&&&break
&&done&&&/proc/self/mountinfo&
$&echo&$SUBROOT
很好。现在我们知道需要挂载/dev/sda2。在文件系统内部,进入/jpetazzo,从这里可以得到到所需文件的剩余路径(示例中是/go//docker/docker)。
让我们计算出剩余路径:
$&SUBPATH=$(echo&$REALPATH&|&sed&s,^$FILESYS,,)
注意:这个方法只适用于路径里没有符号“,”的。如果你的路径里有“,”并且想使用本文方法挂载目录,请告诉我。(我需要调用Shell Triad来解决这个问题:,,?)
在进入容器之前最后需要做的是找到这个块设备的主和次设备号。可以使用stat:
$&stat&--format&"%t&%T"&$DEV
注意这两个数字是十六进制的,我们之后需要的是二进制。可以这么转换:
$&DEVDEC=$(printf&"%d&%d"&$(stat&--format&"0x%t&0x%T"&$DEV))
还有最后一步。因为某些我无法解释的原因,一些文件系统(包括BTRFS)在挂载多次之后会更新/proc/mounts里面的设备字段。也就是说,如果我们在容器里创建了名为/tmpblkdev的临时块设备,并用其挂载我们自己的文件系统,那么文件系统(在宿主机器里!)会显示为/tmpblkdev,而不是/dev/sda2。这听起来无所谓,但实际上这会让之后试图得到文件系统块设备的操作都失败。
长话短说,我们想要确保块设备节点在容器里位于和宿主机器上的同一个路径下。
需要这么做:
$&docker-enter&charlie&--&sh&-c&\
&&"[&-b&$DEV&]&||&mknod&--mode&0600&$DEV&b&$DEVDEC"
创建临时挂载点挂载文件系统:
$&docker-enter&charlie&--&mkdir&/tmpmnt
$&docker-enter&charlie&--&mount&$DEV&/tmpmnt
确保卷挂载点存在,bind mount卷:
$&docker-enter&charlie&--&mkdir&-p&/src
$&docker-enter&charlie&--&mount&-o&bind&/tmpmnt/$SUBROOT/$SUBPATH&/src
删除临时挂载点:
$&docker-enter&charlie&--&umount&/tmpmnt
$&docker-enter&charlie&--&rmdir&/tmpmnt
(我们并不清除设备节点。一开始就检查设备是否存在可能有点多余,但是现在再检查就已经很复杂了。)
大功告成!
让一切自动化
下面这段可以直接拷贝粘贴了。
CONTAINER=charlie
HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
CONTPATH=/src
REALPATH=$(readlink&--canonicalize&$HOSTPATH)
FILESYS=$(df&-P&$REALPATH&|&tail&-n&1&|&awk&'{print&$6}')
while&read&DEV&MOUNT&JUNK
do&[&$MOUNT&=&$FILESYS&]&&&&break&
done&&&/proc/mounts
[&$MOUNT&=&$FILESYS&]&#&Sanity&check!
\while&read&A&B&C&SUBROOT&MOUNT&JUNK
\do&[&$MOUNT&=&$FILESYS&]&&&&break
\done&&&/proc/self/mountinfo&
[&$MOUNT&=&$FILESYS&]&#&Moar&sanity&check!
SUBPATH=$(echo&$REALPATH&|&sed&s,^$FILESYS,,)
DEVDEC=$(printf&"%d&%d"&$(stat&--format&"0x%t&0x%T"&$DEV))
docker-enter&$CONTAINER&--&sh&-c&\
&&&&&"[&-b&$DEV&]&||&mknod&--mode&0600&$DEV&b&$DEVDEC"
docker-enter&$CONTAINER&--&mkdir&/tmpmnt
docker-enter&$CONTAINER&--&mount&$DEV&/tmpmnt
docker-enter&$CONTAINER&--&mkdir&-p&$CONTPATH
docker-enter&$CONTAINER&--&mount&-o&bind&/tmpmnt/$SUBROOT/$SUBPATH&$CONTPATH
docker-enter&$CONTAINER&--&umount&/tmpmnt
docker-enter&$CONTAINER&--&rmdir&/tmpmnt
状态和限制
上述方法不适用于不基于块设备的文件系统,只有在/proc/mounts能正确得到块设备节点(上面谈到,并不总是能正确得到)的时候才能起作用。另外,我只测试了我自己的环境,没有在云实例之类的环境里测试过,但是我很想知道在那里是否适用。
原文链接: (翻译:崔婧雯 校对:李颖杰)
===========================
崔婧雯,现就职于VMware,高级软件工程师,负责桌面虚拟化产品的质量保证工作。曾在IBM WebSphere业务流程管理软件担任多年系统测试工作。对虚拟化,中间件技术有浓厚的兴趣。
来自:/article/149
相关资讯  — 
相关文档  — 
发布时间: 15:09:17
同类热门经验
23903次浏览
12228次浏览
22183次浏览
18761次浏览
12854次浏览
11188次浏览
OPEN-OPEN, all rights reserved.如何在Docker容器内外互相拷贝数据_百度知道
如何在Docker容器内外互相拷贝数据
提问者采纳
host/FULL_CONTAINER_ID/**d8e703d7ed01bd7fb58d59eb16c4b83cf
3;host/id&devicemapper/path/sourcefile /container_id&bin/docker/123abc&lt.用输入输出符 [plain] view plaincopydocker run -i ubuntu /to/hostdir. 获取整个容器的id[plain] view plaincopy$ docker inspect -f
'mnt/lib/&#47:/aufs/aufs/container/within&#47:[plain] view plaincopy$ docker ps
B;path/path/ d8e703d7e303
d8e703d7ed01bd7fb58d59eb16c4b83cf
$ sudo cp file.Id}}'path/to/mnt/{{.直接在主机上拷贝到容器物理存储系统A; cranky_pare
$ docker inspect -f
'&containerId& /to/usr/ /lib/lib/ bash -c 'path/var/root
例子.Id}}'
或者[plain] view plaincopydocker exec -it &cat & & &lt. 在主机上拷贝文件;PATH-NEW-FILE
$ sudo cp path-file-host /path/file'&destfile
2;{{. 获取容器名称或者host/mnt/mnt $container
在容器内拷贝
cp /container/var&#47:[plain] view plaincopy$ docker ps
CONTAINER ID
d8e703d7e303
solidleon/ /{{;path/file/ /
步骤A获取的名称或者id
C从容器内拷贝文件到主机上[plain] view plaincopydocker cp &lt:[plain] view plaincopy$ sudo cp path-file-host /docker/file&#39.txt /sshd -D
cranky_pare
$ docker inspect -f
'target
从主机上拷贝文件到容器内1;var/cat &to/.Id}}'docker/file&#47:/mnt&#47.用-v挂载主机数据卷到容器内[plain] view plaincopydocker run -v /to&#47:latest
/to/rootfs/sbin/container /path/bash -c 'file&#47
来自团队:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 docker容器 互相访问 的文章

 

随机推荐