PHP: PHP-FPM ignores environment variables – solutions

By | 02/19/2020
 

We have a PHP-based application running in Kubernetes and uses settings from a /app/.env file plus environment variables.

The problem is that application running in a Docker container can’t see an $TEST_VAR variable although it’s present in the Deployment:

...
      containers:
      - name: application-dev-web
        image: bttrm-application:119
...
        - name: TEST_VAR
          valueFrom:
            secretKeyRef:
              name: bttrm-app-secret
              key: test_var
...

And its value is set via Kubernetes Secrets:

apiVersion: v1
kind: Secret
metadata:
  name: bttrm-app-secret
  namespace: application-dev-ns
type: Opaque
data:
  test_var: dGVzdF92YWwK

In a pod, this variable also accessible and can be found with the env command:

kubectl -n application-dev-ns exec -ti application-dev-deploy-54c7666b99-frntf -c application-dev-web env | grep DB_
DB_PASSWORD=password

Still, if create a php-file with the  phpinfo() function – in the resulted Environment block we will see only two variables – $USER and $HOME:

kubectl -n application-dev-ns exec -ti application-dev-deploy-66896585fc-622nh curl localhost:8080/info.php | grep -A 5 Environment
<h2>Environment</h2>
<table>
<tr class="h"><th>Variable</th><th>Value</th></tr>
<tr><td class="e">USER </td><td class="v">nobody </td></tr>
<tr><td class="e">HOME </td><td class="v">/ </td></tr>
</table>

Solution #1: env[TEST_VAR]

The first solution can be to add an explicit variable export:

...
env[TEST_VAR] = $TEST_VAR

Deploy and check:

kubectl -n application-dev-ns exec -ti application-dev-deploy-8458fb96bb-6x4xk curl localhost:8080/info.php | grep -A 6 Environment
<h2>Environment</h2>
<table>
<tr class="h"><th>Variable</th><th>Value</th></tr>
<tr><td class="e">TEST_VAR </td><td class="v">test_val
</td></tr>
<tr><td class="e">USER </td><td class="v">nobody </td></tr>
<tr><td class="e">HOME </td><td class="v">/ </td></tr>

Okay, it’s working but you’ll have to add such a string for each variable used.

Solution #2: clear_env = no

Another solution can be by setting the clear_env PHP-FPM’s parameter no.

Update the /etc/php7/php-fpm.d/www.conf file and add the following:

...
    ;env[DB_PASSWORD] = $DB_PASSWORD
    clear_env = no

Deploy. check:

kubectl -n application-dev-ns exec -ti application-dev-deploy-c56fd488b-ld4hk curl localhost:8080/info.php | grep -A 6 Environment
<h2>Environment</h2>
<table>
<tr class="h"><th>Variable</th><th>Value</th></tr>
<tr><td class="e">KUBERNETES_PORT_443_TCP </td><td class="v">tcp://172.20.0.1:443 </td></tr>
<tr><td class="e">APPLICATION_DEV_SERVICE_PORT_80_TCP </td><td class="v">tcp://172.20.57.152:80 </td></tr>
<tr><td class="e">APPLICATION_DEV_SERVICE_SERVICE_PORT </td><td class="v">80 </td></tr>
<tr><td class="e">SUPERVISOR_GROUP_NAME </td><td class="v">php-fpm </td></tr>

Now we can access all the environment variables.

Готово.

(not)Solution #3: variables_order in the php.ini

PHP also has a parameter which defines an order of the variables sources, see the documentation:

variables_order string

Sets the order of the EGPCS (Environment, Get, Post, Cookie, and Server) variable parsing. For example, if variables_order is set to “SP” then PHP will create the superglobals $_SERVER and $_POST, but not create $_ENV$_GET, and $_COOKIE. Setting to “” means no superglobals will be set.

Check the current value:

bash-5.0$ cat /etc/php7/php.ini | grep variables_order
; variables_order
variables_order = "GPCS"

The suggestion was that the issue can be fixed by adding the E (Environment) – but setting variables_order = "EGPCS" didn’t help.