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容器复制文件。每种方法都有其优缺点,所以我们必须选择最符合我们需求的方法。