Maxime Flament
Maxime Flament

Reputation: 751

Cannot use ENV variable from Docker container to perform HEALTHCHECKS in docker-compose file

I have a docker-compose file with a database service that gets an environment file for users and passwords (I removed the env variable for the password as the problem is the same for both user and password):

db:
    restart: always
    container_name: db
    image: mariadb:10.3.9
    env_file:
      - my_env_file.env
    volumes:
      - /opt/dbdata:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysql", "-u", "${DB_USER}", "-e", "\"SHOW DATABASES;\""]
      interval: 1m
      timeout: 10s
      retries: 10

The environment file has a DB_USER entry:

DB_USER=TEST

When building and starting the container with docker-compose, the environment variable cannot be resolved by Docker since the variable only exists in the db container, and I'm getting the following warning:

WARNING: The DB_USER variable is not set. Defaulting to a blank string.

Is there a way to tell Docker to avoid resolving the value of this env variable on the host, but instead resolve it from my container?

I do not want to provide the env variable on the host for security reasons.

I also do not want to use mysqladmin as it can result in false positives (e.g., healthcheck may fail because database is not yet accepting connections).

Upvotes: 3

Views: 2169

Answers (2)

Shashank V
Shashank V

Reputation: 11233

env_file option can only be used to set environment variables inside the container.

To substitute variables in compose file, there are two options -

  1. Shell environment variables - Compose can use the variable values from the shell environment in which docker-compose is run.

  2. .env file - Compose supports declaring default environment variables in an environment file named .env placed in the folder where the docker-compose command is executed. Environment variables in shell will override the values in .env file.


If none of the above options work for you, you can try the following approaches -

  1. Run a shell script inside which you refer the container environment variables as the healthcheck.

  2. Escape the variables with double dollar sign.

test: ["CMD-SHELL", "mysql -u $${DB_USER} -e \"SHOW DATABASES;\""]

Upvotes: 5

BMitch
BMitch

Reputation: 264851

docker-compose will expand environment variables in the docker-compose environment (where you ran the docker-compose command), not in the container environment. The environment variables you are passing are only set inside the container (the compose file is already parsed and variables in the compose file have been expanded by the time that environment variable file is loaded).

Inside the container, a shell is needed to expand environment variables (the $ is a shell syntax, the Linux kernel doesn't do this expansion), but you'll need to escape those variables so that docker-compose does not try to expand them first, and you need a shell. The json list syntax to running commands in docker containers runs with a direct OS exec syscall, bypassing the shell, so you need to either explicitly add a shell to the exec syntax, or just use the shell syntax. Doing the latter, with the $ values escaped as $$ results in:

test: ["CMD-SHELL", "mysql -u $${DB_USER} -e \"SHOW DATABASES;\""]

For more details see:

Upvotes: 4

Related Questions