问题描述


docker default machine重启后(我的问题发生在virtualbox 关闭电源重启), /home/docker目录下存放的脚本等丢失。
每次重启后都需要重新建立脚本,或是从本机拷贝之前备份的数据,非常麻烦。 有时遇到意外重启,最新的数据还没来得及备份,就很忧伤了。

问题解决方案


Find Root Cause

通过查阅资料,得知/docker/home的数据是存放在 tmpfs, 顾名思义temp filesystem
可以使用 df [dir/file name]来查看文件目录数据存放在哪个filesystem.

1. 查看所有的磁盘挂载

docker@default:~$ df -h
Filesystem                Size      Used Available Use% Mounted on
tmpfs                   890.4M    223.7M    666.7M  25% /
tmpfs                   494.7M         0    494.7M   0% /dev/shm
/dev/sda1                17.8G      2.0G     14.9G  12% /mnt/sda1
cgroup                  494.7M         0    494.7M   0% /sys/fs/cgroup
/c/Users                101.4G     49.4G     52.1G  49% /c/Users
/share                  276.7G     55.4G    221.3G  20% /share
/dev/sda1                17.8G      2.0G     14.9G  12% /mnt/sda1/var/lib/docker

2.查看 /home/docker 对应的磁盘

docker@default:~$ df /home/docker
Filesystem                Size      Used Available Use% Mounted on
tmpfs                   890.4M    223.7M    666.7M  25% /

从此处可以看到,/docker/home目录下的数据确实放在tempfs.
通过查阅资料得知,tmpfs是基于内存的临时文件系统,machine关闭后,数据不回保存

解决方法

通过前面分析得知,想要保存数据,需要将数据存到设备文件/dev/sda1中。
可以通过建立软链接的方式,将/home/docker下的文件保存到/mnt/sda1, 但是软链接文件是存在/home/docker的,也就是重启后软链接文件会消失,还需要重新建立。排除这个方法。
还想到一个方法,直接将/home/docker对应的设备文件修改为/dev/sda1.
Google一下,发现同一个设备文件不能同时挂载两个文件目录, 但是可以通过mount --bind的方式将当前挂载目录下的某个目录 绑定 到其他目录。

解决过程

首先在/mnt/sda1/var/lib下创建一个home目录。然后将此目录绑定到/home/docker。

docker@default:/mnt/sda1/var/lib$ sudo mkdir home
docker@default:/mnt/sda1/var/lib$ sudo mount --bind /mnt/sda1/var/lib/home /home/docker

在/home/docker目录下创建一个test.txt

docker@default:~$ sudo touch test.txt
docker@default:~$ sudo vi test.txt

重启

C:\Users\Administrator>docker-machine stop default
Stopping "default"...
Machine "default" was stopped.

C:\Users\Administrator>docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Windows might ask for the permission to configure a dhcp server. Sometimes, such confirmation window is minimized in the taskbar.
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

C:\Users\Administrator>docker-machine env
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.100:2376
SET DOCKER_CERT_PATH=C:\Users\Administrator\.docker\machine\machines\default
SET DOCKER_MACHINE_NAME=default
SET COMPOSE_CONVERT_WINDOWS_PATHS=true
REM Run this command to configure your shell:
REM     @FOR /f "tokens=*" %i IN ('docker-machine env') DO @%i   

连接default machine,查看文件.
发现文件确实存在/mnt/sda1/var/lib/home,但是直接访问/home/docker,发现挂载失效了。这样用起来还是不方便

再次挂载,并设置为启动自动挂载

docker@default:/mnt/sda1/var/lib/home$ sudo mount --bind /mnt/sda1/var/lib/home /home/docker
docker@default:/mnt/sda1/var/lib/home$ sudo cat /etc/mtab

