Load environment variables from env file with Docker and PHP

12,319

Solution 1

Here're a few notes that helped me found the solution, and hope it helps someone else in the future.

First the issues I found while trying and seeing:

  • the first one that caused the error exposed above as wordpress exited with code 4 is that wp-content.php fails when mounted into the container, so either the intention is to allow the "wordpress" entrypoint sh script to modify the file for us or accept will do something else, as tried above, the plugin phpdotenv and $_ENV or getenv fn (https://www.php.net/manual/en/function.getenv.php)

  • the volume is mounted in the Docker-compose.yml file and overwrites files such as the ones we try to COPY into the container WORKDIR, etc

  • The Docker-compose context doesn't allow copying files outside its scope "The path must be inside the context of the build"

Below you'll find a working version (WIP), that worked for me, as an alternative to the default behaviour that, as stated should be honoured (I believe that refactoring, given the points mentioned above, taking into consideration all, this can be improved, but let's keep this related with passing dotenv to PHP, should be useful for someone else in the future).

++++++++++++ docker-compose.yml ++++++++++++++++

version: '3.1'

services:
  web:
    container_name: web
    image: nginx:1.15.11-alpine
    volumes:
      - ./nginx/foobar.conf:/etc/nginx/conf.d/default.conf
      - ../../foobar-blog-ui/public/:/var/www/html/
    ports:
      - 80:80
      - 443:443
    networks:
      - foobar-wordpress-network

  node:
    image: node:8.16.0-slim
    working_dir: /home/node/app
    environment:
      - NODE_ENV=development
    volumes:
      - ../../foobar-blog-ui/:/home/node/app
      - ./node_modules:/home/node/app/node_modules
      - ./npm/.npmrc:/home/node/app/.npmrc
    ports:
     - 8000:8000
     - 9000:9000
    command: bash -c "apt-get update && apt-get install -y rsync vim git libpng-dev libjpeg-dev libxi6 build-essential libgl1-mesa-glx && npm install && exit 0"
    depends_on:
      - wordpress
    networks:
      - foobar-wordpress-network

  wordpress:
    build:
      context: ../../
      dockerfile: ./.init/Docker/Services/DockerWordpress.yml
    container_name: wordpress
    restart: on-failure
    ports:
      - 8888:80
    depends_on:
      - db
    networks:
      - foobar-wordpress-network

  wordpress-cli:
    image: wordpress:cli
    volumes:
      - ../../foobar-wordpress-cms/:/var/www/html
      - ./scripts/docker-entrypoint.sh:/var/www/html/docker-entrypoint.sh
    depends_on:
      - wordpress
      - db
    command: sh -c "sleep 30 && ./docker-entrypoint.sh"
    networks:
      - foobar-wordpress-network

volumes:
  node_modules:

networks:
  foobar-wordpress-network:
      driver: bridge

++++++++++++ dockerfile ++++++++++++++++

FROM wordpress:php7.3-apache

WORKDIR /var/www/html/

COPY ./.init/Docker/.env .
COPY ./foobar-wordpress-cms .
COPY ./.init/Docker/php/uploads.ini /usr/local/etc/php/conf.d/uploads.ini
COPY ./.init/Docker/wordpress/wp-config.php ./wp-config.php

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && chmod +x /usr/bin/composer 
RUN composer require vlucas/phpdotenv
RUN ls -la

