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;
}
}
我正在努力成为 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) 我需要将该函数应用于相对环境变量。 我希望它很清楚:)
看起来像
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;
}
}