磁盘映射 大部分时候你会需要把你host主机(宿主)上的目录映射到Container里面,这样你就非常方便地在host主机上编辑代码,然后直接就可以在Container里面运行它们,而不用手动copy到Container里面再重启Container。按理将host的目录映射到guest(指Container)上应该是一件很容易的事情,就好像VMWare那样,但可惜的是,由于Mac上的Docker多了一层虚拟机,因此多了一层周折,你必须先VM上的目录通过sshfs mount到host(指Mac)上,然后再将你的目录或文件copy到这个mount的目录,再将VM上的这个目录映射到Container里,听起来比较拗口,画个图会清晰很多。 
如上图所示,VM里面的/mnt/sda1/dev/目录(你需要自己创建)通过sshfs命令mount到了host主机(Mac)的~/workspace/dev/目录 ,而VM里的/mnt/sda1/dev/目录又被映射到了Container的/src/目录下,这样你就可以在Container里面的/src/目录下访问你的host文件了。具体如何做呢?首先你需要安装sshfs命令,然后将VM的password写到一个文件中,例如~/.boot2docker/b2d-passwd,在用sshfs命令mount起VM的/mnt/sda1/dev目录: brew install sshfs
cat tcuser > ~/.boot2docker/b2d-passwd
sshfs docker@localhost:/mnt/sda1/dev ~/workspace/dev -p 2022 -o reconnect -o password_stdin < ~/.boot2docker/b2d-passwd 接着你在run一个Container的时候需要通过-v选项来将/mnt/sda1/dev/映射到/src目录: docker run -i -t dev:base -v /mnt/sda1/dev:/src /bin/bash
这样你就可以在你的Container的/src目录下看到你host里的文件了。 磁盘映射还有2个地方需要注意: - 你的文件实际上是存储在VM里面的,也就是说你需要将你的目录或者文件copy到VM里面,你sshfs之后,就是copy到~/workspace/dev目录下
- 千万不要sshfs mount非/mnt/sda1下的目录,因为VM里面跑的是TinyCoreLinux,这个OS的rootfs是临时性的(放在内存的,实际上就是boot2docker.iso文件里面的一个rootfs),因此其根目录/下的东西(包括/home)根本不会持久化,只有/mnt/sda1这个目录下的才能持久化。如果你放在/home目录下,只要VM一重启,就会丢失的,/mnt/sda1则不会,实际上就是那个~/.boot2docker-vm.vmdk文件挂载到了/mnt/sda1目录下
端口映射 和磁盘映射一样,你有时候会需要将Container的端口映射到host主机上,同样蛋疼的是,由于多了一层VM,端口映射也显得比较麻烦。首先你需要设置VirtualBox的端口映射,然后再将Container的端口映射到你的VM里面: 
具体是这么做的,通过2条命令: boot2docker ssh -L 8000:localhost:8000
docker run -i -t -p 8000:8000 也就是说在Docker run的时候通过-p选项指定要映射的端口到VM,而boot2docker ssh命令则是将VM的8000端口映射到了host(Mac)的8000端口,这样你就可以通过Mac的localhost:8000访问Container的8000端口了。 其实,有另一种解决方案就是你不用映射到host(Mac),而是直接登录到VM里面进行访问就好了,boot2docker ssh就可以登录到VM,这样就类似于你的host是Ubuntu,但这种解决方案的问题是这个Ubuntu太弱了(TinyCoreLinux),如果你在这个Ubuntu里面开发代码,或者是运行浏览器,是非常蛋疼的事情,关键还是这个Ubuntu是每次重启都会复原的!所以我建议还是做多一层映射好了。 最后,实际上在VM里面,你是可以直接访问所有的Container的端口的,因为VM到Container的网络都是桥接的。
其他的一些坑 在使用的过程中,还遇到一些不少的坑: - /etc/hosts文件无法修改,这样你就不能自己做域名解析
- VM的系统时间是UTC +0000的,而且貌似无法修改
- Container的IP无法指定为静态IP,因此每次重启Container时,IP可能会变化
第1个问题的解决方案是通过安装dnsmasq软件来做域名解析: # 首先,在你的Container里面安装dnsmasq软件:
apt-get install dnsmasq
# 将以下文本添加到 /etc/dnsmasq.conf文件的最后:
listen-address=127.0.0.1 resolv-file=/etc/resolv.dnsmasq.conf conf-dir=/etc/dnsmasq.d user=root
# 接着在/etc/dnsmasq.d/目录下新建一个文件,随意起个名字
vi /etc/dnsmqsq.d/dns.conf
# 指定你要映射的域名,例如google.com,则将下面贴进dns.conf文件
address="/google.com/172.17.0.4"
# 最后退出容器,重启启动容器时,通过-dns选项指定域名服务器
docker run -i -t -dns 127.0.0.1 -dns 8.8.8.8 dev:base /bin/bash
# 一定要注意上面添加google的域名服务器8.8.8.8,否则你访问不了外网
# 进去Container后,启动dnsmasq,这样你就能够ping google.com了
/etc/init.d/dnsmasq start 第2个问题的解决方案就稍微麻烦些,起码我没有找到更好的解决方案,我是将boot2docker.iso文件重新制作一次来解决这个问题的:
#首先你需要将boot2docker.iso文件mount到一个目录下
hdiutil mount ~/.boot2docker/boot2docker.iso
# 系统会mount到/Volumes/boot2docker目录下,然后你最好将这下面的东西copy出来到一个另外的目录,这样我们好制作一张新的ISO
cp -r /Volumes/boot2docker/* ~/tmp/
# 接着我们修改以下文件
vi ~/tmp/boot/isolinux/isolinux.cfg
# 将其中的以下这行修改:
append loglevel=3 user=docker console=ttyS0 console=tty0 nomodeset norestore base
# 修改为:(其实就是加了tz的启动参数),然后保存
append tz=CST-8 loglevel=3 user=docker console=ttyS0 console=tty0 nomodeset norestore base
# 接着你必须在ubuntu环境下重新制作ISO文件,你可以利用docker跑一个ubuntu,哈哈,假设你将boot2docker目录copy到了ubuntu的/src/目录下,那么接着这么做
# 安装xorriso命令
apt-get install xorriso
# 构建ISO映射
xorriso -as mkisofs -J -R -V boot2docker -no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -o /boot2docker.iso/src/
# 这样就生成了/boot2docker.iso文件,最后你就可以替换到VM的启动ISO文件了,然后重启VM了
boot2docker restart
# 最后你必须设置你的VM为正确的时间,使用date -s 命令,最后用date命令查看,你就能看到CST时区的正确时间了
Sun Mar 30 00:27:13 CST 2014
# 对于你启动的container,你都必须重新设置TZ环境变量,否则即使VM是CST-8,你的container还是UCT +00:00的时间
export TZ='CST-8' 第三个问题暂时无法解决(可能需要编辑底层的LXC配置文件)。
|