Dockerfile COPY 命令将文件复制为目录

Dockerfile COPY command copies file as a directory

请注意:这个问题提到Java和Java密钥库,但实际上没有使用 Java 进行操作,任何对 Docker 有足够了解并编写 Docker 文件的人都应该负责。


我有一个 Web 服务 (myservice),它是一个已经 Docker 化的 JVM 应用程序。 Dockerfile 看起来像这样:

FROM openjdk:8-jdk-alpine as myenv

COPY application.yml application.yml
COPY ${KS_FILE} mykeystore.p12
COPY build/libs/myservice.jar myservice.jar

EXPOSE 9200

ENTRYPOINT [ \
    "java", \
    "-Dspring.config=.", \
    "-Dkeystore.file=mykeystore.p12", \
    "-jar", \
    "myservice.jar" \
]

郑重声明,mykeystore.p12 是一个 文件(不是目录!),它存储 SSL 证书,该服务将返回给任何试图创建的客户端与它的联系。具体来说,它是一个加密的 Java keystore 但这超出了这个问题的范围,而且不是重点。重要的是你明白它是一个文件,而不是一个目录。 我将文件存储在我的本地计算机上。

我在该项目的根目录中也有以下 .env 文件:

MYENV=local
KS_FILE=../apprunner/certs/mykeystore.p12

因此,../apprunner/certs/mykeystore.p12 是我的文件系统上 mykeystore.p12 所在位置的相对路径,我希望该 URI 存储在 .env 文件中并用作环境来自 Dockerfile.

内部的变量

我这样构建图像:

docker build -t myorg/myservice .

我 运行 像这样的图像容器:

docker run -d -p9200:9200 --name myservice --net myrunner_default --env-file .env myorg/myservice

当我 SSH 进入 运行ning 容器时,我 do 在本地文件系统上看到 mykeystore.p12except...

这是一个目录!不是文件!

$ docker exec -it 8391601f451b /bin/sh
/ # ls -al
total 62936
drwxr-xr-x    1 root     root          4096 Feb  1 21:24 .
drwxr-xr-x    1 root     root          4096 Feb  1 21:24 ..
-rwxr-xr-x    1 root     root             0 Feb  1 21:24 .dockerenv
-rw-r--r--    1 root     root          1510 Jan 29 16:27 application.yml
drwxr-xr-x    2 root     root          4096 May  9  2019 bin
drwxr-xr-x    7 root     root          4096 Jan 30 22:50 mykeystore.p12
-rw-r--r--    1 root     root      64371878 Jan 29 16:27 myservice.jar
drwxr-xr-x    5 root     root           340 Feb  1 21:24 dev
drwxr-xr-x    1 root     root          4096 Feb  1 21:24 etc
... etc.

里面有很多奇怪的、意想不到的东西,比如我项目中其他目录的源文件!

显然,在我的 Dockerfile 中使用 ${KS_FILE} 或者 URI 值在我的 .env 文件中的存储方式有问题。无论如何,我必须改变什么:

  1. 我在 .env 文件中指定了 KS_FILE 环境变量的文件路径和名称;和
  2. 在我的 .envDockerfile 之间,文件路径 + 名称被作为 file 复制到 运行ning 容器中,例如当我从容器内部 ls -al 时,我将其视为一个文件?

这里有两个问题。

您只能从构建目录复制文件

您不能复制存在于构建目录之外的文件(例如 ../apprunner/certs/mykeystore.p12)。如果您尝试在 Dockerfile 中引用此文件目录,如下所示:

FROM openjdk:8-jdk-alpine as myenv

COPY application.yml application.yml
COPY ../apprunner/certs/mykeystore.p12 mykeystore.p12

您将看到以下错误:

Step 3/6 : COPY ../apprunner/certs/mykeystore.p12 mykeystore.p12
COPY failed: forbidden path outside the build context: ../apprunner/certs/mykeystore.p12 ()

环境变量扩展不能那样工作

来自 the documentation:

Environment variables (declared with the ENV statement) can also be used in certain instructions as variables to be interpreted by the Dockerfile. Escapes are also handled for including variable-like syntax into a statement literally.

由于您尚未在 Dockerfile 中声明任何 ENV 语句, 该环境扩展为一个空字符串,因此您将获得 效果:

COPY "" mykeystore.p12

这将简单地将构建目录的内容复制到 mykeystore.p12.

docker build 没有使用 .env 文件。

This article 可能会有帮助。