Issue
I have a Laravel 9 application deployed on GKE. It has some background jobs which I have configured to run using supervisor (I will share snippets of config files below).
The Problem
The problem is when Jobs are run using scheduler or manually using the artisan command, there are cache files created in storage/framework/cache/data
path with root
user as owner. This causes the issues as errors keep logging with message Unable to create lockable file
because all the other folders and files have user www-data
which we set in Dockerfile
. To fix it, I have to manually run chown -R www-data:www-data .
in the above cache path.
Dockerfile
FROM php:8.0-fpm
# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/
# Set working directory
WORKDIR /var/www
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
libpng-dev \
libonig-dev \
libicu-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
libzip-dev \
libpq-dev \
ca-certificates \
zip \
jpegoptim optipng pngquant gifsicle \
nano \
unzip \
git \
curl \
supervisor \
cron \
nginx
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo pdo_mysql mbstring zip exif bcmath
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install gd
RUN docker-php-ext-configure intl
RUN docker-php-ext-install intl
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY scripts/supervisor.conf /etc/supervisor/conf.d/supervisor.conf
COPY /scripts/nginx/nginx.conf /etc/nginx/sites-enabled/default
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Setup cron job
COPY scripts/crontab /etc/cron.d/scheduler
RUN chmod 0644 /etc/cron.d/scheduler
RUN usermod -u 1000 www-data
RUN usermod -G staff www-data
COPY --chown=www-data:www-data . /var/www
RUN touch /var/www/storage/logs/laravel.log
RUN mkdir /var/www/storage/framework/cache/data
RUN chown -R www-data:www-data /var/www/storage
RUN chmod -R 777 /var/www/storage
RUN composer install --no-interaction
COPY /scripts/entrypoint.sh /etc/entrypoint.sh
RUN chmod +x /etc/entrypoint.sh
EXPOSE 80 443
ENTRYPOINT ["/etc/entrypoint.sh"]
crontab
* * * * * root echo "cron working..." >> /var/log/cron.log
* * * * * root /usr/local/bin/php /var/www/artisan schedule:run >> /var/log/cron.log
entrypoint.sh
#!/usr/bin/env bash
php artisan config:cache
service supervisor start
service nginx start
php-fpm
supervisor.conf
[program:cron]
process_name=%(program_name)s_%(process_num)02d
command=cron -f
autostart=true
autorestart=true
startretries=5
numprocs=1
stderr_logfile=/var/log/cron.log
stderr_logfile_maxbytes=10MB
stdout_logfile=/var/log/cron.log
stdout_logfile_maxbytes=10MB
Things I have tried so far
I have tried changing user group in crontab from root to www-data but that result in cron not working at all.
I have tried changing supervisor user
to www-data so cron command is run by www-data instead of root.
Also setting user as www-data in Dockerfile, but all of the solutions either result in cron not running at all or the files created by jobs are still owned by root
user.
Solution
After much investigation, I found that it is not a good practice to run laravel scheduler as root
user because that can create files with root owner.
I updated my crontab
file to following:
* * * * * root su -c "/usr/local/bin/php /var/www/artisan schedule:run >> /var/log/cron.log" -s /bin/bash www-data
This way the cache files created will be owned by www-data
and no files from root owner are created.
Hope this helps someone who is facing the same issues.
Answered By - Usama Baig Answer Checked By - Willingham (WPSolving Volunteer)