Docker - 关于容器数据存储

容器结构

Docker容器启动结构:最上层是容器层,可读写层,之下就是镜像层,只读层

在这里插入图片描述

为什么有多个镜像层?

还记得Docker - 常用命令:帮助、镜像、容器下载镜像时,会发现需要下载多个镜像

在这里插入图片描述

每个容器都类似与简化的独立的Linux,自然需要底层支持,如tomcat肯定是需要jdk的支持的,在后续的DockerFile会介绍

那容器是如何获得镜像文件?

在这里插入图片描述

Docker运行容器会在镜像栈顶部添加一个读写层,如果运行中的容器修改现有文件时,该文件会从读写层下面的只读层复制到读写层(从上到下一层层找),只读版本是不会改变的,只是我们只能看到读写层的副本,这就是写时复制机制

这也是为什么不论我们怎么动容器,只要不提交镜像,通过镜像启动其他容器又是初始状态

存在的问题

Docker的这种结构,存在一些问题

  • 关闭或重启容器,该容器的数据不会被影响,但是删除该容器,数据就会丢失,因为容器的数据是不会影响到镜像
  • 存在于联合文件系统中,不易于宿主机的访问
  • 容器间数据共享不方便

就现在而言,能够想到保存数据的方法是docker cp从容器内拷贝数据到主机

在这里插入图片描述

什么是联合文件系统?

也就是上面描述的docker的容器-镜像结构:

联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下
联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
不同Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。


容器数据卷

为了解决上述问题,提出“卷”的概念:

“卷”是容器上的一个或多个“目录”,通过这种目录可以绕过联合文件系统,与宿主机的某目录绑定,可以理解为容器挂载一个虚拟数据卷然后映射到一个主机目录中

在这里插入图片描述

类似与Linux虚拟机与宿主机的共享文件夹


如何添加数据卷

说的再多不如操作一遍

添加容器数据卷有两种方法

  • run命令通过-v设置
  • 通过DockerFile添加

run -v添加

命令:docker run -v 宿主机目录路径:容器目录路径 镜像名

还是使用centos进行实验
在这里插入图片描述

运行容器:docker run -it -v /RootData:/ContainerData --name mycentos01 centos

可以看到容器mycentos01创建了数据卷,目录ContainerData
在这里插入图片描述

同样在宿主机创建了RootData文件夹

在这里插入图片描述

我们可以通过创建文件测试:创建container01.txt文件,写一句container add data01
在这里插入图片描述

在宿主机可以查看到:

在这里插入图片描述

通过数据卷,容器与宿主机可以完成数据共享及数据持久化

我们通过docker inspect(查看容器内部细节)也可以看到相关的信息:

docker inspect 5838bc2db5a9

其中有一条Binds属性

在这里插入图片描述

DockerFile创建

DockerFile是什么?
Dockerfile: 用于描述镜像的生成规则
Dockerfile中的每一条命令,都在Docker镜像中以一个独立镜像层的形式存在

DockerFile就类似与Linux的shell脚本,只不过DockerFile是用来构建镜像的
可以在gitHub上查看这些镜像

例如这个tomcat镜像的Dockerfile

在这里插入图片描述

因为DockerFile有自己的一套语法,比较复杂,后续介绍

总之,DockerFile类似与shell脚本一样,用于创建镜像

我们可以写一个简单的DockerFile:在根目录创建文件夹/mydocker
创建文件DockerFile
在这里插入图片描述

# volume test
FROM centos
VOLUME ["/dataVolumeContainer","/dataVolumeContainer2"]
CMD echo "finished,-----success"
CMD /bin/bash

意思就是,这个新镜像来自centos镜像,类似上面的结构centos为底层镜像;创建数据卷,两个目录路径分别是/dataVolumeContainer,/dataVolumeContainer2,打印finished,-----success,/bin/bash启动

出于可移植的考虑,不能用 -v 主机目录:容器目录的方法在DockerFile创建,毕竟不是所有宿主机都存在设置的目录

运行DockerFile创建新镜像

运行docker build -f /mydocker/DockerFile -t test/centos .

一层层的运行上面的脚本:
在这里插入图片描述

这样就有了自带数据卷的镜像

在这里插入图片描述
我们可以运行查看:
在这里插入图片描述

那我们宿主机对应的目录在哪呢?我们并没有定义,由Docker设置为默认路径

根目录下并没有
在这里插入图片描述

通过docker inspect查看

在这里插入图片描述

并不在原来的位置:
在这里插入图片描述

而是在Mounts:Source:

/dataVolumeContainer对应:
"Source": "/var/lib/docker/volumes/709f2595d2af0e95c305f34671a81253c6ff930313b9c85c5eaedcc108a7eb76/_data"
/dataVolumeContainer2对应:
"Source": "/var/lib/docker/volumes/8a856ecc1707a0612bf8193c09652bae12b86969414c404143afc9d70277197a/_data"

在这里插入图片描述

