13

Background

I'm trying to use Wercker to run my test for a PHP application. Wercker uses Docker containers to setup a test environment to execute tests in. It uses Environment Variables to expose the connection params for any connected services like MySQL and Elasticsearch. Example MYSQL_PORT_3306_TCP_ADDR = 127.0.1.1

My core Docker containers is running Ubuntu 14.04 with PHP and Apache already installed on the container.

Problem

I can't seem to access the Environment Variables via php $_SERVER or $_ENV when running via Apache. It works fine if I run the script via CLI php ./db_connect.php or if I run PHP using its build in server php -S localhost:8000. However If I try and access a page via the Apache virtual host, the Environment Variables are not available.

Progress

I have setup Apache with the mod used to allow environmental variables "I think"

sudo a2enmod env
sudo service apache2 restart

I'm trying to access the Environment Variables in my script.

$database_host      = $_SERVER["MYSQL_PORT_3306_TCP_ADDR"];
$database_username  = $_SERVER["MYSQL_ENV_MYSQL_USER"];
$database_password  = $_SERVER["MYSQL_ENV_MYSQL_PASSWORD"];
$database_name      = $_SERVER["MYSQL_ENV_MYSQL_DATABASE"];
$elasticsearch_host = $_SERVER["ELASTICSEARCH_PORT_9300_TCP_ADDR"];

I can add new variables in my .htaccess, I just don't get all the system environmental variables.

SetEnv TEST_VAR test

I have read this question How to get system environment variables into PHP while running CLI & Apache2Handler? but i'm not sure what its suggesting to do.

Question

How do I expose System Environment Variables to Apache and PHP?

2
  • Have you tried $_ENV['MYSQL_PORT_3306_TCP_ADDR'] ? Note that the environment variables for links are deprecated, and no longer set for the new custom networks in docker 1.9 and above. A better way is to connect using the name of the container that's linked, e.g. http://mysql to connect to the "mysql" container. The environment variables didn't add much, because you need both the name and the port number to obtain the ip-address, so using the name of the container is easier anyway.
    – thaJeztah
    Commented Mar 12, 2016 at 16:04
  • Yes, have tried to access the environment variables from $_ENV and $HTTP_ENV_VARS just to be sure. The container link solution may work, the only problem is that the container exposes additional information like the database table it creates on setup $_SERVER["MYSQL_ENV_MYSQL_DATABASE"] and the random root password $_SERVER['MYSQL_ENV_MYSQL_ROOT_PASSWORD'] that I also need.
    – Levi Putna
    Commented Mar 13, 2016 at 0:27

5 Answers 5

12

If you are using php official Docker image you have to explicitly pass environment variables from Apache to PHP. You can do something like this:

In your Dockerfile:

FROM php:7.2-apache
RUN echo 'SetEnv MYSQL_USER ${MYSQL_USER}' > /etc/apache2/conf-enabled/environment.conf

environment.conf is an arbitrary name, but it should be placed in /etc/apache2/conf-enabled/.

In docker-compose.yml:

version: '2'
services:
    yourservice:
        build: ./yourimage
        image: yourimage
        ports:
            - 8080:80
        volumes:
            - ../html:/var/www/html
        environment:
            MYSQL_USER: foo

In your PHP script:

