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?

Community
  • 1
  • 1
Levi Putna
  • 2,863
  • 6
  • 30
  • 47
  • 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 Mar 12 '16 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 Mar 13 '16 at 00:27

5 Answers5

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');
Augusto Destrero
  • 4,095
  • 1
  • 23
  • 25
  • 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 Jul 30 '20 at 06:24
  • Works like a charm. This is definitely the way to go! – Yevgen Jun 03 '21 at 09: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 Dec 28 '21 at 06: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 Sep 07 '22 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ří Mar 25 '23 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'];
Matthew Fedak
  • 772
  • 9
  • 16
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
0

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
    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. – ToolmakerSteve Mar 30 '19 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. – Augusto Destrero Jul 30 '20 at 09:51
-2

you can check get env with php command like below

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