长话短说,我们想要确保块设备节点在容器里位于和宿主机器上的同一个路径下。
需要这么做:
$ 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(我们并不清除设备节点。一开始就检查设备是否存在可能有点多余,但是现在再检查就已经很复杂了。)
大功告成!
让一切自动化
下面这段可以直接拷贝粘贴了。
#!/bin/sh
set -e
CONTAINER=charlie
HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
CONTPATH=/srcREALPATH=$(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能正确得到块设备节点(上面谈到,并不总是能正确得到)的时候才能起作用。另外,我只测试了我自己的环境,没有在云实例之类的环境里测试过,但是我很想知道在那里是否适用。
您可能感兴趣的文章:阿里云esc服务器Docker部署单节点Mysql的讲解Docker容器和本机之间的文件传输方法Docker数据存储总结Docker数据存储之tmpfs mounts详解Docker数据存储之Bind mounts详解Docker数据存储之Volumes详解docker完整配置nginx+php+mysql的方法步骤Docker容器间通讯直接路由方式实现网络通讯详解docker私有仓库搭建与使用实战第一次构建、运行、发布、获取docker镜像的步骤详解










