khs1994-docker / lnmp

:computer: :whale: :elephant: :dolphin: :penguin: :rocket: Start Docker LNMP(LEMP) In less than 2 minutes Powered by Docker Compose. 让 PHP 开发者快速(一键)搭建基于容器技术(Docker、Kubernetes)的开发、测试、生产(CI/CD by Drone)环境.

Home Page:https://docs.lnmp.khs1994.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`laravel`容器中`.env`配置在`config`下读取错误

cgfeel opened this issue · comments

我知道在laravel-demo中有提示:

不要在 config 以外的地方调用 env() 函数,运行 config:cache 以后该函数永远返回 null

不过这次我是在config内部调用,举例:

  • api_service/.env中是这样写的:APP_ENV=local
  • api_service/config/app.php是默认的:'env' => env('APP_ENV', 'production'),

我拿tinker来测试,得到的却是development,如下:

$ ./lnmp-docker php8-cli php /app/api_service/artisan tinker
Psy Shell v0.11.5 (PHP 8.1.1 — cli) by Justin Hileman
>>> echo config('app.env')
development

我尝试重新启动容器,测试结果还是一样,难道说laravel中的.env在容器build的时候被替换掉了?我找了文档很久都没有提到。


这里我是拿APP_ENV这一项举例,发现.env里其他项,在config下也读取异常。这点还是很重要的,因为在我本地环境、宿主机测试环境、还有服务器生产环境3个地方,需要用到3个不同的.env

You can writing some word in a comment to trigger action:

  • /translate-title

我用lnmp创建了一个新项做测试,并设置一个域名解析到新项目

$ cd ./app &&  ../bin/lnmp-laravel new laravel 
$ cd ../ && ./lnmp-docker nginx-config http laravel test.laravel-test.com
  • 修改test.laravel-test.com.conf,将root指向/app/laravel/public
  • 修改本机host,将test.laravel-test.com指向测试机

配置一个路由./app/laravel/routes/web.php,如下:

Route::get('/test', function () {
    return [
        'env' => env('APP_ENV'),   // 查询环境变量,如果不是 null 说明并没有产生缓存
        'putenv_exists' => function_exists('putenv'),    // 确认是否禁用读取.env
        'file_exists' => file_exists(base_path('.env')),    // 确认.env是否存在
        'dir_list' => scandir(base_path()),    // 扫描项目根目录所有文件
        'env_contents' => file_get_contents(base_path('.env')),    // 读取项目根目录.env文件内容
    ];
});

访问 http://test.laravel-test.com/test 这里只看APP_ENV的结果,如下:

{
    "env":"development",
    "putenv_exists":true,
    "file_exists":true,
    "dir_list":[
        ".env",
        ".env.example",
    ],
    "env_contents: "APP_NAME=Laravel
APP_ENV=local",
}

说明:

  1. 并没有生成缓存,否则env('APP_ENV')应该是null
  2. 读取env环境变量值是development,并没有禁用putenv,不存在禁止读取env文件的情况;
  3. env文件存在于项目根目录,且env环境变量值是local

这就很费解了,为什么读出来的实际值和.env不一致呢?

  1. 我就去看是不是读了.env.example,结果发现.env.example中也是APP_ENV=local
  2. 也没有其他.env*文件,那么这个环境变量到底来自哪里呢?
  3. 肯定也不是/app/laravel/config/app.php,因为默认值是'env' => env('APP_ENV', 'production'),

还有什么情况会造成这个问题呢?实在不能理解了。。。

我再做了一个测试,还是/app/laravel这个项目,先查询.env内容确保是local

$ ./lnmp-docker php8-cli cat /app/laravel/.env
APP_ENV=local

再查询config内容是否正确

$ ./lnmp-docker php8-cli cat /app/laravel/config/app.php 
    'env' => env('APP_ENV', 'production'),

两个文件都没有问题,我开始生成缓存文件:

$ ./lnmp-docker php8-cli php /app/laravel/artisan config:cache

这个时候打开缓存文件./app/laravel/bootstrap/cache/config.php,可以看到env指向了development。。。。这是为什么?这个数据来自哪个文件
image

看到一篇文章是这么说的 https://blog.csdn.net/weixin_34204057/article/details/91759994

因为环境变量是通过php的 putenv()getenv() 实现写入和读取的,如果webserver是通过 php -S localhost 或类似命令支持的,那么在你重启服务之前,laravel不允许覆盖之前的环境变量值。

我尝试过./lnmp-docker down之后./lnmp-docker up不管用

请问这个有解决办法吗?

我找到一个暂时能够解决问题的办法,分几种情况:

  • 第1种:.env也覆盖不了的变量,替换个名字,比如APP_ENV,就加个名字如:APP_ENV_DOCKER=local
    修改config/app.php,将env改为新的名字如:'env' => env('APP_ENV_DOCKER', 'production'),然后重新生成缓存
  • 第2种:.env可以覆盖的变量,修改.env后重新生成缓存

最后提醒,如论是那种方式,一定要重新生成缓存,否则修改不生效,无论是生产环境,还是开发环境,一定要手动生成缓存

$ ./lnmp-docker php8-cli php /app/laravel/artisan config:cache

至于有哪些环境变量是可以覆盖的,哪些不能覆盖,我也不清楚,遇到了就用上面的方法来解决吧,虽然比较笨,也很麻烦,目前也只能这样了

再拉取最新提交试试

再拉取最新提交试试

好的,我一会试试看

再拉取最新提交试试

我重新拉取后,执行下面的命令重新生成缓存,在缓存文件./bootstarp/cache/config.php中结果还是development

./lnmp-docker php8-cli php /app/api_service/artisan config:cache

我拉取的应该是最新的20.10

$ git log
commit 2ca22ec3ce26564f8c6f2d62a5a6383cad636a36 (HEAD -> 20.10, origin/20.10)
Author: Kang Huaishuai <khs1994@khs1994.com>
Date:   Wed Jun 22 18:51:58 2022 +0800

    Support custom APP_ENV,close #1228
    
    Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>

.env 文件(lnmp项目根目录,不是laravel项目中的)中修改 APP_ENV 的值了吗

APP_ENV

谢谢,解决了,原来需要修改./.env,我重新查了下文档,原来在php容器化常用命令里找到了

https://docs.lnmp.khs1994.com/command.html#app-env