Docker学习笔记(四)--容器数据卷

164 阅读5分钟

很多时候,我们不希望直接将数据放在容器中。因为在容器的同时,也会将我们的数据进行删除。这时,我们就可以通过容器数据卷,来将数据放在宿主机中。

本章以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}