Docker 中卷操作

236 阅读4分钟

这是我参与更文挑战的第14天,活动详情查看: 更文挑战

操作环境

  • Centos 7.9.2009
  • Docker version 20.10.2, build 2291f61

原始镜像

直接下载最新的redis镜像

docker pull redis
[root@testmachine fuhanxiao]# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
redis        latest    621ceef7494a   13 days ago   104MB
[root@testmachine fuhanxiao]# docker run -p 6379:6379 -d redis
1ab8246b84bc23afbd8348deecd74e4260d457e6dd987917bec8b1ddb3f1afdf

需要注意的是因为做了端口映射,必须要满足下面两个

必须要有firewalld或者是iptables服务在跑,默认centos7使用的是firewalld,systemctl status firewalld

必须要打开ip forward,echo 1 > /proc/sys/net/ipv4/ip_forward 查看下容器信息

[root@testmachine fuhanxiao]# docker inspect 1ab
...
...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "d31bb6212a374dd34a93a992274f3a522cd1555c554ccf497277c3c89a668f5b",
                "Source": "/var/lib/docker/volumes/d31bb6212a374dd34a93a992274f3a522cd1555c554ccf497277c3c89a668f5b/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...
...

可以看到原始镜像配置了一个volume,Destination对应的是容器内的目录/data,Source对应的是宿主机的目录,这里的目录名是一个随机数。

这其实是镜像内暴露了一个volume出来,但是起容器的时候没有声明本地对应的目录,所以docker就自己新建了一个目录作为对应的volume,下面我还会用自己新建的volume对这一理论进行验证。

声明volume 下面我们在原始镜像的基础上开始自己的实验。

创建Dockerfile内容如下

FROM redis
COPY ./redis.conf /usr/local/etc/redis/redis.conf
VOLUME /usr/local/etc/redis
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

主要是这里的第三行,通过VOLUME关键字将容器内部的一个目录声明成一个volume。需要注意的是Dockfile里面只能声明容器内部的目录,因为生成的镜像可能会被运行在各种设备上,所以宿主机的目录一定是在起容器的时候指定和生成的。

同时这里还拷贝了一份本地的配置文件到容器内,作为新镜像的启动配置,下面我们就用这个文件来进行测试。

生成新的镜像

[root@testmachine myredis]# docker build -t redis:v2 .
Sending build context to Docker daemon  190.5kB
Step 1/4 : FROM redis
 ---> 621ceef7494a
Step 2/4 : COPY ./redis.conf /usr/local/etc/redis/redis.conf
 ---> fdd3cb20855c
Step 3/4 : VOLUME /usr/local/etc/redis
 ---> Running in a95a0f7fad1c
Removing intermediate container a95a0f7fad1c
 ---> 884d688cb230
Step 4/4 : CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
 ---> Running in 9badfe62c79d
Removing intermediate container 9badfe62c79d
 ---> ca75e474ccf3
Successfully built ca75e474ccf3
Successfully tagged redis:v2
[root@testmachine myredis]# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
redis        v2        ca75e474ccf3   10 minutes ago   104MB
redis        latest    621ceef7494a   2 weeks ago      104MB

下面我们用这个新的v2镜像来测试。

创建volume

指定容器目录不指定宿主机目录

如上面看到的那样,指定了容器的目录但是不指定宿主机目录的话,docker会自动在宿主机上创建对应的目录。

其中指定容器目录的方式有两种:

通过命令行

[root@testmachine myredis]# docker run -p 6379:6379 -v /usr/local/etc/redis -d redis
af3aeeb1071d3fd2470fa3174803fc73c0872033f5e2e44c25144368f0281aa3

注意这里用的镜像是默认镜像redis,并不是redis:v2,然后通过-v参数声明了容器内的一个目录作为volume。

注意,为了避免错误,volume的目录路径最好是完整路径

下面查看下容器绑定的volume

[root@testmachine myredis]# docker inspect af3
...
...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "b7b0151ded2be4f71dab89ef1ce5289be2785917106d71efe35a0ca2e07aadf8",
                "Source": "/var/lib/docker/volumes/b7b0151ded2be4f71dab89ef1ce5289be2785917106d71efe35a0ca2e07aadf8/_data",
                "Destination": "/usr/local/etc/redis",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "d9b95843b00e4f4861668b79dcd8261b78a233c2c5ee4a588a664e4950730361",
                "Source": "/var/lib/docker/volumes/d9b95843b00e4f4861668b79dcd8261b78a233c2c5ee4a588a664e4950730361/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...
...

可以看到docker同样创建了一个随机目录,进入这个目录,新建一个文件写点内容

[root@testmachine myredis]# cd /var/lib/docker/volumes/b7b0151ded2be4f71dab89ef1ce5289be2785917106d71efe35a0ca2e07aadf8/_data
[root@testmachine _data]# echo 123 > test.txt

然后去容器内就马上能看到了

[root@testmachine fuhanxiao]# docker exec -it af3 /bin/bash
root@af3aeeb1071d:/data# cd /usr/local/etc/redis/
root@af3aeeb1071d:/usr/local/etc/redis# cat test.txt
123