echo getenv('MYSQL_USER');
5
  • 3
    Best answer. No need to mess with config files any more than necessary. Very simple solution, while keeping all control in the Dockerfile/docker-compose.
    – Keugels
    Commented Jul 30, 2020 at 6:24
  • Works like a charm. This is definitely the way to go!
    – Yevgen
    Commented Jun 3, 2021 at 9:08
  • Nice solution! One recommendation would be to use >> instead of > in order not to loose previous contents of the environment.conf file, if any.
    – Cristik
    Commented Dec 28, 2021 at 6:18
  • Interestingly, when I set the SetEnv variable value in a file within the conf.d/ folder so as to make it available to all of the server, getenv('variable') returns false. But, $_SERVER['variable'] returns value. If I set it in the Apache VirtualHost section, getenv('variable) returns value. I am on a Cent OS 7 with PHP 7.2 and Apache 2.4. Not sure if others ran into something similar.
    – Kalyan
    Commented Sep 7, 2022 at 15:39
  • Note this works because '${MYSQL_USER}' is evaluated at runtime, not build time. For build time passing of variables, compose yaml file uses build: ... args: XY
    – Jiří
    Commented Mar 25, 2023 at 11:32
7

Here is the solution:

Docker will pass these to apache but you have to configure apache to make them available to PHP.

Setup the values in your local .env file

MYSQL_PORT_3306_TCP_ADDR=1234
MYSQL_ENV_MYSQL_USER=development
MYSQL_ENV_MYSQL_PASSWORD=password    

Then add these as environment params in the docker-compose.yml file

version: 2
services:
  web:
  build: php:5.6-apache
  environment:
    MYSQL_PORT_3306_TCP_ADDR:${MYSQL_PORT_3306_TCP_ADDR}
    MYSQL_ENV_MYSQL_USER: ${MYSQL_ENV_MYSQL_USER}
    MYSQL_ENV_MYSQL_PASSWORD: ${MYSQL_ENV_MYSQL_PASSWORD}

Then to pass these to PHP set these as environment params in your Virtual Host config

<VirtualHost *:80>
    ServerName some-project

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/some-project

    # Set apache environment variables
    SetEnv MYSQL_PORT_3306_TCP_ADDR ${MYSQL_PORT_3306_TCP_ADDR}
    SetEnv MYSQL_ENV_MYSQL_USER ${MYSQL_ENV_MYSQL_USER}
    SetEnv MYSQL_ENV_MYSQL_PASSWORD ${MYSQL_ENV_MYSQL_PASSWORD}
</VirtualHost>

These will now be available to access in PHP via the $_SERVER super global array.

<?php
    echo $_SERVER['MYSQL_ENV_MYSQL_USER'];
2

if you're using php-fpm, you can pass env vars from OS to PHP-FPM through clear_env ini setting in a file like /path/to/php/fpm/pool.d/www.conf:

clear_env = no

it works with environment vars set via docker-compose.yml as below:

version: "..."

services:
    php-fpm:
        image: php:7-fpm
        environment:
            MY_VAR: my-value

IMPORTANT: Of course, the risk is that your PHP-FPM will get access to all OS env vars. If passing all vars is a problem, you can also pass only specific vars via www.conf or another php ini config file:

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
env[MY_VAR] = $MY_VAR
1

With docker-compose you can retrieve the operating system's environment variables set with the environment option of the docker-compose.yml file through php's $_ENV variable.

version: 2
services:
  web:
    build: php:5.6-apache
    environment:
      MYSQL_USER: "user"
      MYSQL_PASSWORD: "passwd"

should give you

$_ENV['MYSQL_USER'] = user
$_ENV['MYSQL_PASSWORD'] = passwd

I'm not sure how Wercker maps environment variables to the containers, but there's this open issue that I think might help https://github.com/wercker/wercker/issues/63

2
  • 2
    Indeed that is what should work, but based on what I've experienced, and the question, it seems that "docker + apache + php" doesn't necessarily pass those environment variables through to php. IDK under what circumstances this is a problem, but I have seen this in an environment that didn't include wercker - so it is something about apache settings, or how docker passes the variables to apache. Commented Mar 30, 2019 at 19:04
  • Setting environment only in docker-compose.yml is not sufficient to pass variables to PHP. The variables listed in environment will be available in Apache config files, in the form ${MYSQL_USER}, but you'll also have to use SetEnv directive in Apache config to pass the variables down to PHP. See my answer for a complete example. Commented Jul 30, 2020 at 9:51
-3

you can check get env with php command like below

php -r "echo getenv('MYSQL_USER');"
1
  • Note that this invokes the PHP CLI, not the Apache process. The poster is not having problems accessing variables when invoking the CLI.
    – Ethan
    Commented Jan 24, 2023 at 19:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.