Wordpress: Environment variables no longer work in Docker Compose

Created on 11 Mar 2021  路  19Comments  路  Source: docker-library/wordpress

After pulling the latest WordPress Docker image today I end up with a default wp-config.php, resulting in 'Error establishing a database connection' when trying to open my WordPress website.

My wp-config.php doesn't contain the values I specify via environment variables in my docker-compose.yml, which are:

  • WORDPRESS_DB_HOST
  • WORDPRESS_DB_NAME_FILE
  • WORDPRESS_DB_USER_FILE
  • WORDPRESS_DB_PASSWORD_FILE
  • WORDPRESS_CONFIG_EXTRA

My logs show this line:
No 'wp-config.php' found in /var/www/html, but 'WORDPRESS_...' variables supplied; copying 'wp-config-docker.php' (WORDPRESS_CONFIG_EXTRA WORDPRESS_DB_HOST WORDPRESS_DB_NAME_FILE WORDPRESS_DB_PASSWORD_FILE WORDPRESS_DB_USER_FILE)

This seems related to the recent merge of Move "wp-config-docker.php" to non-beta (5.7 GA) #572. As per this comment, I entered my Docker container and removed wp-config.php and restarted the container. A new wp-config.php is generated (giving the same message in my logs as shown above), but this is the same as the previous one and doesn't contain the values from my environment variables.

I guess the new issues #573 and #574 are related.

I pull new WordPress docker images on a daily bases, and this problem hasn't occurred before. So I guess it is not caused on my end.

Most helpful comment

Perhaps you can provide a more specific (minimal) example so we can try to reproduce the issue? pray

@tianon thanks for your reply! I'm able to reproduce the problem with the following minimal docker-compose.yml example:

version: '3.1'
services:
  app:
    image: wordpress:5.6.0-php7.4   
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_NAME: test
      WORDPRESS_DB_USER: test
      WORDPRESS_DB_PASSWORD: test     
    networks:
      - network                
  mysql:
    image: mysql:8.0
    environment:
      - "MYSQL_DATABASE=test"  
      - "MYSQL_USER=test"
      - "MYSQL_PASSWORD=test"
      - "MYSQL_RANDOM_ROOT_PASSWORD=yes"
    networks:
      - network
networks:
  network:

Everything works fine when you run docker-compose up -d with the file above. The problem arises when you change the WordPress image to wordpress:5.7.0-php7.4 (run docker-compose down and then docker-compose up -d again).

To be more specific, when I use the wordpress:5.6.0-php7.4 image I end up with a wp-config.php that contains the correct database information:

/** The name of the database for WordPress */
define( 'DB_NAME', 'test');

/** MySQL database username */
define( 'DB_USER', 'test');

/** MySQL database password */
define( 'DB_PASSWORD', 'test');

But when I use the wordpress:5.7.0-php7.4 image I end up with the following which results in a 'Error establishing a database connection' when I try to open WordPress in my browser:

/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'database_name_here') );

/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'username_here') );

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'password_here') );

All 19 comments

Perhaps you can provide a more specific (minimal) example so we can try to reproduce the issue? :pray:

If this is in a CI environment, the likely cause is that the WordPress container will no longer wait for MySQL to be "up" / ready before it starts the web server.

Had the same problem. My docker-compose.yml looked like this before, working fine. Which allowed for empty password and a root user.

version: '3'

services:
  database:
    image: mariadb
    ports:
      - 8079:3306
    volumes:
      - ./database:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"

  wordpress:
    depends_on:
      - database
    image: wordpress:latest
    volumes:
      - ./site/web/app:/var/www/html/wp-content
    ports:
      - 8080:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: database:3306
      WORDPRESS_TABLE_PREFIX: pewp_
      WORDPRESS_DEBUG: 1

But with the new get_env lines:

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'password_here') );

...empty passwords don't work anymore because Wordpress tries to login with 'password_here'.

Would it be a good idea to change to the following to allow for default login? It then wouldn't be necessary to set the user and password in the docker-compose.yml file, which keeps development configuration nice and simple.

