Search code examples
dockersymfonydocker-swarmsupervisorddocker-secrets

Supervisor, Docker and Swarm secrets not accessible


I'm struggling to make working supervisor with docker, symfony, doctrine and swarm secrets.

In my Dockerfile, I'm doing this:

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

So I launch Supervisor which looks like this:

My main program:

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

which starts PHP with an entry point. In this entry point, I use swarm secrets only in prod:

 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

Inside the entry point, the command bin/console is working perfectly fine. If I am in dev mode, it use the local database_url in my .env file, if i am in prod it use the secrets defined in the docker compose.

The problems happens when I have a second program in supervisor which is like this:

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

and launch.sh :

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

And here it's failing with a Doctrine error who looks like this:

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

and actually 'myname' is the default value in the .env (for dev environment) for my database_url dsn (for doctrine).

This supervisor problem is linked to the fact that I cannot execute doctrine commands by myself. I mean when I run:

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

to connect to my container and after inside the container i want to execute something like this:

./bin/console doctrine:migrations:migrate

it's not working also (same error as in supervisor).

To sum-up, docker swarm secrets are not "computed" when it's executing by myself or by supervisor, they are reading the default value in the .env and not reading the value in the swarm secret... and i have no idea how to solve this. i tried to add to docker exec -e DATABASE_URL=/run/secrets/doctrine_dsn but it's not working either (except if i give the true value of secrets doctrine dsn).

Any help would be very great thanks a lot


Solution

  • Looks like the original answer 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. It's best to avoid putting secrets in environment variables.

    WordPress's current method provides a much more secure solution:

    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;
        }
    }