Closed pschaub closed 6 years ago
@pSchaub
Basically this shouldn't be the case, as Laravel itself loads it's environment variables using DotEnv, which is called with immutable set to true, so if a system environment variable already exists and is called DB_HOST, this should not get overridden.
Which webserver do you use, if I may ask? Apache for example does NOT use environment variables from the operating system itself/set within the operating system itself per default, so you'd have to include those variables (source them) in eg. /etc/apache2/envvars and restart apache for them to be recognized by Laravel. You can also have a look at mod_env which can do the same, with a little bit more configuration (keyword PassEnv Directive): https://httpd.apache.org/docs/2.4/mod/mod_env.html
Can you please try this?
If you dont want the system env
to be overridden by your local .env
file - then just remove that variable from your .env
file?
@laurencei with 5.8 I'm having the exact oposite issue. System vars are only considered if I run artisan config:cache otherwise it keeps looking first for .env file even tough its available as system var... I cant find if this was intentional change or...
@rockoo - not sure mate. There were some issues with the whole env
stuff that got fixed in 5.8.8 from memory. Try the latest version and see if the problem persists? If so, open a new ticket with all the details.
@rockoo long shot, but have you got to the bottom of this by any chance? Facing the same thing at the moment and it leaves me a bit baffled
@osteel sorry for the late reply. Unfortunatelly not for that version. The way I got around it was to execute a shell script on docker build that would run cache command... :/
@rockoo no worries, thanks for getting back to me. I'm facing this with Laravel 6.x. I am populating the .env
file via a bash script instead for the time being, although this is not ideal!
@osteel If I come up with an idea of what is happening I will update you!
Quick update: I've now had to deploy the application to a production environment, where environment variables are injected into the container as server-level ones (no .env
file). I had no other choice than to run config:cache
as part of an initialisation script for the container, otherwise the environment variables are ignored.
We're using Laravel 6.2 at the moment.
@osteel I've also been looking into this in a container environment (although with L7) and it seems the documentation may be a little deceptive.
Reading the docs, I got the impression that config:cache
would cache references to the environment variables (provided the calls to env()
were in config files), so they could still be altered at runtime.
But it looks like when config:cache
is run, it'll just grab the current value and cache that. So if your build system's environment variables don't happen to match prod, you're SOL.
This is a pain when trying to use Laravel inside a container, because you effectively have no way to cache at build time AND have dynamic config.
@laurencei Am I sort of on the right track here? Is there simply no way to get environment variables at runtime after a config:cache
(even it the calls to env()
are inside config files)?
@danielcotton You are right. You should run config:cache
again in your container after you changed the environment variables. It's not enough to do it in your build. You need to run if after deployment.
See the docs:
If you execute the config:cache command during your deployment process, you should be sure that you are only calling the env function from within your configuration files. Once the configuration has been cached, the .env file will not be loaded and all calls to the env function will return null.
Source: https://laravel.com/docs/8.x/deployment#optimizing-configuration-loading
You should run config:cache again in your container after you changed the environment variables.
Hey @pschaub , this is not always feasible. In kubernetes (or even in docker-compose) some ENV variables are set when the container starts up. When supporting multiple environments (dev, staging, production, etc.) and using continuous deployment, .env
files are pretty much unworkable.
I would argue that system-level ENVs should take precedence over .env
files.
@eriadam Is there a reason to set the variable in the .env
file if you know you will set it through the system-level env?
Just remove it from the .env
file?
@pschaub Yes that works, but the problem here is with having to run config:cache
when I set a new system level variable at runtime. If an ENV variable is set/changed, its new value should be available in the application the next time it is accessed. Again, this is an issue with kuberentes and multiple environments.
I agree with @eriadam. I think what is really being asked is a maybe a net-new feature or flag to the config:cache
, where we can config:cache
on docker build, but have the generated cached config use the native $_ENV['key']
. Just a thought. When following the 12 factor app principles its best to build once and then promote with runtime configs. Running bash scripts and commands on startup is ok for more basic deployments, but when we start using Lambdas or Knative time-to-boot is imperative. Also I am happy to look into a creating a PR if that concept is compelling.
What I ended up doing is removing the .env
file completely and injecting the environment variables normally (docker-compose or k8s config map), then changing the start up command in the container like so:
FROM php:7.4-apache
// do stuff...
CMD php artisan config:cache && apache2-foreground
This caches the system environments when the container starts up, so by the time the first request comes in, they are in place. Not super happy with it, but works in our setup. Not sure it would work for @fuzzybaird's lambda use-case.
@eriadam I think that is a great solution for most people. But for me I am trying to safe precious milliseconds on container/lambda cold starts. But I will give that a try and see how much it impacts the boot time and report back.
Description:
The documentation describes:
So the developer also thinks that the
config:cache
function will cache the system-level environment variable if set and not just values from the.env
file. But it does not (yet).Steps To Reproduce:
.env.example
to.env
. We use the envDB_HOST
in our example.DB_HOST
on system-level.php artisan config:cache
..env
file and not the value from the system environment variable.