/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'root') );

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', '') );

(By the way if you have a running project with a local mysql or mariadb volume which you don't want to destroy, just docker exec it <container id> bash into the container and create a new user with a password, and filling that in docker-compose.yml)

See https://github.com/docker-library/wordpress/pull/577: we're not likely to bring back the previous insecure default, but we do want to make sure explicitly specifying an empty password works (which I think doesn't right now; I haven't verified that).

As another workaround, you can safely modify your copied wp-config.php (we now only create it initially, we don't update it directly anymore).

That being said, I would strongly recommend creating and using a non-root user with minimal privileges for running WordPress.

Perhaps you can provide a more specific (minimal) example so we can try to reproduce the issue? pray

@tianon thanks for your reply! I'm able to reproduce the problem with the following minimal docker-compose.yml example:

version: '3.1'
services:
  app:
    image: wordpress:5.6.0-php7.4   
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_NAME: test
      WORDPRESS_DB_USER: test
      WORDPRESS_DB_PASSWORD: test     
    networks:
      - network                
  mysql:
    image: mysql:8.0
    environment:
      - "MYSQL_DATABASE=test"  
      - "MYSQL_USER=test"
      - "MYSQL_PASSWORD=test"
      - "MYSQL_RANDOM_ROOT_PASSWORD=yes"
    networks:
      - network
networks:
  network:

Everything works fine when you run docker-compose up -d with the file above. The problem arises when you change the WordPress image to wordpress:5.7.0-php7.4 (run docker-compose down and then docker-compose up -d again).

To be more specific, when I use the wordpress:5.6.0-php7.4 image I end up with a wp-config.php that contains the correct database information:

/** The name of the database for WordPress */
define( 'DB_NAME', 'test');

/** MySQL database username */
define( 'DB_USER', 'test');

/** MySQL database password */
define( 'DB_PASSWORD', 'test');

But when I use the wordpress:5.7.0-php7.4 image I end up with the following which results in a 'Error establishing a database connection' when I try to open WordPress in my browser:

/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'database_name_here') );

/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'username_here') );

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'password_here') );

@tianon 馃憢

I have a similar configuration to @siccovansas.

Dockerfile

FROM wordpress:5.7.0-php7.4-apache

SHELL ["/bin/bash", "-c"]

RUN apt-get update && \
  apt-get install vim -y

docker-compose.yml

version: '3.6'
services:

  app:
    container_name: wordpress
    build: .
    ports:
      - 1000:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: root
      WORDPRESS_DB_PASSWORD: 123
    volumes:
      - ./<plugin>:/var/www/html/wp-content/plugins/<plugin>
    restart: always

  mysql:
    container_name: mariadb
    image: mariadb:10.4.11-bionic
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} # These values are coming from a .env file
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
    depends_on:
      - app
    restart: always

  phpmyadmin:
    container_name: phpmyadmin
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - 1080:80
    depends_on:
      - app
      - mysql
    environment:
      PMA_HOST: mysql
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}

Here's what's set in the container's wp-config.php:

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'database_name_here') );

/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'username_here') );

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'password_here') );

/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );

鈽濓笍

If I use the tag: wordpress:5.6.*-php7.2-apache, everything works, but as soon as I switch to anything 5.7.*, the environment variables don't copy over.

But when I use the wordpress:5.7.0-php7.4 image I end up with the following which results in a 'Error establishing a database connection' when I try to open WordPress in my browser

How long did you want for MySQL to start? With the new changes, the wordpress container will be available almost immediately so the database may not be ready yet.


Here's what's set in the container's wp-config.php:

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'database_name_here') );

/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'username_here') );

/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', 'password_here') );

/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );

That is exactly how it should currently look. Part of the change is that the environment values are no longer embedded into wp-config.php, but instead they are pulled from the environment (getenv_docker).


Allowing empty passwords again is in #577.

You are right @yosifkit! I didn't wait long enough with the 'failing' example I gave for the database to be ready. So ignore all that :)