tmpfs / tmpfs rw,relatime,size=911808k 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0
tmpfs /dev/shm tmpfs rw,relatime 0 0
/dev/sda1 /mnt/sda1 ext4 rw,relatime,data=ordered 0 0
cgroup /sys/fs/cgroup tmpfs rw,relatime,mode=755 0 0
cgroup /sys/fs/cgroup/cpuset cgroup rw,relatime,cpuset 0 0
cgroup /sys/fs/cgroup/cpu cgroup rw,relatime,cpu 0 0
cgroup /sys/fs/cgroup/cpuacct cgroup rw,relatime,cpuacct 0 0
cgroup /sys/fs/cgroup/blkio cgroup rw,relatime,blkio 0 0
cgroup /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0
cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0
cgroup /sys/fs/cgroup/freezer cgroup rw,relatime,freezer 0 0
cgroup /sys/fs/cgroup/net_cls cgroup rw,relatime,net_cls 0 0
cgroup /sys/fs/cgroup/perf_event cgroup rw,relatime,perf_event 0 0
cgroup /sys/fs/cgroup/net_prio cgroup rw,relatime,net_prio 0 0
cgroup /sys/fs/cgroup/hugetlb cgroup rw,relatime,hugetlb 0 0
cgroup /sys/fs/cgroup/pids cgroup rw,relatime,pids 0 0
/c/Users /c/Users vboxsf rw,nodev,relatime 0 0
/share /share vboxsf rw,nodev,relatime 0 0
/dev/sda1 /mnt/sda1/var/lib/docker ext4 rw,relatime,data=ordered 0 0
/dev/sda1 /home/docker ext4 rw,relatime,data=ordered 0 0

找到刚刚的挂载对应行/dev/sda1 /home/docker ext4 rw,relatime,data=ordered 0 0, 将它添加到 /etc/fstab

docker@default:/mnt/sda1/var/lib/home$ sudo mount -o remount,rw /   # 将fstab修改为可写文件  
docker@default:/mnt/sda1/var/lib/home$ sudo vi /etc/fstab
# /etc/fstab
proc            /proc        proc    defaults          0       0
sysfs           /sys         sysfs   defaults          0       0
devpts          /dev/pts     devpts  defaults          0       0
tmpfs           /dev/shm     tmpfs   defaults          0       0
/dev/zram0  swap         swap    defaults,noauto   0       0
/dev/sda2       none            swap     defaults             0 0 # Added by TC
/dev/sda1       /mnt/sda1       ext4     noauto,users,exec    0 0 # Added by TC
/dev/sr0        /mnt/sr0        auto     noauto,users,exec    0 0 # Added by TC
/dev/sda1       /home/docker    ext4     rw,relatime,data=ordered  0  0

立即生效fstab(或重启)

docker@default:/mnt/sda1/var/lib/home$ sudo mount -a
mount: /dev/sda1 is already mounted or /home/docker busy
       /dev/sda1 is already mounted on /mnt/sda1
       /dev/sda1 is already mounted on /mnt/sda1/var/lib/docker
       /dev/sda1 is already mounted on /home/docker

到此,这个问题就算解决了

其他相关

绑定完成后, 在~目录(也就是/home/docker)操作就需要sudo权限, 使用起来还是不太方便。
可以将/mnt/sda1/var/lib/home的用户修改为当前用户。

docker@default:~$ cd /mnt/sda1/var/lib
docker@default:/mnt/sda1/var/lib$ who  # 查看当前用户
docker          tty1            00:38   Dec 12 09:53:11
docker          pts/0           00:00   Dec 12 09:57:02  192.168.99.1
docker@default:/mnt/sda1/var/lib$ sudo chown -Rf docker home
docker@default:/mnt/sda1/var/lib$ ls -al
total 20
drwxr-xr-x    5 root     root          4096 Dec 12 09:35 .
drwxr-xr-x    3 root     root          4096 Dec  5 08:58 ..
drwxr-xr-x    6 docker   docker        4096 Dec  5 08:59 boot2docker
drwx--x--x   15 root     root          4096 Dec 12 09:53 docker
drwxr-xr-x    2 docker   root          4096 Dec 12 09:36 home
docker@default:/mnt/sda1/var/lib$ cd ~
docker@default:~$ touch demo.txt  # 不用在前面添加sudo了
docker@default:~$
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