1

I'm setting up the development environment for my application inside Docker containers, at the moment I have these containers:

myapp-data       - Holds application source code and log files
myapp-phpfpm     - Runs the php5-fpm process for Nginx
myapp-nginx      - Runs the Nginx web server that serves the application

This setup works beautifully, I'm really happy with it. But my application needs a MySQL database to connect to, so I'm using the official MySQL image, and running it like so:

sudo docker run --name myapp-mysql -e "MYSQL_ROOT_PASSWORD=iamroot" -e "MYSQL_USER=redacted" -e "MYSQL_PASSWORD=redacted" -e "MYSQL_DATABASE=redacted" -d mysql

This also works great. But my myapp-phpfpm container needs to be linked to the myapp-mysql container in order to expose MySQL's connection details to my application. So I restart my myapp-phpfpm container:

sudo docker run --privileged=true --name myapp-phpfpm --volumes-from myapp-data --link myapp-mysql:mysql -d readr/phpfpm

So now my myapp-phpfpm container is linked to my myapp-mysql container so I should be able to access the database within my PHP application.

The problem is I can't. The environment variables don't exist inside the PHP application. If I do:

die(var_dump(`printenv`));

I don't get the MySQL environment variables. To try to debug I did a whoami to find out what user PHP is running as, which is www-data. I then created a bash process inside the container, used su www-data to become the www-data user and did printenv there. Sure enough, the MySQL environment variables do exist there:

MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP=tcp://172.17.1.118:3306
MYSQL_ENV_MYSQL_ROOT_PASSWORD=iamroot
... etc ...

So, how can I access the environment variables that Docker exposes about my myapp-mysql container within PHP?

John Dorean
  • 3,744
  • 9
  • 51
  • 82
  • can you post the `ENV` part of your various Dockerfiles ? – user2915097 Feb 05 '15 at 15:01
  • Why should the environment variables exist inside the myapp-phpfpm container? – Behe Feb 05 '15 at 16:54
  • @user2915097 There are no `ENV` declarations inside any of my Dockerfiles. @Behe Because the `myapp-phpfpm` container is linked to the `myapp-mysql` container. – John Dorean Feb 05 '15 at 18:20
  • I believe it's the way you connect to MySQL. Docker by default does not automatically set the connection between your containers just by linking. Link will only set the environment variables for you on the application container. To do so, you have to configure your phpfpm to get the values. Do your application contains any JDBC connector or such to get the MySQL connection? – Hans Feb 06 '15 at 02:27

4 Answers4

1

I solved this by creating a custom start.sh script that then gets called from my Dockerfile:

#!/bin/sh

# Function to update the fpm configuration to make the service environment variables available
function setEnvironmentVariable() {
    if [ -z "$2" ]; then
            echo "Environment variable '$1' not set."
            return
    fi

    # Check whether variable already exists
    if grep -q $1 /etc/php5/fpm/pool.d/www.conf; then
        # Reset variable
        sed -i "s/^env\[$1.*/env[$1] = $2/g" /etc/php5/fpm/pool.d/www.conf
    else
        # Add variable
        echo "env[$1] = $2" >> /etc/php5/fpm/pool.d/www.conf
    fi
}

# Grep for variables that look like MySQL (MYSQL)
for _curVar in `env | grep MYSQL | awk -F = '{print $1}'`;do
    # awk has split them by the equals sign
    # Pass the name and value to our function
    setEnvironmentVariable ${_curVar} ${!_curVar}
done

# start php-fpm
exec /usr/sbin/php5-fpm

This then adds the environment variables to the PHP5-FPM config so they can be accessed from within PHP scripts.

John Dorean
  • 3,744
  • 9
  • 51
  • 82
  • For me, the problem was that I did not set clear_env = no in the pool configuration; it defaults to Yes - so all env variables are cleared. Using the standard image php:5.6-fpm from Docker Hub. See https://php.net/manual/ro/install.fpm.configuration.php – VladFr Mar 02 '15 at 11:21
1

php-fpm by default clears all environment variables, /etc/php5/fpm/pool.d/www.conf:

; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no

you can fix this by uncommenting in your Dockerfile:

RUN sed -i -e "s/;clear_env\s*=\s*no/clear_env = no/g" /etc/php5/fpm/pool.d/www.conf
Tombart
  • 30,520
  • 16
  • 123
  • 136
0

I'd recommend using something like fig and just passing the env vars to both containers at startup. If you really want to you could docker inspect any container from any other container if you bind-mount the docker socket, then do something like this:

docker inspect -f {{.Config.Env}} myapp-mysql
Abdullah Jibaly
  • 53,220
  • 42
  • 124
  • 197
0

The problem may not be the environment variables - it may be your PHP installation.

TL;DR environment variables that are accessible when you're running your application under Apache & PHP may not be available if you're using nginx or lighttpd and fastcgi.

The longer version

Here's the way I understand it (and it's probably wrong or incomplete because my experience with this is quite limited). Because PHP is not running as part of the browser under nginx with fastCGI, it does not have access to the shell in which the browser was started and therefore does not have access to the environment variables in that shell.

The solution is to declare the variables you're interested in as part of the configuration. This answer is kind of terse, but it contains the basic answer to this problem.

Community
  • 1
  • 1
Kryten
  • 15,230
  • 6
  • 45
  • 68