Short answer :
- Be mindful about the distinction between your host environment variables and your container environment variables, and how to set them
- Symfony (as many others) have a process to handle environment variable definition: whether it is defined as an environment variable on your host machine / container, or in a .env file, or as a secret, etc...)
Why this article ?
Handling environment variables, between host machine, .env file(s), and container, is not always easy. Is my variable used when building the Dockerfile? When using docker compose? Is it passed to my container? Can it be used by my app ?This article will address this question usingFrankenPHP for building a Symfony app.
I will focus on the
APP_ENV
environment variable and its actual value, depending on some cases.
Passing the environment variables
When using Symfony Docker image, some environment variables are defined to be used inside the container. Namely:For starter, let's focus on the second one: it has the advantage to define an environment variable calledservices:
php:
[...]environment:
SERVER_NAME:
${SERVER_NAME:-localhost}, php:80MERCURE_PUBLISHER_JWT_KEY:
${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}MERCURE_SUBSCRIBER_JWT_KEY:
${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}DATABASE_URL:
postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}MERCURE_URL:
${CADDY_MERCURE_URL:-http://php/.well-known/mercure}MERCURE_PUBLIC_URL:
${CADDY_MERCURE_PUBLIC_URL:-https://${SERVER_NAME:-localhost}:${HTTPS_PORT:-443}/.well-known/mercure}MERCURE_JWT_SECRET:
${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}SYMFONY_VERSION:
${SYMFONY_VERSION:-}STABILITY:
${STABILITY:-stable}
MERCURE_PUBLISHER_JWT_KEY
based on the definition of another environment variable
called CADDY_MERCURE_JWT_SECRET
, so there will be less confusion in the explantation. I think.
MERCURE_PUBLISHER_JWT_KEY
will be an environment variable
available in the container.
Its value will either be the value of the CADDY_MERCURE_JWT_SECRET
environment variable
on the host machine, or the string default value !ChangeThisMercureHubJWTSecretKey!
.
Now, how do you set the
CADDY_MERCURE_JWT_SECRET
variable value? Here's some options:
- The environment variable exists on your host machine: it can be used
- A more flexible option is to use a
.env
file, which is read by the docker tool when building the image, and in which you will set the environment value to the value you need. You can also put the value in another file, then you will need to build the image withdocker compose --env-file <my_file> build
- Alternatively, you can define the variable value in the start of your docker command,
for example
CADDY_MERCURE_JWT_SECRET=MySecret docker compose build
Deploying an app in dev environment
Creating an app in a dev environment is quite simple... and well explained here : https://github.com/dunglas/symfony-docker/tree/main.When you check the various files and containers, you'll see that the
APP_ENV
variable has
a default dev
value in the frankenphp_dev
image.
Which means, any container using this image, will have APP_ENV=dev
as its core.
Cool, that's what I wanted anyway.
Deploying an app in test environment
To create the same app as before, but for the purpose of testing, we could assume that it works just as dev. Then, inside your container, you performbin/console dump-env:test
, and you're good.
Well, spoiler : no.
Let's connect to that container, to see what's going on.
OK, so, by default / by design,$ git clone https://github.com/dunglas/symfony-docker.git .
Clonage dans '.'... [...]$ docker compose build
[...] ✔ Service php Built$ docker compose up -d
[+] Running 1/1 ✔ Container frankenphp_test_env-php-1 Started$ docker exec -it frankenphp_test_env-php-1 bash
root@6c03bca33d57:/app# set | grep ENV
APP_ENV=devroot@6c03bca33d57:/app# bin/console cache:clear
// Clearing the cache for thedev
environment with debug true [OK] Cache for the "dev" environment (debug=true) was successfully cleared.
APP_ENV
is set to dev by building the frankenphp image,
and we see that here.
The environment variable is indeed set to dev
, and when using a console command,
you see that our app uses this dev
environment.
No worries, let's perform
bin/console dump-env:test
!
Mmmh ... Symfony console still think it is inroot@6c03bca33d57:/app# composer dump-env test
Successfully dumped .env files in .env.local.phproot@6c03bca33d57:/app# bin/console cache:clear
// Clearing the cache for thedev
environment with debug true [OK] Cache for the "dev" environment (debug=true) was successfully cleared.
dev
environment!
Let me check my .env.local.php
file, maybe something as gone wrong.
root@6c03bca33d57:/app# cat .env.local.php
<?php
// This file was generated by running "composer dump-env test"
return array (
'APP_ENV' => 'test',
'SYMFONY_DOTENV_PATH' => './.env',
'APP_SECRET' => '***',
);
Seemed to have worked fine...
Yet, my app doesn't know it... Yes, because your server environment variable (which means in this case, the container environment variables) are preferred over the app definitions! This container-level environment variable actually override any definition that you could have in a
.env
file or even .env.local
file.
Running tests
When using this app in your personal computer, you are in the dev environment. However, you can still run your tests, in thetest
environment!
For this to work, we have PHPUnit to thank, especially, the configuration given below:
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
[...]>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
</php>
[...]
This configuration allows for your code to know to run the PHPUnit in the test
environment,
with all the according definitions.
Related links :
- https://symfony.com/doc/current/configuration.html#configuring-environment-variables-in-env-files
- https://github.com/dunglas/symfony-docker/pull/739
- https://docs.docker.com/compose/how-tos/environment-variables/envvars-precedence/
- https://github.com/symfony/recipes/blob/main/phpunit/phpunit/11.1/phpunit.dist.xml#L16
Socials
Github
Stack
Overflow
LinkedIn