The problem seems to be that I'm using Docker Secrets (as mentioned on https://hub.docker.com/_/wordpress/). E.g., in my docker-compose.yml I use WORDPRESS_DB_NAME_FILE instead of WORDPRESS_DB_NAME. But wp_config.php ends up with define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'database_name_here') ); which doesn't take into account that it should get the value from WORDPRESS_DB_NAME_FILE.

You can recreate the problem using this docker-compose.yml

version: '3.1'
services:
  app:
    image: wordpress:5.7.0-php7.4
    secrets:
      - db_name
      - db_user
      - db_password
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_NAME_FILE: /run/secrets/db_name
      WORDPRESS_DB_USER_FILE: /run/secrets/db_user
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
    networks:
      - network
  mysql:
    image: mysql:8.0
    secrets:
      - db_name
      - db_user
      - db_password
    environment:
      - "MYSQL_DATABASE_FILE=/run/secrets/db_name"
      - "MYSQL_USER_FILE=/run/secrets/db_user"
      - "MYSQL_PASSWORD_FILE=/run/secrets/db_password"
      - "MYSQL_RANDOM_ROOT_PASSWORD=yes"
    networks:
      - network
secrets:
  db_name:
    file: ./secrets_db_name.txt
  db_user:
    file: ./secrets_db_user.txt
  db_password:
    file: ./secrets_db_password.txt
networks:
  network:

Create the secrets_db_name.txt, secrets_db_user.txt, and secrets_db_password.txt files, each containing one line with a value (which e.g., could all be test)

getenv_docker definitely uses _FILE variables before falling back to the non-_FILE variable (as the image has in the past via the entrypoint script).

https://github.com/docker-library/wordpress/blob/fb920c697693bad49582c3a0c8bf1fa0e7642d2b/wp-config-docker.php#L27-L31

But it seems like there is a bug if the secret files have new lines. Using the compose file in the comment just above and adding WORDPRESS_DEBUG I was able to see the possible issue:

Warning: mysqli_real_connect(): (HY000/1045): Access denied for user 'test
'@'172.18.0.3' (using password: YES) in /var/www/html/wp-includes/wp-db.php on line 1653

My three secret files were just created with echo test > secrets_db_password.txt and so they included a new line in them (which we need to allow and trim as the shell script did). A workaround until a fix is added is to ensure the secret files don't have a newline: echo -n test > secrets_db_password.txt

Added fix for newlines in _FILE contents to #577

Removing the newlines from the secret files indeed fixes my problem! Thanks for troubleshooting and adding a fix! Case closed I guess :)

How long did you want for MySQL to start? With the new changes, the wordpress container will be available almost immediately so the database may not be ready yet.

@yosifkit I waited for quite a bit, here's a quick video demo. It says mysqld ready for connections... but I still get the WordPress Database Error screen.

https://user-images.githubusercontent.com/2741371/111238429-79039580-85cd-11eb-9a3d-39201b2a3b34.mov

@yosifkit I also noticed that there's no tables in my database 馃

image

@kunalnagar I guess you have another issue, but it looks like you're missing WORDPRESS_DB_NAME: custom404pro in your docker-compose.yml

@siccovansas I think so too. But I've tried adding WORDPRESS_DB_NAME and it still doesn't work for me. Maybe it's the mariadb image that I'm using. I'll try switching around to different mysql images and see what happens.

Could you possibly post your docker-compose.yml file here for reference redacting all secrets of course?

@yosifkit @siccovansas I left it running for about 15 mins or so and it worked! 馃帀

Same problem here https://github.com/docker-library/wordpress/issues/578?_pjax=%23js-repo-pjax-container#issuecomment-799965165 but without any new lines or line breaks in secrets

Do note that there is no need to use this mechanism to create the root superuser, that user gets created by default with the password specified by the MYSQL_ROOT_PASSWORD variable.

https://github.com/docker-library/docs/tree/2b1bfbc81bab0f10d024aa2fd7ac4c999487e6ac/mysql#mysql_user-mysql_password

Do not put root as the value of MYSQL_USER. It will likely fail to finish database initialization.

Was this page helpful?
0 / 5 - 0 ratings