Supervisor,Docker 和 Swarm 机密无法访问

Supervisor, Docker and Swarm secrets not accessible

我正在努力成为 docker、symfony、学说和 swarm 秘密的工作主管。

在我的 Dockerfile 中,我这样做:

FROM php:${PHP_VERSION}-fpm-alpine
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisor.conf"]

所以我启动了如下所示的 Supervisor:

我的主程序:

[program:php]
command=docker-entrypoint.sh "php-fpm"
autostart=true
autorestart=true

以入口点开始 PHP。在这个入口点,我只在产品中使用 swarm secrets:

 if [ "$APP_ENV" = 'prod' ]; then
    file_env DATABASE_URL
    file_env MESSENGER_TRANSPORT_DSN
  fi

  php bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration

在入口点内,命令 bin/console 运行良好。如果我处于开发模式,它使用我的 .env 文件中的本地 database_url,如果我处于生产模式,它使用 docker compose.

中定义的秘密

当我在 supervisor 中有第二个程序时会出现问题,如下所示:

[program:messenger-consume]
command=bash -c "export APP_ENV=%(ENV_APP_ENV)s && /usr/local/bin/launch.sh"
user=root

和launch.sh:

if [ "$APP_ENV" = "prod" ]; then
  php /srv/app/bin/console messenger:consume async --time-limit=3600 --memory-limit=128M -vv
fi

这里它失败了,出现了如下所示的 Doctrine 错误:

Access denied for user 'myname'@'10.0.1.4' (using password: YES)

实际上 'myname' 是我的 database_url dsn(对于学说)的 .env(对于开发环境)中的默认值。

这个主管问题与我无法自己执行条令命令有关。我的意思是当我 运行:

docker exec -i $(docker ps -q -f name="php*") sh

连接到我的容器,进入容器后我想执行如下操作:

./bin/console doctrine:migrations:migrate

它也不起作用(与主管中的错误相同)。

总而言之, docker swarm secrets 在由我自己或主管执行时不会“计算”,它们正在读取 . env 而不是读取 swarm secret 中的值......我不知道如何解决这个问题。 我试图添加到 docker exec -e DATABASE_URL=/run/secrets/doctrine_dsn 但它也不起作用(除非我给出秘密学说 dsn 的真实价值)。

任何帮助都会非常有用 非常感谢

我终于自己找到了答案。

我需要在每个需要环境变量的脚本中添加这个函数:

file_env() {
    local var=""
    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"
}

在 Supervisor 中,我需要导出原始环境变量名称,以便能够通过在命令中执行此操作来“重新计算”:

bash -c "export DATABASE_URL_FILE=%(ENV_DATABASE_URL_FILE)s && /usr/local/bin/launch.sh"

我不是很明白,但我认为该函数正在导出环境变量,但暂时,它只在脚本中可用。所以每次我需要自己使用一个 swarm secret(在 docker compose 中是这样声明的:DATABASE_URL_FILE=/run/secrets/doctrine_dsn) 我需要将该函数应用于相对环境变量。 我希望它很清楚:)

看起来像 comes from an early WordPress solution which unfortunately just converts the secret to an environment variable. That defeats the purpose of using Docker Secrets: preventing secrets from unintentionally leaking. Environment variables are routinely leaked in debug dumps, to logging and monitoring systems, and to child processes.最好避免将秘密放入环境变量中。

WordPress's current method 提供了一个更安全的解决方案:

function getenv_docker($env, $default) {
    if ($fileEnv = getenv($env . '_FILE')) {
        return rtrim(file_get_contents($fileEnv), "\r\n");
    }
    else if (($val = getenv($env)) !== false) {
        return $val;
    }
    else {
        return $default;
    }
}