1. 概述

随着我们的应用程序越来越多地部署到云环境,对于开发者来说掌握Docker成为了一种必要技能。在调试应用时,复制文件到或从Docker容器中通常是很有用的操作。

本文将教您如何以不同方式在Docker容器之间复制文件。

2. Docker cp 命令

最快的方式从Docker容器中复制文件是使用docker cp命令。这个命令类似于Unix的cp命令,并具有以下语法:

docker cp

在查看此命令的一些示例之前,让我们假设我们正在运行以下Docker容器:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1477326feb62        grafana/grafana     "/run.sh"                2 months ago        Up 3 days           0.0.0.0:3000->3000/tcp   grafana
8c45029d15e8        prom/prometheus     "/bin/prometheus --c…"   2 months ago        Up 3 days           0.0.0.0:9090->9090/tcp   prometheus

第一个例子将主机机器的/tmp目录中的文件复制到grafana容器的安装目录中:

docker cp /tmp/config.ini grafana:/usr/share/grafana/conf/

我们也可以使用容器ID而不是名称:

docker cp /tmp/config.ini 1477326feb62:/usr/share/grafana/conf/

要将grafana容器中的文件复制到主机机器的/tmp目录,只需将参数顺序颠倒:

docker cp grafana:/usr/share/grafana/conf/defaults.ini /tmp

我们还可以复制整个目录而不仅仅是单个文件。这个例子将grafana容器中的整个conf目录复制到主机机器的/tmp目录:

docker cp grafana:/usr/share/grafana/conf /tmp

然而,docker cp命令也有一些限制。首先,我们不能使用它在两个容器之间复制。它只能用于在主机系统和单个容器之间复制文件。

其次,虽然它的语法与Unix cp命令相同,但它不支持相同的标志。事实上,它只支持两个:

-a: 归档模式,复制文件时会保留所有uid/gid信息
-L: 总是遵循SRC中的符号链接

3. 卷挂载

另一种从Docker容器中复制文件的方法是使用卷挂载。这意味着我们可以使主机系统中的目录在容器内部可用。

为了使用卷挂载,我们必须在容器启动时使用-v标志:

docker run -d --name=grafana -p 3000:3000 grafana/grafana -v /tmp:/transfer

上述命令运行一个grafana容器,并将主机机器的/tmp目录作为新目录挂载到容器内的/transfer中。如果我们想要,我们可以提供多个-v标志来在容器内创建多个卷挂载。

这种方法有几种优点。首先,我们可以使用Unix的cp命令,它比docker cp命令具有更多标志和选项

第二个优势是我们可以为所有Docker容器创建一个共享目录。这意味着只要它们都有相同的卷挂载,我们就可以直接在容器之间复制文件。

请记住,这种方法的一个缺点是所有文件都必须通过卷挂载进行传输。这意味着我们不能在一个命令中复制文件。相反,我们首先将文件复制到挂载的目录,然后复制到最终的目标位置。

这种方法的另一个缺点是我们可能会遇到文件所有权问题。Docker容器通常只有一个root用户,这意味着默认情况下容器内部创建的文件将由root拥有。如果需要,在主机机器上可以使用Unix chown命令恢复文件所有权。

4. Dockerfile

Dockerfile用于构建Docker镜像,然后将镜像实例化为Docker容器。Dockerfile可以包含多种不同的指令,其中之一是COPY

COPY指令允许我们将文件(或文件)从主机系统复制到镜像中。这意味着这些文件将成为从该镜像创建的每个容器的一部分。

COPY指令的语法与其他我们看到的复制命令相似:

COPY <SRC> <DEST>

就像其他复制命令一样,SRC可以是主机机器上的单个文件或目录,也可以包括通配符匹配多个文件。

让我们看看一些示例。

这将从当前Docker构建上下文复制单个文件到镜像中:

COPY properties.ini /config/

而这将复制所有XML文件到Docker镜像:

COPY *.xml /config/

这种方法的主要缺点是我们不能用它来运行Docker容器Docker镜像并非Docker容器,因此只有在知道镜像内部所需的文件集时才适合使用这种方法。

5. 结论

在这篇文章中,我们讨论了如何从和到Docker容器复制文件。每种方法都有其优缺点,所以我们必须选择最符合我们需求的方法。