Docker编写:
version: "3"
services:
db:
container_name: db
image: mysql
ports:
- "3306:3306"
volumes:
- initdb:/docker-entrypoint-initdb.d/:ro
web:
container_name: web
image: my_web
volumes:
- initdb:/initdb/:ro
depends_on:
- db
volumes:
initdb:
my_web映像包含/initdb/create_schema.sql。
web依赖于db。因此服务db将在web之前启动。来自web的create_schema. sql是否可供db使用?
通过测试,它是可用的。这是保证还是随机的?
create_schema. sql是在构建my_web映像时生成的。它不在主机磁盘上。
尝试了解卷何时创建并Map到容器。如果在启动所有容器之前创建并Map卷,则可以保证通过卷共享的数据可用。
2条答案
按热度按时间igetnqfo1#
大多数应用程序框架都包含某种 * 数据库迁移 * 系统,一种更健壮的方法是让应用程序在启动时运行迁移,而不是尝试使用这样的命名卷。
Docker命名卷有一个微妙的顺序来将内容复制到卷中。当创建一个挂载卷的容器时,当且仅当卷完全为空时,内容将从挂载点复制到镜像中。这仅在卷为空时发生(因此它永远不会看到映像内容的更改),并且它只发生在Docker命名卷上,而不是其他类型的挂载(Docker bind mounts,Kubernetes PersistentVolumeClaims,...)。
这个序列意味着Compose将
1.创建命名卷
1.创建并启动
db
容器,挂载空卷1.创建并启动
web
容器,此时Docker会将脚本复制到卷中这会导致一个竞态条件,即不确定是
web
容器启动时首先复制文件,还是db
容器开始在该目录中查找初始化脚本。如果您将此设置扩展到use a health check以等待数据库运行,那么这根本不起作用。在
db
容器完成初始化之前,不会创建web
容器,这意味着您可以保证扫描/docker-entrypoint-initdb.d
目录时卷为空。同样,请记住Docker永远不会 * 更新 * 卷的内容,因此如果您更改初始化脚本,卷仍将使用旧的卷。标准数据库映像也仅在其数据目录未初始化时运行
/docker-entrypoint-initdb.d
。运行迁移系统可以避免这两个问题。xmq68pz92#
如果你想的话
create_schema. sql是在构建my_web映像时生成的。它不在主机磁盘上。
然后你需要创建第三个容器(它可以用类似于
web
文件的Dockerfile生成,但有不同的入口点)让我们将其命名为init-db-script
,在db容器之前启动它,在其中生成create_schema.sql
然后将其添加到depends for db
或者你可以尝试通过
docker run
为'脚本容器'创建卷中的数据,这将在脚本完成后停止,但卷中的数据将被创建。但我建议在构建脚本之前生成
create_schema.sql
,将其添加到存储库中,并将其副本添加到其Dockerfile中的db的Docker映像中