docker 堆栈:从机密设置环境变量



我试图从秘密设置密码,但它没有拿起它。Docker Server 版本是 17.06.2-ce。我使用以下命令来设置机密:

echo "abcd" | docker secret create password -

我的码头工人撰写 yml 文件看起来像这样

version: '3.1'
...
 build:
  context: ./test
  dockerfile: Dockerfile
environment:
  user_name: admin
  eureka_password: /run/secrets/password
secrets:
  - password

我也有根机密标签:

secrets:
  password:
     external: true

当我在环境中对密码进行硬编码时,它可以工作,但是当我尝试通过机密时,它不会拾取。我试图将撰写版本更改为 3.2,但没有运气。任何指示都非常感谢!

要详细说明原始接受的答案,只需更改您的docker-compose.yml文件,使其包含以下内容作为入口点:

version: "3.7"
  services:
    server:
      image: alpine:latest
      secrets:
        - test
      entrypoint: [ '/bin/sh', '-c', 'export TEST=$$(cat /var/run/secrets/test) ; source /entrypoint.sh' ]
    
secrets:
  test:
    external: true

这样你就不需要任何额外的文件了!

你需要修改docker compose才能从/run/secrets读取秘密env文件。如果要通过 bash 设置环境变量,可以覆盖docker-compose.yaml文件,如下所示。

您可以将以下代码另存为entrypoint_overwrited.sh

# get your envs files and export envars
export $(egrep  -v '^#'  /run/secrets/* | xargs) 
# if you need some specific file, where password is the secret name 
# export $(egrep  -v '^#'  /run/secrets/password| xargs) 
# call the dockerfile's entrypoint
source /docker-entrypoint.sh

docker-compose.yaml覆盖dockerfileentrypoint键:

version: '3.1'
#...
build:
  context: ./test
  dockerfile: Dockerfile
entrypoint: source /data/entrypoint_overwrited.sh
tmpfs:
  - /run/secrets
volumes:
  - /path/your/data/where/is/the/script/:/data/
environment:  
  user_name: admin
  eureka_password: /run/secrets/password
secrets:
  - password

使用上面的代码片段,将覆盖环境变量user_nameeureka_password。如果您的秘密 env 文件定义了相同的 env var,那么如果您在服务中定义某些 env_file 也会发生同样的情况。

我发现了亚历杭德罗方法的巧妙扩展:使您的自定义入口点从ENV_FILE变量加载到ENV变量:

environment:
  MYSQL_PASSWORD_FILE: /run/secrets/my_password_secret
entrypoint: /entrypoint.sh

然后在您的entrypoint.sh

#!/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"
}
file_env "MYSQL_PASSWORD"

然后,当上游图像更改添加对_FILE变量的支持时,您可以删除自定义入口点,而无需更改撰写文件。

一种选择是在运行命令之前直接映射密钥:

entrypoint: "/bin/sh -c 'eureka_password=`cat /run/secrets/password` && echo $eureka_password'"

例如节点的 MYSQL 密码:

version: "3.7"
services:
  app:
    image: xxx
    entrypoint: "/bin/sh -c 'MYSQL_PASSWORD=`cat /run/secrets/sql-pass` npm run start'"
    secrets:
      - sql-pass  
secrets:
   sql-pass:
     external: true

这是对接受答案的类似方法,只是从另一边:"如果你想让一个秘密出现在环境中,只需在其名称后附加'.env'"。符合 POSIX 标准,因此适用于每个/bin/sh,而不仅仅是 bash:

# ############################################################
# secrets2env.sh
#
# Set environment variables from secret files
#
# For every secret file ending in ".env",
# set an environment variable with the same name
# but without the ".env" suffix, and the contents
# of the file as its value.
# Then call all positional parameters (=original entrypoint).
#
# This is meant to be used in docker compose when you don't have control
# over the docker image which requires secrets in environment variables.
# Simply inject this script as a new entrypoint and name your file
# secrets as required:
#
# ------------------------------------------------------------
# docker-compose.yml
# ------------------------------------------------------------
# services:
#   app:
#     entrypoint: ["/run/secrets/secrets2env.sh", "/original-entrypoint-if-any"]
#     secrets:
#       - ADMIN_PASSWORD.env
#       - source: secrets2env.sh
#         target: /run/secrets/secrets2env.sh
#         mode: 0777
#
# secrets:
#  ADMIN_PASSWORD.env:
#    file: ./secrets/ADMIN_PASSWORD.env
#  secrets2env.sh:
#    file: ./secrets/secrets2env.sh
# ------------------------------------------------------------
# (adding the script itself as a secret seems fitting, you may prefer it
# as a config, or even just a bind mount)
# (the file in /run/secrets/ will be named ADMIN_PASSWORD.env
# because that's the name of the secret - your original local file could
# be named differently - I'm just trying to keep it simple)
#
# The container will get an environment variable
# "ADMIN_PASSWORD" with the value being the contents
# of your file ./secrets/ADMIN_PASSWORD_ENV.env
# (in the container, the file /run/secrets/ADMIN_PASSWORD.env
# will also still exist, it is just read into the variable)
#
# Unfortunately, it's not possible to "inherit" the original
# entrypoint and command of the image. Even worse, if you set
# a new entrypoint then the original command is nulled out and needs
# to be set again. See https://stackoverflow.com/a/47063296
#
# Use docker inspect to look them both up, e.g. `docker inspect postgres:13`
# will show you in "Config" that "Cmd": ["postgres"] and
# "Entrypoint": ["docker-entrypoint.sh"] so you set
# entrypoint: ["/run/secrets/secrets2env.sh", "docker-entrypoint.sh"]
# command: postgres
# You may want to copy it to /secrets2env.sh to make the call shorter
# but I prefer it in the same directory as the secret files.
# ############################################################
for secret_file in $(find /run/secrets -name '*.env'); do
    export "$(basename "${secret_file%.env}")"="$(cat "$secret_file")"
done
# Chain with existing entrypoint (if any)
exec "$@"

设置文件模式以使其可执行需要长符号,这使得它有点拗口。如果多个服务需要这个,你可以添加到你的docker-compose.yml的顶部

x-secrets2env: &secrets2env
  source: secrets2env.sh
  target: /run/secrets/secrets2env.sh
  mode: 0777

然后,只要您有一个或多个"环境机密",就可以参考它:

services:
  app:
    entrypoint: ["/run/secrets/secrets2env.sh", "/entrypoint.sh"]
    secrets:
      - ADMIN_PASSWD.env
      - DB_PASSWORD.env
      - *secrets2env

因为您正在使用文件而不是值初始化eureka_password。

最新更新