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;
}
}

