从构建密钥设置Docker环境变量

15
当使用新的Docker构建增强功能时,是否有设置环境变量的方法?
已尝试过。
RUN --mount=type=secret,id=secret export SECRET=/run/secrets/secret
RUN --mount=type=secret,id=secret ENV SECRET=/run/secrets/secret

两者都不起作用。或者在dockerfile上设置环境变量的秘密是不好的吗?因为在明文中运行docker history到env var被设置。如果是这样的话,最好的方法是如何将env var设置得尽可能安全?

1
如果您将值放入环境变量中,它还会保密吗? - Raedwald
这没有什么意义。构建后的 ENV 变量将以明文形式在 docker inspect 中可见。 - anemyte
2个回答

13

如果您想从一个秘密中设置变量,可以在shell中使用$(cat /filename)语法。这会影响该单个步骤内的shell,因此所有使用该变量的地方都需要在同一步骤内。您不能将变量从RUN步骤提取到ENV步骤中。如果需要使其持久化到其他RUN步骤,则需要将变量写入文件系统并将其包含在镜像中,这是不理想的(相反,在后续的RUN步骤中只需再次挂载该秘密即可)。

以下是一个正常工作的示例,您也可以使用export secret_var导出该秘密:

$ cat df.secret
FROM busybox
RUN --mount=type=secret,id=secret \
    secret_var="$(cat /run/secrets/secret)" \
 && echo ${secret_var}

$ cat secret.txt
my_secret

$ docker build --progress=plain --secret id=secret,src=$(pwd)/secret.txt -f df.secret .
#1 [internal] load build definition from df.secret
#1 sha256:85a18e77d3e60159b744d6ee3d96908a6fed0bd4f6a46d038e2aa0201a1028de
#1 DONE 0.0s

#1 [internal] load build definition from df.secret
#1 sha256:85a18e77d3e60159b744d6ee3d96908a6fed0bd4f6a46d038e2aa0201a1028de
#1 transferring dockerfile: 152B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 sha256:a5a676bca3eaa2c757a3ae40d8d5d5e91b980822056c5b3b6c5b3169fc65f0f1
#2 transferring context: 49B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/busybox:latest
#3 sha256:da853382a7535e068feae4d80bdd0ad2567df3d5cd484fd68f919294d091b053
#3 DONE 0.0s

#5 [1/2] FROM docker.io/library/busybox
#5 sha256:08a03f3ffe5fba421a6403c31e153425ced631d108868f30e04985f99d69326e
#5 DONE 0.0s

#4 [2/2] RUN --mount=type=secret,id=secret     secret=$(cat /run/secrets/secret)  && echo ${secret}
#4 sha256:6ef91a8a7daf012253f58dba292a0bd86af1d1a33a90838b6a99aba5abd4cfaf
#4 0.587 my_secret
#4 DONE 0.7s

#6 exporting to image
#6 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00
#6 exporting layers 0.0s done
#6 writing image sha256:a52db3458ad88481406cd60627e2ed6f55b6720c1614f65fa8f453247a9aa4de done
#6 DONE 0.0s

请注意第四行代码#4 0.587 my_secret显示了输出的秘密。


1
使用环境变量中的构建密钥如何?我理解需要从文件中访问密钥,但是这个网站建议可以将密钥作为环境变量输入。 - wgj
@wgj,是的,你可以这样做,这个功能已经在20.10版本中加入了。但我认为这是另一个问题。根据示例,我最好的猜测是OP询问如何在运行的应用程序容器内设置环境变量。 - BMitch
明白了。是的,这正是我一直在寻找的,因为我自己无论如何都无法让它工作。 - wgj

-1

在您的示例中,环境变量是从秘密中设置的,但仅适用于该进程。

如果您想要运行时环境变量从秘密中设置,您需要挂载包含秘密的卷,或通过docker-compose传递秘密,在任何情况下,然后利用入口点脚本根据秘密位置设置秘密。

注意:秘密文件需要对将运行dockerfile的任何人/服务都可用。

向您的Dockerfile添加入口点脚本

Dockerfile:

FROM alpine

# Bash is needed for the script to set env_vars based on secrets
RUN apk upgrade --update-cache --available && \
    apk add bash \
    && rm -rf /var/cache/apk/*

# Adding entrypoint script to image
COPY ./docker_entrypoint /usr/local/bin/docker_entrypoint
RUN chmod +x /usr/local/bin/docker_entrypoint

ENTRYPOINT [ "docker_entrypoint"]

CMD ["printenv"]

这个脚本将查找格式为ENVAR_FILE的环境变量,以找到存储密钥的路径 - 将密钥导出到一个没有_FILE的环境变量中,然后调用剩余的命令。

docker_entrypoint:

#!/usr/bin/env bash

set -e

file_env() {
    local var="$1"
    local fileVar="${var}_FILE"
    local def="${2:-}"

    if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
        echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
        exit 1
    fi
    local val="$def"
    if [ "${!var:-}" ]; then
        val="${!var}"
    elif [ "${!fileVar:-}" ]; then
        val="$(< "${!fileVar}")"
    fi
    export "$var"="$val"
    unset "$fileVar"
}

# Explicitly list the environment variables you want to
# set from secrets
file_env "ENVAR1"
file_env "ENVAR2"

exec "$@"


现在您可以传递格式为ENVAR_FILE=/mnt/path/to/secret的环境变量 - 上述entrypoint脚本将读取该文件的内容并生成变量ENVAR=whateverYourSecretIs。
使用docker-compose的示例:
services:
  someService:
    image: <imageFromDockerFileAbove>
    environment: 
      - ENVAR1_FILE=/run/secrets/envar1
      - ENVAR2_FILE=/run/secrets/envar2
    secrets:
      - envar1
      - envar2
secrets:
  envar1:
    file: /pth/to/secret
  envar2:
    file: /pth/to/secret

期望输出:

someService_1  | HOSTNAME=<containerID>
someService_1  | ENVAR1=mysecret1
someService_1  | ENVAR2=mysecret2
someService_1  | PWD=/
someService_1  | HOME=/root
someService_1  | SHLVL=0
someService_1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

docker inspect --format='{{json .Config.Env}}' <containerID>

会返回:

["ENVAR1_FILE=/run/secrets/envar1","ENVAR2_FILE=/run/secrets/envar2","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接