Symfony7 .env Setup (Docker, .env, .env.prod, .env.local)
.env (commited to project):
### Project .env with defaults for all environments and dev defaults # # Additionally we use: # - .env.uat, .env.prod with environment specific defaults # - .env.local uncommited, with local overrides at servers (APP_ENV, secrets, eg. database credentials) # # Furthermore we use the following command to make .env vars available in terminal/bash scripts. This allows to NOT type secrets in command call options. # eval "$(docker compose exec studyamo-php bin/console app:dotenv --export)" # # # In all environments, the following files are loaded if they exist, # the latter taking precedence over the former: # # * .env contains default values for the environment variables needed by the app # * .env.local uncommitted file with local overrides # * .env.$APP_ENV committed environment-specific defaults # * .env.$APP_ENV.local uncommitted environment-specific overrides # # Real environment variables win over .env files. # Important notice: In docker enviroments "real env vars" must be defined for the php container! # Local shell env vars are ignored!
.env.prod (environment specific non-sensitive settings, commited):
# Non-sensitive variables for "prod" environment that differ from .env # Sensitive variables are defined in .env.local (uncommitted) # Note: APP_ENV cannot be set here, as this file is only called if APP_ENV is already set in .env.local # Debugging (toolbar) if not defined: dev->true, prod->false APP_DEBUG=false MY_VAR=foo
.env.local (only on server, sensitive settings/secrets, uncommited):
# .env.local file for sensitive env variables like secrets. # The variables defined here take precedence over the ones defined in the main .env file # APP_ENV also needs to be defined here, otherwise .env.[APP_ENV] cannot be loaded # Environment (dev, prod) APP_ENV=prod # Secrets go here...
If you want to make the .env vars also available as real ENV vars you can do, e.g. at your prod server (example for docker compose):
- ssh foo@prod.example.com
- vi ~/.profile
-
# ... Other stuffa above... cd ~/your-project-dir eval "$(docker compose exec your-project-php bin/console app:dotenv --export)" ls -la git status
-
src/DotEnvCommand.php
<?php namespace App\Command; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; #[AsCommand( name: 'app:dotenv', description: 'Show or export .env variables.', )] class DotEnvCommand extends Command { protected function configure(): void { $this ->addOption('plain', null, InputOption::VALUE_NONE, 'Show variables in plain format') ->addOption('export', null, InputOption::VALUE_NONE, 'Show variables as export statements') ->setHelp(<<<'HELP' To export variables into your current terminal session, run: <info>eval "$(php bin/console app:dotenv --export)"</info> HELP ); } protected function execute(InputInterface $input, OutputInterface $output): int { // If no options given, show help if (!$input->getOption('plain') && !$input->getOption('export')) { return $this->getApplication()->find('help')->run($input, $output); } $vars = []; // Nice: symfony has information about which vars are loaded from .env files $dotenvVars = explode(',', $_ENV['SYMFONY_DOTENV_VARS'] ?? ''); foreach ($dotenvVars as $key) { if (isset($_ENV[$key])) { $vars[$key] = $_ENV[$key]; } } // Sort keys alphabetically ksort($vars); foreach ($vars as $key => $value) { if ($input->getOption('export')) { // Properly escape the value for shell $escapedValue = addcslashes($value, '"\\$`'); $output->writeln("export {$key}=\"{$escapedValue}\""); } else { $output->writeln("{$key}={$value}"); } } return Command::SUCCESS; } }