我们正在部署一个堆栈,撰写文件列表两个服务:
我们看到了 directive,将数据库持久化到一个Docker卷
然而,如果我们docker stack rm然后docker stack deploy我们的撰写文件,我们失去了所有的数据库内容。
这是预期的行为吗?这样做的理由是什么?
发布于 2019-05-15 14:26:48
群模式不构建对接图像,所以可以肯定地说,停靠者群忽略了您的Dockerfile的每一行。生成的映像将具有一个卷标识,该卷将在容器运行时创建,无论它是在群集模式内还是在群集模式之外。如果您没有在运行时指定卷挂载,那么docker将在该位置为您提供一个匿名卷(稍后很难识别),并且是容器正在运行的节点的本地卷。使用新堆栈,将不会使用以前的匿名卷,而且在各种情况下,匿名卷可以自动删除(例如,当容器配置为退出时自动删除时,我不确定它是否适用于群集模式)。
命名卷可以使数据更容易在单个节点集群中重用。当您到达多节点集群时,需要将这些数据移出正在运行容器的节点。有关如何将NFS之类的内容用于外部数据存储的详细信息,请参阅this answer中的相关问题。
发布于 2019-05-15 14:22:32
Dockerfile有一个卷,但您可能还没有将该卷挂载到容器外部可访问的位置,这意味着它可能不会被拖出到要在容器/容器部署之间共享的持久覆盖存储中。
在docker-compose.yml文件中的数据库服务中,您需要一个volumes部分。我省略了您当前的设置,因为您没有提供它,我将用省略号...替换它。
mySQL:
...
volumes:
- mySQL-data:/var/lib/mysql这告诉系统,您希望将容器外的/var/lib/mysql目录保存在共享覆盖层中,我随机命名为mySQL-data。
发布于 2019-05-15 14:57:55
在这种情况下,处于群体模式是不相关的。
如果您只依赖于Dockerfile中定义的匿名卷,那么运行一个新容器将创建和挂载一个新卷。您需要在容器开始时专门挂载一个指定的卷(在您的情况下,将它添加到您的撰写文件中),以便在运行之间重新装入相同的卷。
如果需要重新装入丢失的数据卷,如果没有在服务器上删除数据,则仍有可能。您只需要找到相关的卷(其中有一个散列作为名称),最终将其重命名并重新装入您的新容器。
我使用了以下场景来说明我的观点:
首先获取图像并看一看:
$ docker pull mysql:latest
$ docker image inspect mysql:latest从最后一个命令中我们可以看到,有一个为/var/lib/mysql声明的卷
我在我的开发机器上。把所有东西都清理干净了,所以现在我没有卷了
$ docker volume ls
DRIVER VOLUME NAME
$启动一个容器,然后再查看卷
$ docker run -d --name test -e MYSQL_ALLOW_EMPTY_PASSWORD=1 mysql:latest
37a92341f52b189d00636d1f03ecfbd4e3e7e5d55b685f5ec254971d7732566c
$ docker volume ls
DRIVER VOLUME NAME
local 50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7现在向容器中添加一些数据。
$ docker exec -it test bash
root@37a92341f52b:/# mysql
Welcome to the MySQL monitor. [... snip ...]
mysql> create database testso;
Query OK, 1 row affected (0.03 sec)
mysql> use testso;
Database changed
mysql> create table test (id int not null primary key);
Query OK, 0 rows affected (0.08 sec)
mysql> insert into test values (1);
Query OK, 1 row affected (0.05 sec)
mysql> select * from test;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> exit
Bye
root@37a92341f52b:/# exit
$ 创建一个新容器
$ docker rm -f test
test
$ docker run -d --name test -e MYSQL_ALLOW_EMPTY_PASSWORD=1 mysql:latest
79148de09d7a3e13db338da133cfd7d44fe3590dc1c7ffe6129722c5c6baea21
$ docker volume ls
DRIVER VOLUME NAME
local 50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7
local ef6fb2647c11c10ef98d25ca0dc2bd43231729ed18386c65768a0ad808fca93b如您所见,我们为新容器准备了第二个卷。我将在这里不显示这一点,但如果我连接,数据是空的,在您的情况下。现在让我们试着恢复。
先做个小清理
$ docker rm -f test
test
$ docker volume rm ef6fb2647c11c10ef98d25ca0dc2bd43231729ed18386c65768a0ad808fca93b
ef6fb2647c11c10ef98d25ca0dc2bd43231729ed18386c65768a0ad808fca93b我们希望有一个人类可读的名字,但我们不能重命名一个卷。我所做的是将旧的卷和一个新的命名卷装入一个busybox容器中,以传输数据。
$ docker run -it --rm -v 50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7:/mysql/old -v mysql_data:/mysql/new busybox:latest
/ # cd /mysql/
/mysql # mv old/* new/
/mysql # exit现在我们有了这个新的卷,我们可以去掉那个匿名的。
$ docker volume ls
DRIVER VOLUME NAME
local 50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7
local mysql_data
$ docker volume rm 50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7
50f9810d13271c7c91b7e025e139db480f288a936f0a55f85d9580ef3aa83af7最后,我们将命名卷重新装入一个新的mysql容器中,以获取数据。
$ docker run -d --name test -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -v mysql_data:/var/lib/mysql mysql:latest
3f6eff0b7660f3f8e9518564affc6555acb17184845156099d18300b3e76f4a2
$ docker exec -it test bash
root@3f6eff0b7660:/# mysql
Welcome to the MySQL monitor. [... snip ...]
mysql> use testso
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from test;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.01 sec)https://stackoverflow.com/questions/56151262
复制相似问题