很多时候,我们不希望直接将数据放在容器中。因为在容器的同时,也会将我们的数据进行删除。这时,我们就可以通过容器数据卷,来将数据放在宿主机中。
本章以masql为例,将数据库中的数据放置在宿主机中。
# 容器数据卷一般在创建容器的时候,使用-v来进行指定
# 冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径。 可以指定多个
docker run -v 宿主机目录:容器内目录
docker create -v 宿主机目录:容器内目录
现在尝试创建一个mysql,并将数据挂载到容器外
# 创建mysql容器
[root@localhost home]# docker run -d -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name data-mysql mysql:5.7
#在创建完成容器之后,就会发现宿主机/home目录下多了个mysql文件夹,容器中的目录被同步出来了
[root@localhost mysql]# cd /home/mysql/data
[root@localhost data]# ls
auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 mysql private_key.pem server-cert.pem sys
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 ibtmp1 performance_schema public_key.pem server-key.pem
#这样 ,容器对于该目录的修改就会同步到宿主机,即使将容器删除,也不会影响数据。
#使用之前的docker inspect 来查看容器的挂载信息
[root@localhost data]# docker inspect --format="{{json .Mounts}}" data-mysql
[{"Type":"bind","Source":"/home/mysql/data","Destination":"/var/lib/mysql","Mode":"","RW":true,"Propagation":"rprivate"},{"Type":"bind","Source":"/home/mysql/conf","Destination":"/etc/mysql/conf.d","Mode":"","RW":true,"Propagation":"rprivate"}]
#发现也已经绑定成功
#删除容器后再次查看,发现目录还在,没有被删除
[root@localhost home]# docker stop data-mysql
data-mysql
[root@localhost home]# docker rm data-mysql
data-mysql
[root@localhost home]# cd /home/mysql/data/
[root@localhost data]# ls
auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 performance_schema public_key.pem server-key.pem
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 mysql private_key.pem server-cert.pem sys
其实,在官方的mysql镜像创建的时候,就已经挂载了一个目录
#1.再次创建一个mysql,但是不指定目录
[root@localhost home]# docker run -d -e MYSQL_ROOT_PASSWORD=root --name data-mysql mysql:5.7
#2.查看容器 卷的详情
[root@localhost home]# docker inspect --format="{{json .Mounts}}" data-mysql
[{"Type":"volume","Name":"aa6306ec0e6d9ade0dddfc6cf9a12e0026c91948e5fb37a2a007ddc2627ea505","Source":"/var/lib/docker/volumes/aa6306ec0e6d9ade0dddfc6cf9a12e0026c91948e5fb37a2a007ddc2627ea505/_data","Destination":"/var/lib/mysql","Driver":"local","Mode":"","RW":true,"Propagation":""}]
#发现,容器中的目录/var/lib/mysql被挂载到
#宿主机的/var/lib/docker/volumes/aa6306ec0e6d9ade0dddfc6cf9a12e0026c91948e5fb37a2a007ddc2627ea505/_data 目录下
所有的docker 容器内的卷,在没有指定目录的情况下,都是在/var/lib/docker/volumes/XXXX/_data 目录下
如果想在已经创建好的容器中添加挂载该怎么做。
#1.先在宿主机创建一个待同步目录/home/centos ,并在其中添加一个文件a.txt
[root@localhost data]# cd /home
[root@localhost home]# mkdir centos
[root@localhost centos]# cd centos
[root@localhost centos]# touch z.txt
#2.创建一个centos镜像
[root@localhost centos]# docker run -it --name=test centos /bin/bash
#3.在镜像内创建一个相同的目录,并创建一个inner.txt文件
[root@76ce255d0b55 home]# mkdir centos
[root@76ce255d0b55 /]# cd /home/centos/
[root@76ce255d0b55 centos]# touch inner.txt
#4. 退出容器
[root@76ce255d0b55 /]# exit
exit
# 5.停止docker
[root@localhost home]# systemctl stop docker.service
Warning: Stopping docker.service, but it can still be activated by:
docker.socket
#6. 修改容器的配置文件 vim /var/lib/docker/containers/container-ID全称/config.v2.json
[root@localhost home]# vim /var/lib/docker/containers/b67935441d15161b5c84c3f7fad173295c94c6e8395958a0cbc4a4baff293b17/config.v2.json
#修改MountPoints这个节点,建议下载下来改完再传回去,记得备份
"MountPoints": {
"/home/centos": {
"Source": "/home/centos",
"Destination": "/home/centos",
"RW": true,
"Name": "",
"Type": "bind",
"Spec": {
"Type": "bind",
"Source": "/home/centos",
"Target": "/home/centos"
},
"SkipMountpointCreation": false,
"Propagation":"rprivate"
}
},
#7.修改vim /var/lib/docker/containers/container-ID全称/hostconfig.json 其中的Binds节点
"Binds":["/home/centos:/home/centos"]
# 8.启动docker
[root@localhost ~]# systemctl start docker.service
#查看容器的挂载信息,发现成功了
[root@localhost ~]# docker inspect --format="{{json .Mounts}}" test
[{"Type":"bind","Source":"/home/centos","Destination":"/home/centos","Mode":"","RW":true,"Propagation":"rprivate"}]
#9. 启动容器
[root@localhost centos]# docker start test
test
[root@localhost centos]# docker exec -it test /bin/bash
[root@76ce255d0b55 /]# cd /home/centos/
[root@76ce255d0b55 centos]# ls
a.txt
# 发现inner.txt 不见了,宿主机的/home/centos目录把容器中的/home/centos覆盖
在已经创建的容器中添加卷时,宿主机目录会直接将容器中要挂载的目录覆盖
除了这种方式之外,还能通过docker export导出容器,然后在重新创建容器的时候指定目录。这种方式就不需要关闭整个docker容器。
附:修改容器端口
如果在创建容器的时候,忘记指定了 -p 属性,也能够通过修改配置文件的方式来指定。那他的很多信息也能通过类似的方式在容器创建后进行补充。
#1.创建一个mysql 不指定对外端口
docker run -d -e MYSQL_ROOT_PASSWORD=root --name port-mysql mysql:5.7
# 2.关闭docker
[root@localhost ~]# systemctl docker docker.service
#3.修改配置文件vim /var/lib/docker/containers/container-ID全称/config.v2.json
# NetworkSettings节点下的ports
"Ports": {
"3306/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "3306"
},
{
"HostIp": "::",
"HostPort": "3306"
}
],
"33060/tcp": null
},
#4.修改容器的文件 vim /var/lib/docker/containers/container-ID全称/hostconfig.json
#第一个3306表示容器端口,绑定到宿主机(HostPort:3306)
"PortBindings": {
"3306/tcp": [
{
"HostIp": "",
"HostPort": "3306"
}
]
},
# 开启docker
[root@localhost ~]# systemctl restart docker.service
#查看容器的端口配置
[root@localhost ~]# docker inspect --format="{{json .NetworkSettings.Ports}}" port-mysql
{"3306/tcp":[{"HostIp":"0.0.0.0","HostPort":"3306"},{"HostIp":"::","HostPort":"3306"}],"33060/tcp":null}