laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.54k stars 11.02k forks source link

Scheduler don't uses env-variable handed over via docker-compose #46956

Closed Orscheler closed 1 year ago

Orscheler commented 1 year ago

Laravel Version

10.4.1

PHP Version

8.2.4

Database Driver & Version

10.10.2-MariaDB

Description

We have the following setup:

docker-compose containing the environment variable for the affected container:

environment:
            APP_ENV: int

The .env inside the Laravel root directory doesn't include the APP_ENVvariable.

The config/app.php is being configured, to use "production" in case the APP_ENV variable is not being configured.

'env' => env(
   'APP_ENV', 
   'production'
),

In app/Console/Kernel.php several jobs are being defined, which also make use of the environment variable. We also added Log::info('Environment: '.config('app.env')); to the schedule.

Furthermore there is a cronjob being defined, that triggers the scheduler: * * * * * /usr/local/bin/php /app/artisan schedule:run >> /var/log/cron.log 2>&1

The cronjob is running with the root-user, however the given env-variable is not being used, but the default instead:

[2023-05-04 09:40:01] production.INFO: Environment: production  
[2023-05-04 09:41:01] production.INFO: Environment: production  
[2023-05-04 09:42:02] production.INFO: Environment: production  
[2023-05-04 09:43:01] production.INFO: Environment: production 

Even the variable is being set:

root@2a57ec5602df:/app# export | grep APP_ENV
declare -x APP_ENV="int"

When running the scheduler manually (also with the user root) /usr/local/bin/php /app/artisan schedule:run, everything is being fine

[2023-05-04 09:38:38] int.INFO: Environment: int
[2023-05-04 09:38:44] int.INFO: Environment: int

php artisan config:clear has already been executed to make sure, that there is no caching issue.

Steps To Reproduce

See example above

github-actions[bot] commented 1 year ago

Thank you for reporting this issue!

As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.

If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.

Thank you!

andumy commented 1 year ago

Hey @Orscheler I've tried to replicate your issue, but It seems that I cannot reproduce the bug. How does your docker-compose file look like?

The setup I've used to replicate:

docker-compose.yml:

version: '2.4'

services:
    php:
        image: php:8.2-fpm
        environment:
            APP_ENV: int
        volumes:
            - .:/var/www/html
        networks:
            - test

    nginx:
        image: nginx:latest
        volumes:
            - .:/var/www/html
            - ./default.conf:/etc/nginx/conf.d/default.conf
        ports:
            - 8080:80
        networks:
            - test

networks:
    test:

default.conf:

server {
    listen 80;
    root /var/www/html/public;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;

        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;

         proxy_set_header Host $host;
         proxy_set_header X-Forwarded-Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header X-Forwarded-Server $host;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    error_log /var/log/nginx/laravel_error.log;
    access_log /var/log/nginx/laravel_access.log;
}

routes/web.php:

Route::get('/', function () {
    dd(config('app.env'));
});
nunomaduro commented 1 year ago

@Orscheler, have you managed to resolve the issue yet? If not, you could attempt to set the environment variable at the service > php level as instructed by @andumy:


services:
    php:
        image: php:8.2-fpm
        environment:
            APP_ENV: int

In case this solution doesn't work, would you be willing to create an open-source repository with a new Laravel application, the necessary changes to reproduce the issue, and your Dockerfile? This will help us to attempt reproducing the issue on our local environment. No worries, if we are able to verify that there is an issue here, I will re-open this issue.

d-soerensen commented 6 months ago

I am also facing this issue today.

@andumy the problem here is a little different than using a http request. If you use the scheduler to boot jobs or other things it simply cannot read environment variables from anywhere but the .env file.

Notice how the 'mongodb' connection has no problem reading the 'MONGO_DB_HOST' from .env whereas the 'system-db' has all the default values, because it can't read from the servers environment variables. (and yes I triple checked that they exist)

[2024-04-24 20:19:02] production.DEBUG: env vars {"vars":{"mongodb":{"driver":"mongodb","dsn":"://user:secret@development-1.v39lgpg.mongodb.ne/?retryWrites=true&w=majority","database":"default"},"system-db":{"driver":"mongodb","dsn":"://user:secret@localhost/?retryWrites=true&w=majority","database":"default"}}}

[2024-04-24 20:19:02] production.ERROR: Failed to parse MongoDB URI: '://user:secret@localhost/?retryWrites=true&w=majority'. Invalid URI Schema

.env file: image

Kernel.php: image

config/database.php: image

artisan tinker has no problem seeing env vars outside of .env: image

My examples are from a production GKE environment with configMaps, but nonetheless the same scenario as OP with their env vars defined in their docker-compose.yml.

d-soerensen commented 6 months ago

@nunomaduro the issue is not resolved and the suggested tip is unrelated to the issue. Please review it.

Orscheler commented 6 months ago

What I found out: When cron executes a job, it doesn’t load the environmental variables from files like ~/.bashrc, ~/.bash_profile, /etc/profile and others. This is because cron runs jobs from a non-interactive, non-login shell.

Therefore those variables need to be loaded before starting the cron. I'm doing this via a supervisor job.

[program:cron]
command=/bin/bash -c "printenv > /etc/environment && /usr/sbin/cron -f"

This was fixing my issue with the environment values handed over by the container. In case you are using the .env file to set the variables, you're not facing this issues.

So this issue is not Laravel related, but being related to the host.

voicerecordist commented 4 days ago

If you in docker container and since the environment variables only need to be written once, you may do it with entrypoint file. Here is a example of Entry Point Usage:

#!/bin/bash

# Export all environment variables to /etc/environment for cron jobs
printenv > /etc/environment

# Start the cron service (if it's not started elsewhere)
cron

# Start your main process (e.g., PHP-FPM, nginx, Supervisor, etc.)
exec "$@"