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
2 Likes

Have you thought of running cron in a separate container? My understanding is using using separate containers for different services is what docker was built on. I built a simple docker container based on alpine using cron. It is only 5MB. Makes it really easy to deploy and re-deploy to multiple applications.

https://hub.docker.com/r/djpic/cron

I’ve stumbled upon the exact same issue. My cronjob was supposed to run a php script that used #!/usr/bin/env php as shebang line. This used to work fine when I based my container off ubuntu:18.04, but it stopped when I switched to php:7.4.

The problem is that env is looking in your PATH for php, and when you put your cronjob in /etc/cron.d/, there is no PATH variable defined. Since this is specified in the normal /etc/crontab, your workaround by appending it there works.

Another solution is to add the following two lines in your file in /etc/cron.d/.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin