从 Docker 容器复制文件到主机
在 Docker 1.8 之前,我们只能将文件从容器复制到主机。但是,随着容器变得更加流行,将文件复制到容器中或从容器中复制文件已成为必要。
我们可能想要从 docker 容器复制文件的常见原因之一是与我们的团队成员共享日志文件。但是,不允许复制/dev
、/proc
、/sys
、tmpfs
下的资源等敏感信息。
本文将讨论如何使用 DockerFile、docker cp
命令从 Docker 容器中复制文件,并将目录作为卷挂载到主机。
这需要正确安装和配置 Docker 和 Docker 容器。这适用于 Linux 和 WSL 环境。
使用 docker cp
将文件从 Docker 容器复制到主机
docker cp
命令是我们可以用来将文件和目录以及从主机复制到 docker 容器的最简单方法之一。我们将使用 Ubuntu 20.4.5 和当时最新版本的 Docker,即 19.03。
语法:
$ docker cp [OPTIONS] CONTAINER: SRC_PATH DEST_PATH|-
其中,
SRC_PATH
指定我们要复制的文件在主机上的源路径。DEST_PATH
是在容器上存储文件的目标路径。
使用此命令,我们可以通过交换参数 SRC_PATH
和 DEST_PATH
来将文件复制到容器中或从容器中复制文件。此命令的一个优点是我们可以将文件和目录复制到正在运行或已停止的容器中或从中复制。
docker cp
命令类似于 Unix cp -a
;因此,这意味着它还递归地复制目录。此外,该命令还假定容器的所有路径都相对于根目录。
我们将首先创建我们的目标容器;因此,我们还需要一个镜像。我们将使用 Docker 注册表中提供的官方 Ubuntu 映像。
$ docker pull ubuntu
然后,我们将以分离和交互模式创建一个 docker 容器。这允许我们的容器在后台运行。
$ docker run -it -d ubuntu
e10b4a7bbc59131d30492a87dd70b8ea74fa686ed5036ec918b6596fc83efe2b
使用 exec
命令,我们将使用命令 docker exec
和 -it
标志运行交互式 SSH 会话。这将允许我们在容器内交互地运行命令。
要创建一个简单的文本文件,我们将导航到 /usr/share
文件夹。
我们将首先使用相应的容器 ID 进入容器。
$ docker exec -it e10b4a7bbc59 /bin/bash
root@e10b4a7bbc59:/#
我们将导航容器内的文件夹 /usr/share/
以创建我们的文本文件。
$ docker exec -it e10b4a7bbc59 /bin/bash
root@e10b4a7bbc59:/# cd usr
root@e10b4a7bbc59:/usr# cd share
root@e10b4a7bbc59:/usr/share#
我们将使用 touch
命令创建一个名为 new_file.txt
的文件。我们将很快将此文件从该容器复制到我们的主机。
因此,最好记下存储文件的目录,因为我们将在将文件复制到主机时使用该位置。
root@e10b4a7bbc59:/usr/share# touch new_file.txt
要验证我们是否已创建文件,请运行 ls
命令列出此目录中的所有文件,如下所示。
root@e10b4a7bbc59:/usr/share# ls
adduser bash-completion debianutils dpkg keyrings man pam polkit-1
apport bug dict gcc libc-bin menu pam-configs sensible-utils
base-files common-licenses doc gdb lintian misc perl5 tabset
base-passwd debconf doc-base info locale new_file.txt pixmaps terminfo
现在我们已经成功地在容器中创建了一个文件,我们想将这个文件从这个容器复制到我们的主机 - 使用 exit
命令从容器退出到主 shell。
我们将在终端中运行 docker cp
命令并将 new_file.txt
复制到主机的目录中。但是,我们首先需要注意三个重要的事情:
- 容器标识;
- 目标文件在容器中的位置;
- 我们将复制文件的主机中的目标目录。
$ docker cp e10b4a7bbc59:/usr/share/new_file.txt ./new_file.txt
通过执行该命令,我们已成功将 new._file.txt
复制到主机。我们可以通过在该特定文件夹中运行 ls
命令来验证这一点。
isaac@DESKTOP-HV44HT6:~/isaac$ ls
adduser bash-completion debianutils dpkg keyrings man `new_file.txt` pixmaps terminfo
apport bug dict gcc libc-bin menu pam polkit-1
base-files common-licenses doc gdb lintian misc pam-configs sensible-utils
base-passwd debconf doc-base info locale my-app perl5 tabset
使用 Docker Mounts 将文件从 Docker 容器复制到主机
我们还可以使用 docker mounts 将文件从 docker 容器复制到主机。
绑定挂载是最早的解决方案之一,它允许我们通过将 docker 容器挂载到主机系统上的目录来持久化数据。
绑定挂载允许我们通过引用目标目录的绝对文件路径来引用确切的目录。除了将文件从容器复制到主机之外,我们还可以创建依赖于主机系统目录的服务。
要创建 docker 挂载,我们可以在创建 docker 容器时使用 -v
或 --mount
标志。除了这个标志之外,我们还将指定我们想要映射到 docker 容器上的目录的主机上的目录。
这种方法通常是首选,因为我们可以在 docker 容器内创建多个挂载。我们还可以创建目录来从多个容器传输文件。
要将我们的目录挂载到 docker 容器,我们必须指定以下字段,这些字段应始终以正确的顺序由冒号分隔。这些包括:
- 我们要挂载的主机目录的路径;
- 我们应该挂载该目录的容器中目录的路径;
- 其他可选选项如
ro
指定只读模式。
语法:
docker run -t -i -v <host_dir>:<container_dir
在下面的示例中,我们使用 Ruby 官方镜像来创建容器并将本地目录挂载到容器上的目录中。完成此操作后,我们可以轻松地将文件从容器复制到本地目录,反之亦然。
$ docker run -it -v $HOME/Desktop/new_container:/new_container --name new_container ruby bash
root@7a00af9d4d96:/#
我们可以轻松地在 docker 容器和主机目录之间复制文件。另外,请注意,在主机目录中创建的文件将自动在挂载到主机的 docker 容器目录中可用。
使用 COPY
将文件从 Docker 容器复制到主机
当使用 docker 文件创建 docker 镜像时,我们还可以使用 COPY
命令在 docker 主机和容器之间复制文件。
语法:
COPY <SRC> <DEST>
在下面的 DockerFile 中,我们将 ./app.py
指定为源目录,将 /var/www/app.py
指定为目标目录。
# base image
FROM python
# Set your working directory
WORKDIR /var/www/
# Copy the necessary filesls
COPY ./app.py /var/www/app.py
COPY ./requirements.txt /var/www/requirements.txt
# Install the necessary packages
RUN pip install -r /var/www/requirements.txt
# Run the app
ENTRYPOINT ["echo", "Hello, Developer"]
这个 DockerFile 创建一个简单的 Flask 应用程序的镜像,该应用程序在控制台上打印一条消息。
Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.
LinkedIn