在Dockerfile中如何避免复制文件以使其在RUN命令中可访问

34次阅读
没有评论

问题描述

需要构建一个包含预填充数据库的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:

  1. 对于单个Shell,可以执行以下命令:
    bash
    export DOCKER_BUILDKIT=1
  2. 若要更改主机的默认设置,可以将以下内容添加到/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版本和环境而异,建议在实际操作前先做好备份并仔细测试。

正文完