laravel 8 sail, cron not running automatically - php

I am using laravel 8 sail, and I want to run a task repeatedly, but seems schedule task not getting called.
I have installed crontab
RUN apt-get update && apt-get install -y cron
COPY crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab \
&& crontab /etc/cron.d/crontab \
&& touch /var/log/cron.log
and created crontab file
* * * * * cd /var/www/html && php artisan schedule:run --no-ansi >> /var/log/cron.log 2>&1
# Don't remove the empty line at the end of this file. It is required to run the cron job
And inside Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('inspire')->everyMinute();
$schedule->call(function () {
DB::table('products')->delete();
})->everyMinute();
}
Normally after every minute it should run inspire command and delete products table, but nothing happen.
note: When I get inside the docker instance and run 'cd /var/www/html && php artisan schedule:run --no-ansi >> /var/log/cron.log 2>&1' it works fine but automatically not.

Related

How to set up Supervisor and Laravel Horizon on Docker

I have successfully deployed a laravel application with horizon installed to AWS ECS. However horizon has remained Inactive and I am stuck trying to get it to work as my emails are getting queued and never sent. This is my docker file
FROM php:8.1.4-fpm-alpine3.14
RUN apk update
RUN apk add --no-cache git libzip-dev zip unzip php8-exif supervisor
RUN mkdir -p /usr/src/php/ext/redis; \
curl -fsSL https://pecl.php.net/get/redis --ipv4 | tar xvz -C "/usr/src/php/ext/redis" --strip 1; \
docker-php-ext-install redis;
RUN docker-php-ext-install pdo pdo_mysql zip exif \
&& curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/html
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY horizon.conf /etc/supervisor/conf.d/horizon.conf
COPY . .
RUN chown -R www-data:www-data /var/www/html
RUN composer install --ignore-platform-req=ext-pcntl
RUN chmod 544 startup.sh
CMD ["/usr/bin/supervisord"]
ENTRYPOINT ["./startup.sh"]
I created a supervisord.conf file with this content in it
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
a horizon.conf file with its content below
[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
stopwaitsecs=3600
and this is what my startup script startup.sh looks like
#!/bin/sh
php artisan migrate
php artisan db:seed
php artisan config:cache
php artisan route:cache
php artisan horizon
php artisan queue:restart
php artisan serve --host=0.0.0.0 --port 80
I am not exactly very knowledgable with supervisor on containers so I need help figuring out why I am not able to get horizon to be active and fix it.

Laravel Scheduler creates cache files as root user

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.
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.

shell_exec sh file including npm, npx

I have a .sh file that I execute from PHP with the shell_exec command. The .sh files are like below.
It creates the directories and "npm init -yes" line is executed successfully and I get the return lines but "npm install --save-dev hardhat" and "npx hardhat" lines have no return and don't do what expected to. Any idea how can I execute it and it works? When I execute the .sh file with root on the terminal it works also. But not with user apache.
cd /var/nftprojects
mkdir nft57
cd nft57
chmod -R 777 /var/nftprojects/nft57
mkdir ethereum
chmod -R 777 /var/nftprojects/nft57/ethereum
cd ethereum
npm init -yes
npm install --save-dev hardhat
npx hardhat --verbose
cd /var/nftprojects/nft57
mkdir /var/nftprojects/nft57/web
cd /var/nftprojects/nft57/web
npx create-next-app#latest
cd /var/nftprojects/nft57/ethereum
touch .env
npm install dotenv --save

CodeDeploy gets stuck on Install or AfterInstall

I have codedeploy setup with same appspec file for 6 different deployments. While the codedeploy works perfectly for some of the deployments, it gets stuck on others.
The issue is, it gets stuck on random environments on random basis, sometimes on Install phase and sometimes on AfterInstall phase. It also gets stuck on one of the multiple servers inside same deployment.
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html/current
permissions:
- object: /var/www/html/current
pattern: "**"
owner: root
group: www-data
mode: 644
type:
- file
- object: /var/www/html/current
pattern: "**"
owner: root
group: www-data
mode: 755
type:
- directory
hooks:
BeforeInstall:
- location: scripts/beforeinstall.sh
runas: root
AfterInstall:
- location: scripts/afterinstall.sh
runas: root
beforeinstall.sh
#!/bin/bash
php artisan cache:clear
hostname >> /tmp/bhostname.txt
crontab -r
if [ "$HOSTNAME" = horizon ]
then
hostname >> /tmp/ahostname.txt
cd /var/www/html/current/backend && sudo php artisan down
sudo supervisorctl stop laravel-worker:*
sleep 30
sudo service supervisor stop
sleep 30
rm -rf /var/www/html/current/backend/bootstrap/*
rm -rf /var/www/html/current/backend/storage/*
rm -rf /var/www/html/current/backend/worker.log
else
cd /var/www/html/current/backend && sudo php artisan down
rm -rf /var/www/html/current/backend/bootstrap/*
rm -rf /var/www/html/current/backend/storage/*
fi
afterinstall.sh
#!/bin/bash
chown -R www-data:www-data /var/www/html/current/backend/bootstrap
chown -R www-data:www-data /var/www/html/current/backend/storage
cd /var/www/html/current/backend && sudo php artisan cache:clear
cd /var/www/html/current/backend && sudo php artisan view:clear
cd /var/www/html/current/backend && sudo php artisan config:cache
export GOOGLE_APPLICATION_CREDENTIALS=/var/www/html/current/backend/storage/gcp_translate.json
# (crontab -l 2>/dev/null; echo "*/2 * * * * cd /var/www/html/current/backend/ && php artisan schedule:run >> /dev/null 2>&1")| crontab -
echo "*/2 * * * * cd /var/www/html/current/backend/ && php artisan schedule:run >> /dev/null 2>&1" > /var/spool/cron/crontabs/www-data
echo "* * * * * /bin/chown -R www-data.www-data /var/www/html/current/backend/storage/logs" > /var/spool/cron/crontabs/root
echo "0 0 * * * rm -rf /opt/codedeploy-agent/deployment-root" > /var/spool/cron/crontabs/root
chmod 600 /var/spool/cron/crontabs/www-data
chmod 600 /var/spool/cron/crontabs/root
service cron restart
if [ "$HOSTNAME" = horizon ]
then
cd /var/www/html/current/backend && php artisan up
cd /var/www/html/current/ && pwd && ls -altr && mv laravel-worker.conf /etc/supervisor/conf.d
sudo service supervisor restart
sleep 30
sudo supervisorctl restart laravel-worker:*
fi
service php7.4-fpm restart
service nginx restart
The issue was resolved by reducing build size.
The build used to be around 900 MB after packaging as .zip file. After trimming it down to 600 MB, AWS CodeDeploy is not getting stuck on random basis.
The build was trimmed by removing node_modules (1.7 GB without compression) from frontend.
Therefore, I conclude the issue to be inadequate size of servers (t3.medium) with regards to the highly compressed bigger builds.

Cron does not run in a PHP Docker container

I am using the php:7.4-fpm Docker image and I'm trying to set up cron to run but it's not running.
Here is my Dockerfile:
FROM php:7.4-fpm
# Set working directory
WORKDIR /var/www
# Install dependencies
RUN apt-get update && apt-get install -y \
cron \
build-essential \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
libzip-dev \
libmcrypt-dev \
libonig-dev \
zlib1g-dev \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
graphviz \
curl \
supervisor
# Install Imagick
RUN apt-get update && \
apt-get install -y libmagickwand-dev --no-install-recommends && \
pecl install imagick && \
docker-php-ext-enable imagick
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
# Permissions for Laravel
RUN chown -R www-data:www-data /var/www
RUN chmod -R 777 /var/www
# Copy crontab file to the cron.d directory
COPY ./docker/php-server/crontab /etc/cron.d/crontab
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/crontab
# Apply cron job
RUN crontab /etc/cron.d/crontab
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
EXPOSE 9000
CMD bash -c "cron && php-fpm"
When I enter the container and check the contents of /etc/cron.d/crontab it is correct
* * * * * php /var/www/artisan schedule:run >> /var/log/cron.log 2>&1
# An empty line
But it's not being run. I'm not sure what's going on here..
When I run service cron status it says [ ok ] cron is running. But nothing is happening.
So I finally managed to solve it. I have no idea why COPYing the cron file wasn't working. I still don't know why. (maybe someone smarter than me can explain it). But I solved it very simply by appending my commands to the /etc/crontab file and now it works.
P.S. crontab file requires a new line character at the end so using echo adds it automatically.
Here is my updated Dockerfile (I deleted all the other lines where I copied the crontab):
RUN echo "* * * * * root php /var/www/artisan schedule:run >> /var/log/cron.log 2>&1" >> /etc/crontab
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
I had the same bug, fixed by setting up the cron on the machine hosting the docker container instead of the container itself.
So the cron entry translates to something like :
* * * * * docker exec web php artisan schedule:run >> storage/logs/cron.log 2>&1
If you face an issue with tty allocation, try with docker exec -it

Categories