1. 将数据从宿主机挂载到容器中的三种方式
Docker提供三种方式将数据从宿主机挂载到容器中:
- volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
- bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
- tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用 tmpfs,同时避免写入容器可写层提高性能。
2. Volume
管理卷:
docker volume create nginx-vol
docker volume ls
docker volume inspect nginx-vol
用卷创建一个容器:
docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
清理:
docker stop nginx-test
docker rm nginx-test
docker volume rm nginx-vol
注意:
- 如果没有指定卷,自动创建
- 建议使用--mount,更通用
[root@localhost ~]# docker volume create nginx_vol
nginx_vol
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local nginx_vol
[root@localhost ~]# docker volume inspect nginx_vol
[
{
"CreatedAt": "2019-08-18T17:22:46+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/nginx_vol/_data",
"Name": "nginx_vol",
"Options": {},
"Scope": "local"
}
]
[root@localhost ~]# ls /var/lib/docker/volumes/nginx_vol/_data/ ---数据卷数据存放位置
安装nginx,与容器共享网页文件目录:
[root@localhost ~]# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm ---设置nginx的yum源
[root@localhost ~]# yum install -y nginx ---安装nginx
[root@localhost ~]# systemctl start nginx ---启动nginx
[root@localhost html]# docker rm -f $(docker ps -a | awk '{print $1}') ---先删除前面创建的容器
b75a5892d442
2645100be04d
0dab09030fd2
23688554bc1f
d7123e29b0be
2dd1300152d5
c8633362cbe4
4dc7b59c8eef
44fddd40d047
4404f627f050
1feb5ca6ca6c
Error: No such container: CONTAINER
[root@localhost html]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost html]# vi /usr/lib/sysctl.d/00-system.conf
net.ipv4.ip_forward=1 ---添加如下行
:wq
[root@localhost html]# docker run -d --name nginx01 -p 88:80 --mount src=nginx_vol,dst=/usr/share/nginx/html nginx
---创建容器nginx01,src指定卷名,dst指定挂载的html文件路径
2397a403199a0046102f63f4a07ecf9c821f1a12d71c5fbd00780b119bb151f5
[root@localhost ~]# ls /var/lib/docker/volumes/nginx_vol/_data/ ---挂载成功
50x.html index.html
测试访问新创建的容器的网页
[root@localhost ~]# cd /var/lib/docker/volumes/nginx_vol/_data/
[root@localhost _data]# ls
50x.html index.html
[root@localhost _data]# vi index.html ---修改默认页面内容
<h1>Hello world!</h1>
:wq
[root@localhost _data]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2397a403199a nginx "nginx -g 'daemon of…" 3 hours ago Up 3 hours 0.0.0.0:88->80/tcp nginx01
[root@localhost _data]# docker inspect 2397a403199a
---省略若干---
"IPAddress": "172.17.0.2", ---找到容器对应的IP
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
[root@localhost ~]# curl 172.17.0.2
<h1>Hello world!</h1>
修改后的内容
说明可以直接在外面修改容器中的数据,但是不建议这么做。
[root@localhost ~]# docker stop nginx01 ---把nginx01停止掉
nginx01
[root@localhost ~]# docker run -d --name nginx02 -p 88:80 --mount src=nginx_vol,dst=/usr/share/nginx/html nginx ---重新创建一个新的容器,指定的目录跟nginx01一样
9902f8e84ec761ea7c98b734998c3072ea49afd96ed03e869f8bbd7b5fab052b
访问网页
nginx01停止掉了还是能正常访问网页,因为数据还是使用的原来的数据,端口还是原来的端口,就算原来的容器损坏了,只要再重新创建一个容器指定相同的内容即可。这就是volume的好处。
[root@localhost ~]# docker rm -f $(docker ps -a | awk '{print $1}') ---删除所有容器
9902f8e84ec7
2397a403199a
Error: No such container: CONTAINER
[root@localhost ~]# ls /var/lib/docker/volumes/nginx_vol/_data/ ---数据还在
50x.html index.html
[root@localhost ~]# docker volume rm nginx_vol ---删除数据卷
nginx_vol
[root@localhost ~]# ls /var/lib/docker/volumes/nginx_vol/_data/ ---数据没了
ls: cannot access /var/lib/docker/volumes/nginx_vol/_data/: No such file or directory
小结:删除容器,数据卷的数据还在,只有删除数据卷,数据卷的数据才会被删除。
3. Bind Mounts
用卷创建一个容器:
docker run -d --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx
docker run -d --namenginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
验证绑定:
docker inspect nginx-test
清理:
docker stop nginx-test
docker rm nginx-test
注意:
- 如果源文件/目录不存在,不会自动创建,会抛出一个错误。
- 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏,所以最好确保挂载目标目录为空目录。但是后续在容器中新增的数据会同步到宿主机对应的目录下。
[root@localhost ~]# docker run -d --name nginx01 -p 88:80 --mount type=bind,src=/mnt/,dst=/usr/share/nginx/html nginx
8e3ddc68630d8e1acf6382baf061a3e3c208b62a9b2570ba8ffaebd4dfeeff6d
[root@localhost ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e3ddc68630d nginx "nginx -g 'daemon of…" 11 seconds ago Up 10 seconds 0.0.0.0:88->80/tcp nginx01
[root@localhost ~]# ls /mnt/ ---目前没有数据
[root@localhost app]# docker exec -it nginx01 bash
root@8e3ddc68630d:/# cd /usr/share/nginx/html/
root@8e3ddc68630d:/usr/share/nginx/html# ls
root@8e3ddc68630d:/usr/share/nginx/html# echo "Hello world!" > index.html
root@8e3ddc68630d:/usr/share/nginx/html# exit
exit
[root@localhost app]# ls /mnt ---同步到src目录下了
index.html
[root@localhost app]# docker run -d --name nginx02 -p 89:80 --mount type=bind,src=/etc,dst=/opt nginx
---把/etc目录挂载到/opt目录下
434e38fa613a33e6cbc9a4607edb25bb61d5c7abb75d22bf80bb9d59190caaa1
[root@localhost app]# docker exec -it nginx02 bash
root@434e38fa613a:/# ls /opt/
DIR_COLORS centos-release-upstream e2fsck.conf hostname locale.conf nsswitch.conf.bak python security sysctl.d
DIR_COLORS.256color chkconfig.d environment hosts localtime openldap rc.d selinux system-release
DIR_COLORS.lightbgcolor containerd ethertypes hosts.allow login.defs opt rc.local services system-release-cpe
GREP_COLORS cron.d exports hosts.deny logrotate.conf os-release rc0.d sestatus.conf systemd
GeoIP.conf cron.daily favicon.png init.d logrotate.d pam.d rc1.d shadow terminfo
GeoIP.conf.default cron.deny filesystems inittab lvm passwd rc2.d shadow- tmpfiles.d
NetworkManager cron.hourly firewalld inputrc machine-id passwd- rc3.d shells tuned
X11 cron.monthly fstab iproute2 magic pkcs11 rc4.d skel udev
adjtime cron.weekly fuse.conf issue makedumpfile.conf.sample pki rc5.d ssh vconsole.conf
aliases crontab gcrypt issue.net man_db.conf plymouth rc6.d ssl virc
aliases.db crypttab gnupg kdump.conf mke2fs.conf pm redhat-release statetab vmware-tools
alternatives csh.cshrc groff kernel modprobe.d polkit-1 resolv.conf statetab.d wpa_supplicant
anacrontab csh.login group krb5.conf modules-load.d popt.d rpc subgid xdg
asound.conf dbus-1 group- krb5.conf.d motd postfix rpm subuid xinetd.d
audisp default grub.d ld.so.cache mtab ppp rsyslog.conf sudo-ldap.conf yum
audit depmod.d grub2.cfg ld.so.conf my.cnf prelink.conf.d rsyslog.d sudo.conf yum.conf
bash_completion.d dhcp gshadow ld.so.conf.d my.cnf.d printcap rwtab sudoers yum.repos.d
bashrc docker gshadow- libaudit.conf networks profile rwtab.d sudoers.d
binfmt.d dracut.conf gss libnl nginx profile.d sasl2 sysconfig
centos-release dracut.conf.d host.conf libuser.conf nsswitch.conf protocols securetty sysctl.conf
总结
Volume特点:
- 多个运行容器之间共享数据
- 当容器停止或被移除时,该卷仍然存在
- 多个容器可以同时挂载相同的卷
- 当明确删除卷时,卷才会被删除
- 将容器的数据存储在远程主机或其他存储上
- 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/)
Bind Mounts特点:
- 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析
- 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问构建的项目包
- 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时
网友评论