在dataVolumeContainer创建一个文件

在这里插入图片描述

在宿主机可以查看到:

在这里插入图片描述


数据卷容器

为了数据持久化、共享,每次启动一个容器都要设置数据卷,太繁琐了

能不能让数据卷“独立”出来,不同的容器只需要挂载这个数据卷就可以完成数据共享?

用专门的容器来挂载数据卷,其他容器通过挂载这个父容器来实现数据共享,这个专门挂载数据卷的容器称为数据卷容器

在docker通过--volumes-from在容器间传递共享

在这里插入图片描述

例如:

  • 根据上面test/centos镜像,创建容器centos01,docker run -it --name centos01 test/centos,在dataVolumeContainer目录下创建文件container01.txt

在这里插入图片描述

  • 传递共享,以centos01为数据卷容器,创建容器centos02
docker run -it --name centos02 --volumes-from centos01 test/centos

可以看到数据卷存在文件container01.txt,我们创建一个新文件container02.txt

在这里插入图片描述

  • 继续以centos01为数据卷容器创建新容器centos03

同样的操作:
在这里插入图片描述
确实,所有容器都可以共享文件

可以看到运行了3个容器:
在这里插入图片描述

我们知道centos01是数据卷容器,centos2、centos3都是继承centos1
如果删除它,其他容器还能共享文件吗?

删除:
在这里插入图片描述
重新连接centos02,创建文件update02.txt,重新连接centos03,可以确定依旧可以共享文件

在这里插入图片描述

得到结论:
容器间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现 PostgreSQL 的 Active-Active 复制,可以使用 docker-compose 来部署多个 PostgreSQL 实例。下面是一个简单的步骤: 1. 创建一个 docker-compose.yml 文件,并定义两个 PostgreSQL 容器,如下所示: ``` version: '3' services: postgres1: image: postgres volumes: - ./pgdata1:/var/lib/postgresql/data - ./pgconf:/etc/postgresql environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: mysecretpassword POSTGRES_DB: mydatabase PGDATA: /var/lib/postgresql/data/pgdata1 PGPORT: 5432 PGLOG: /var/log/postgresql/postgresql.log REPLICATION_USER: replicator REPLICATION_PASSWORD: mysecretpassword ports: - "5432:5432" networks: - postgres_network postgres2: image: postgres volumes: - ./pgdata2:/var/lib/postgresql/data - ./pgconf:/etc/postgresql environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: mysecretpassword POSTGRES_DB: mydatabase PGDATA: /var/lib/postgresql/data/pgdata2 PGPORT: 5433 PGLOG: /var/log/postgresql/postgresql.log REPLICATION_USER: replicator REPLICATION_PASSWORD: mysecretpassword ports: - "5433:5432" networks: - postgres_network networks: postgres_network: ``` 在上面的示例中,我们定义了两个 PostgreSQL 容器 postgres1 和 postgres2,它们都使用相同的数据库 mydatabase。我们还定义了一个网络 postgres_network,用于连接这两个容器。 2. 创建两个目录 pgdata1 和 pgdata2,用于存储 PostgreSQL 数据。我们还需要创建一个 pgconf 目录,用于存储 PostgreSQL 配置文件。 3. 使用 docker-compose 命令启动容器: ``` docker-compose up -d ``` 4. 进入 postgres1 容器,创建一个名为 replicator 的用户,并授权复制权限: ``` docker exec -it postgres1 psql -U postgres CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'mysecretpassword'; GRANT REPLICATION TO replicator; ``` 5. 修改 postgres2 容器的配置文件 pgconf/postgresql.conf,添加以下配置: ``` listen_addresses = '*' port = 5432 wal_level = replica max_wal_senders = 10 wal_keep_segments = 10 hot_standby = on ``` 6. 修改 postgres2 容器的配置文件 pgconf/pg_hba.conf,添加以下配置: ``` host replication replicator <ip-address-of-postgres1>/32 md5 ``` 7. 重启 postgres2 容器: ``` docker-compose restart postgres2 ``` 8. 在 postgres1 容器中创建一个名为 postgres2 的复制槽: ``` docker exec -it postgres1 psql -U postgres SELECT * FROM pg_create_physical_replication_slot('postgres2'); ``` 9. 在 postgres1 容器中创建一个名为 postgres2 的复制流: ``` docker exec -it postgres1 psql -U postgres SELECT pg_create_logical_replication_slot('postgres2', 'wal2json'); ``` 10. 在 postgres2 容器中启动流复制: ``` docker exec -it postgres2 pg_basebackup -h postgres1 -D /var/lib/postgresql/data -U replicator -v -P -Fp --xlog-method=stream docker exec -it postgres2 psql -U postgres SELECT * FROM pg_create_physical_replication_slot('postgres1'); SELECT * FROM pg_replication_slots; SELECT * FROM pg_stat_replication; ``` 完成上述步骤后,两个 PostgreSQL 容器就可以进行 Active-Active 复制了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值