The following article also helped ( https://vsupalov.com/docker-arg-env-variable-guide/#the-dot-env-file-env ).

Solution 2

Environment Variables in Docker

Setup .env in docker-compose.yml

Environmnet File .env

WORDPRESS_DB_NAME=platform-ops-db

docker-compose.yml

version: '2'
services:
  web:
    image: nginx:1.15.11-alpine
    container_name: web
    env_file:
      - ./.env
    environment:
      MYSQL_DATABASE: ${WORDPRESS_DB_NAME}

We can use the WORDPRESS_DB_NAME throughout the application running withing the container web.

To run the Wordpress in a container behind the proxy please check with the repo conf file Wordpress as a container behind the proxy in the repo Repo

Share:
12,319
punkbit
Author by

punkbit

Code / Skate / Music / Design

Updated on June 05, 2022

Comments

  • punkbit
    punkbit almost 2 years

    How to use dotenv variables set in the Docker file, passed to a Php application?

    Recently tried to use a ".env" file with a set of key paired values to use across different configuration files, but noticed that Docker + the Wordpress image is not easy to setup. While quite trivial to set up in node, etc.

    See the ".env" file below that sits same dir as the docker-compose.yml:

    WORDPRESS_DB_NAME=wp_xxxx
    WORDPRESS_DB_USER=xxxxxx
    WORDPRESS_DB_PASSWORD=xxxxxx
    WORDPRESS_DB_HOST=xxxxxxxx
    

    The official Wordpress image available here ( https://hub.docker.com/_/wordpress ) documents that "The following environment variables are also honoured for configuring your WordPress [...] WORDPRESS_DB_USER, WORDPRESS_DB_PASSWORD, etc".

    By default the Configuration parameters in the "wp-config.php" are not replaced by the .env variables, which lead me to extend the original Wordpress image by installing composer. Let's call the file bellow "DockerWordpress.yml":

    FROM wordpress:php7.3-apache
    
    RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && chmod +x /usr/bin/composer 
    RUN composer require vlucas/phpdotenv
    

    That is used in the main Docker-compose.yml file, as we can see below. Find the service "Wordpress":

    version: '3.1'
    
    services:
      web:
        container_name: web
        image: nginx:1.15.11-alpine
        volumes:
          - ./nginx/foobar.conf:/etc/nginx/conf.d/default.conf
          - ../../foobar-blog-ui/public/:/var/www/html/
        ports:
          - 80:80
          - 443:443
        networks:
          - foobar-wordpress-network
    
      node:
        image: node:8.16.0-slim
        working_dir: /home/node/app
        environment:
          - NODE_ENV=development
        volumes:
          - ../../foobar-blog-ui/:/home/node/app
          - ./node_modules:/home/node/app/node_modules
          - ./npm/.npmrc:/home/node/app/.npmrc
        ports:
         - 8000:8000
         - 9000:9000
        command: bash -c "apt-get update && apt-get install -y rsync vim git libpng-dev libjpeg-dev libxi6 build-essential libgl1-mesa-glx && npm install && exit 0"
        depends_on:
          - wordpress
        networks:
          - foobar-wordpress-network
    
      wordpress:
        build:
          context: .
          dockerfile: ./Services/DockerWordpress.yml
        container_name: wordpress
        restart: on-failure
        ports:
          - 8888:80
        environment:
          WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST}
          WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
          WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
          WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
        volumes:
          - ../../foobar-wordpress-cms/:/var/www/html
          - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
          - ./wordpress/wp-config.php:/var/www/html/wp-config.php
        depends_on:
          - db
        networks:
          - foobar-wordpress-network
    
      wordpress-cli:
        image: wordpress:cli
        volumes:
          - ../../foobar-wordpress-cms/:/var/www/html
          - ./scripts/docker-entrypoint.sh:/var/www/html/docker-entrypoint.sh
        depends_on:
          - wordpress
          - db
        command: sh -c "sleep 30 && ./docker-entrypoint.sh"
        networks:
          - foobar-wordpress-network
    
      db:
        image: mariadb:latest
        ports:
          - 3306:3306
        restart: on-failure
        environment:
          MYSQL_DATABASE: ${WORDPRESS_DB_NAME}
          MYSQL_USER: ${WORDPRESS_DB_USER}
          MYSQL_PASSWORD: ${WORDPRESS_DB_PASSWORD}
        #   MYSQL_ROOT_HOST: ${WORDPRESS_DB_HOST}
          MYSQL_ROOT_HOST: '%'
          MYSQL_RANDOM_ROOT_PASSWORD: '1'
        volumes:
          - ./wordpress/database:/docker-entrypoint-initdb.d
          - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf"
          - ./mysql/data:/var/lib/mysql
        networks:
          - foobar-wordpress-network
        healthcheck:
            test: ["CMD", "mysqladmin", "-u${WORDPRESS_DB_USER}", "-p${WORDPRESS_DB_PASSWORD}", "ping"]
            interval: 60s
            timeout: 60s
            retries: 3
    
    volumes:
      mysql_data:
      node_modules:
    
    networks:
      foobar-wordpress-network:
          driver: bridge
    

    Finally, the "wp-config.php" file that is mounted from an external source into the container volume, as you can see in the previous "docker-compose" file. This is done by following the documentation provided by the defacto plugin to use dotEnv variables ( https://github.com/vlucas/phpdotenv ) in the Php community.

    <?php
    
    require_once(__DIR__ . './vendor/autoload.php');
    (new \Dotenv\Dotenv(__DIR__ . '/../.init/Docker'))->load();
    
    /**
     * The base configuration for WordPress
     *
     * The wp-config.php creation script uses this file during the
     * installation. You don't have to use the web site, you can
     * copy this file to "wp-config.php" and fill in the values.
     *
     * This file contains the following configurations:
     *
     * * MySQL settings
     * * Secret keys
     * * Database table prefix
     * * ABSPATH
     *
     * @link https://codex.wordpress.org/Editing_wp-config.php
     *
     * @package WordPress
     */
    
    // ** MySQL settings - You can get this info from your web host ** //
    /** The name of the database for WordPress */
    define( 'DB_NAME', '');
    
    /** MySQL database username */
    define( 'DB_USER', '');
    
    /** MySQL database password */
    define( 'DB_PASSWORD', '');
    
    /** MySQL hostname */
    define( 'DB_HOST', '');
    
    /** Database Charset to use in creating database tables. */
    define( 'DB_CHARSET', 'utf8');
    
    /** The Database Collate type. Don't change this if in doubt. */
    define( 'DB_COLLATE', '');
    
    /**#@+
     * Authentication Unique Keys and Salts.
     *
     * Change these to different unique phrases!
     * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
     * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
     *
     * @since 2.6.0
     */
    define( 'AUTH_KEY',         'U(p)0EQ$O;meL`Oe@1$t7nI?<$=|NJ)kb+Shya21)-M2HI#/B#e~:@gX+}h@[LNE' );
    define( 'SECURE_AUTH_KEY',  'Qpe;9 Ye^zuSozw@}2*f9mK~]7/V1,gf[^v4=}@ N!$<(q2qI<3U]kNK^P4b)n;7' );
    define( 'LOGGED_IN_KEY',    'R=yN?s&Ek8ncd;xuvIHU];2fo#piE[MbF6 63@aP:p1TyZmz#94(>XErht{}6<V,' );
    define( 'NONCE_KEY',        'Xr~QqP8%cjPA$] ?m*-CrcjgdfA6Vao>8C/AI6-pi_Y<rI]y=6fKSOS6i/%4F~Xl' );
    define( 'AUTH_SALT',        '<<7vysQ=uPfNxyl? z=97AyIfm~QNn5%JI7^)bFW&;A`V.5`W2xj+KXJY`_hV66T' );
    define( 'SECURE_AUTH_SALT', 'dT-4]:wh_.++<M&L6>&Eywn})wSzy+.`v6eBhl694uF(fc:yp9:?oV! PDbU(ST(' );
    define( 'LOGGED_IN_SALT',   '3rPPnmKp|dUR=KX{W-TVYH7a:60P7z}$h3jgggKJgn~9XX`)6XuCtzMLjypztu!m' );
    define( 'NONCE_SALT',       'X4aAby}iQOenS$2g7~R@,9+/-mc_lfzq!*RMP+cKOgv0K[{xS73~|k0u:zq>G.My' );
    
    /**#@-*/
    
    /**
     * WordPress Database Table prefix.
     *
     * You can have multiple installations in one database if you give each
     * a unique prefix. Only numbers, letters, and underscores please!
     */
    $table_prefix = 'wp_';
    
    /**
     * For developers: WordPress debugging mode.
     *
     * Change this to true to enable the display of notices during development.
     * It is strongly recommended that plugin and theme developers use WP_DEBUG
     * in their development environments.
     *
     * For information on other constants that can be used for debugging,
     * visit the Codex.
     *
     * @link https://codex.wordpress.org/Debugging_in_WordPress
     */
    // define( 'WP_DEBUG', true );
    // define( 'WP_DEBUG_LOG', true );
    
    /* That's all, stop editing! Happy publishing. */
    
    /** Absolute path to the WordPress directory. */
    if ( ! defined( 'ABSPATH' ) ) {
        define( 'ABSPATH', dirname( __FILE__ ) . '/' );
    }
    
    /** Sets up WordPress vars and included files. */
    require_once( ABSPATH . 'wp-settings.php' );
    

    Since I'm using composer and the phpdotnet plugin, I've also tried:

    define( 'DB_NAME', getenv('WORDPRESS_DB_NAME'));
    ...
    

    In the error log, I can read:

    wordpress exited with code 4
    

    The error above code 4 is caused by providing "environment variables", that causes the entrypoint script to try to modify the wp-config.php for us.

    Since the code 4 is caused by the environment variables, with or without the inspect docker image returns the following (does not have env variables):

    [
        {
            "Id": "sha256:0d91452f5f88a168d9e85e2c4992460e2ef50d66d60c581c3ffc60b78824a416",
            "RepoTags": [
                "docker_wordpress:latest"
            ],
            "RepoDigests": [],
            "Parent": "sha256:73c390be73f955ac64e67751faba8095ed0d31a98a3eb841ea38be6a81d9bd02",
            "Comment": "",
            "Created": "2019-09-09T22:54:10.8766881Z",
            "Container": "20a95e0640aa65d9c1c244cdacf0dae09165c4da3ff19460190dce4cf4a80d8b",
            "ContainerConfig": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "80/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "PHPIZE_DEPS=autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c",
                    "PHP_INI_DIR=/usr/local/etc/php",
                    "APACHE_CONFDIR=/etc/apache2",
                    "APACHE_ENVVARS=/etc/apache2/envvars",
                    "PHP_EXTRA_BUILD_DEPS=apache2-dev",
                    "PHP_EXTRA_CONFIGURE_ARGS=--with-apxs2 --disable-cgi",
                    "PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2",
                    "PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2",
                    "PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie",
                    "GPG_KEYS=CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D",
                    "PHP_VERSION=7.3.9",
                    "PHP_URL=https://www.php.net/get/php-7.3.9.tar.xz/from/this/mirror",
                    "PHP_ASC_URL=https://www.php.net/get/php-7.3.9.tar.xz.asc/from/this/mirror",
                    "PHP_SHA256=4007f24a39822bef2805b75c625551d30be9eeed329d52eb0838fa5c1b91c1fd",
                    "PHP_MD5=",
                    "WORDPRESS_VERSION=5.2.3",
                    "WORDPRESS_SHA1=5efd37148788f3b14b295b2a9bf48a1a467aa303"
                ],
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "composer require vlucas/phpdotenv"
                ],
                "Image": "sha256:73c390be73f955ac64e67751faba8095ed0d31a98a3eb841ea38be6a81d9bd02",
                "Volumes": {
                    "/var/www/html": {}
                },
                "WorkingDir": "/var/www/html",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": null,
                "StopSignal": "WINCH"
            },
            "DockerVersion": "19.03.2",
            "Author": "",
            "Config": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "80/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "PHPIZE_DEPS=autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c",
                    "PHP_INI_DIR=/usr/local/etc/php",
                    "APACHE_CONFDIR=/etc/apache2",
                    "APACHE_ENVVARS=/etc/apache2/envvars",
                    "PHP_EXTRA_BUILD_DEPS=apache2-dev",
                    "PHP_EXTRA_CONFIGURE_ARGS=--with-apxs2 --disable-cgi",
                    "PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2",
                    "PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2",
                    "PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie",
                    "GPG_KEYS=CBAF69F173A0FEA4B537F470D66C9593118BCCB6 F38252826ACD957EF380D39F2F7956BC5DA04B5D",
                    "PHP_VERSION=7.3.9",
                    "PHP_URL=https://www.php.net/get/php-7.3.9.tar.xz/from/this/mirror",
                    "PHP_ASC_URL=https://www.php.net/get/php-7.3.9.tar.xz.asc/from/this/mirror",
                    "PHP_SHA256=4007f24a39822bef2805b75c625551d30be9eeed329d52eb0838fa5c1b91c1fd",
                    "PHP_MD5=",
                    "WORDPRESS_VERSION=5.2.3",
                    "WORDPRESS_SHA1=5efd37148788f3b14b295b2a9bf48a1a467aa303"
                ],
                "Cmd": [
                    "apache2-foreground"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:73c390be73f955ac64e67751faba8095ed0d31a98a3eb841ea38be6a81d9bd02",
                "Volumes": {
                    "/var/www/html": {}
                },
                "WorkingDir": "/var/www/html",
                "Entrypoint": [
                    "docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": null,
                "StopSignal": "WINCH"
            },
            "Architecture": "amd64",
            "Os": "linux",
            "Size": 530754564,
            "VirtualSize": 530754564,
            "GraphDriver": {
                "Data": {
                    ...
                },
                "Name": "overlay2"
            },
            "RootFS": {
                "Type": "layers",
                "Layers": [
                    ...
                ]
            },
            "Metadata": {
                "LastTagTime": "2019-09-09T22:54:10.9465719Z"
            }
        }
    ]
    

    Have in mind that I expect that the documentation is correct and that the setup above, that the environment variables should be honoured.

  • thicolares
    thicolares about 3 years
    Important: so far, it only works if both .env and docker-compose.yml are in the same folder.