问题描述
需要构建一个包含预填充数据库的Docker镜像。目前,他们在Dockerfile中使用以下命令:
COPY db-dump.gz /tmp
RUN zcat /tmp/db-dump.gz | mysql
但是否有一种方法可以在不首先将(可能很大的)转储文件复制到容器中的情况下实现相同的结果?
在shell级别上,他可以使用类似以下示例的方式将数据通过管道传输到容器中:
zcat db-dump.gz | docker exec -i $CID mysql
但我不知道在Dockerfile中是否有类似的选项。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
使用BuildKit和实验性前端
使用BuildKit和实验性前端可以实现这个目标。在18.09版本之后,可以通过以下方式启用BuildKit:
- 对于单个Shell,可以执行以下命令:
bash
export DOCKER_BUILDKIT=1 - 若要更改主机的默认设置,可以将以下内容添加到
/etc/docker/daemon.json
文件中:
json
{
"features": {"buildkit": true}
}
修改完成后需要重新加载Docker引擎。
启用BuildKit后,你的Dockerfile如下所示:
# syntax=docker/dockerfile:experimental
RUN --mount=type=bind,source=db-dump.gz,target=/tmp/db-dump.gz \
zcat /tmp/db-dump.gz | mysql
在此Dockerfile中,我们使用了--mount
参数来将本地文件(db-dump.gz
)绑定到容器内的路径(/tmp/db-dump.gz
)。这样就可以在不复制文件的情况下在容器内部访问文件。然后,我们使用zcat
命令解压缩文件,并将数据导入到MySQL数据库中。
要构建此镜像,可以使用以下命令:
docker build .
请确保已启用BuildKit。有关BuildKit实验性功能的更多信息,请参阅BuildKit实验性功能文档。
使用脚本来控制容器运行顺序(备选方案)
另一种方法是使用脚本来控制容器的运行顺序。你可以编写一个脚本,使用docker run
命令手动控制容器的启动顺序。以下是一个简单的bash脚本示例,可以实现这个目标:
#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b
在此示例中,我们使用docker run
命令启动容器A,并等待容器A完全启动。一旦容器A准备就绪,我们再启动容器B。
请注意,这种方法可能会增加复杂性,并且需要确保容器A和容器B之间的依赖关系正确设置。
这两种方法都可以帮助你实现在Dockerfile中使文件在RUN命令中可访问的目标。根据实际情况选择合适的方法。
请注意,以上方案中的命令和示例可能会因Docker版本和环境而异,建议在实际操作前先做好备份并仔细测试。