docker-compose redis password via environment variable

Viewed 18428

I'm trying to pass my redis password to docker-compose via environment variable but it gives me an errors.

Here is mine part of mine docker-compose with redis image:

  redis:
    image: redis
    container_name: redis
    # command: redis-server --requirepass mypassword <--- this works as expected
    # command: redis-server --requirepass ${REDIS_PASSWORD} <-- this is not
    command: redis-server --requirepass $${REDIS_PASSWORD} <-- and this is not
    volumes:
      - redis:/var/lib/redis/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
    ports:
      - "6379"
    env_file:
      - .env.prod

My .env.prod

REDIS_PASSWORD=mypassword

It gives me an error:

consumer: Cannot connect to redis://:**@redis:6379/0: WRONGPASS invalid username-password pair or user is disabled..

But if I specifying password directly in docker-compose without env variable it works.

3 Answers

This should work:

    redis:
        image: redis
        command: >
          --requirepass ${REDIS_PASSWORD}

None of the answers worked for me. Here is what I ended up doing, adjusted to the code snippet provided by OP:

redis:
  image: redis
  container_name: redis
  command:
    - /bin/sh
    - -c
    # - Double dollars, so that the variable is not expanded by Docker Compose
    # - Surround by quotes, so that the shell does not split the password
    # - The ${variable:?message} syntax causes shell to exit with a non-zero
    #   code and print a message, when the variable is not set or empty
    - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}"
  volumes:
    - redis:/var/lib/redis/data
    - ./redis.conf:/usr/local/etc/redis/redis.conf
  ports:
    - "6379"
  env_file:
    - .env.prod

I changed the command field, so that the command is run through the shell — this way, /bin/sh can expand the REDIS_PASSWORD variable or exit with an error message, if the variable could not be find.

As for why the code snippet in question does not work:

  1. command: redis-server --requirepass ${REDIS_PASSWORD}

    In this case, the ${REDIS_PASSWORD} would be expanded by Docker Compose. Docker Compose first tries to find an environment variable called REDIS_PASSWORD. Then, Docker Compose looks for file .env (yes, even if the env_file field was provided). Because the variable is defined in file .env.prod, Compose cannot find it.

  2. command: redis-server --requirepass $${REDIS_PASSWORD}

    Here, ${REDIS_PASSWORD} is passed unexpanded to the redis-server command. This is because Docker runs the redis-server command directly, not through the shell. When one enters that command in a terminal emulator, the shell, usually Bash, expands the variable before running the command.

Sources

env_file allows to set environment variables in the container - while you need them in the environment of docker-compose in order to perform variable substitution for ${REDIS_PASSWORD}.

To achieve your goal remove the env_file from your yml and, either:

  • rename your .env.prod file to just .env, so that docker-compose would automatically pick it; or,
  • specify it while calling docker-compose, by way of the --env-file parameter:
docker-compose --env-file .env.prod up
Related