Development

20. August 2022

Docker and Symfony Dotenv can sometimes be a pain

While planning and implementing a deployment workflow using docker-compose for Orchestration, I had invested a lot of time regarding several and reoccurring problems in combination with the Dotenv component of Symfony. So I would like to share my findings and my way of solving this, so you can bring your application quicker into production.

The problem

For deployments in test and production, I use a separate deployment repository containing the configuration like an .env file for the variables for that actual specific environment (e.g. prod) which is automatically written in the $_SERVER environment of the container by docker. But when running the container in these environments, I noticed that the dev configuration is suddenly used.

So I went to debugging this issue until I noticed that after builds, suddenly a wild .env file appeared out of nowhere in the root directory of the project. Which was kinda weird because it was never committed, only the .env.dist existed in the repository.

The explanation

By default, Symfony and docker-compose use a .env file which is found in the root of the directory. So this .env file would be read by both, which is mostly no problem during development.

When running composer install the post-scripts of Symfony flex actually copy the .env.dist to .env if it does not exist. If this had landed in production, in my case the configuration would be as if it were in development. This explains why this wild file suddenly appears out of nowhere. Of course, while developing a .env already existed, so this issue didn’t occur.

Since Symfony always prefers environment variables from the local .env file in the root of the project, these overwrite the ones from the $_SERVER which should actually be the ones to use.

So, I thought about how can this be solved for good and came up with the following solutions.

The solution

To be 100% sure there will not be a problem in the future with this, we have committed ourselves to move the .env file (which is empty) for symfony into a separate directory config/environment/.env. Like this, Symfony won’t load the .env file in the root of the project, and they do not interfere with the variables for docker.

Symfony projects prior to 5.1

The path of the .env file can be changed in config/bootstrap.php. I just create an empty .env file in this directory to omit runtime errors.

(new Dotenv(false))->loadEnv(dirname(__DIR__) . '/config/environment/.env');

Symfony projects 5.1+

After updating several applications to the 5.1 I have encountered that the bootstrap.php is actually removed. But it still could be used in future versions, so I used it until 5.3.

The reason is that Symfony introduces the new runtime, which is available from version 5.3 and upwards. This added many new features and integrations, also regarding the Dotenv component.

After reading the documentation, I have gladly found methods for configuration of this path within either the $_SERVER environment or composer.json. I am going to use the composer version, since it is nicer IMHO.

"extra": {
    "symfony": {
        "allow-contrib": false,
        "require": "5.4.*"
    },
    "runtime": {
        "dotenv_path":  "config/environment/.env"
    }
},

Disclaimer:
I cannot be help responsible for any injuries, legal problems or damage to your devices.
You act upon your own responsibility and risk.