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
1 Like

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

1 Like

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

I’m highly speculating, but I think COPY should also do the trick.
I’m just guessing, but are you using Mac/Windows when creating the crontab file?
I saw plenty issues about crontab not working due to wrong line breaks. Only LF line breaks works for crontab, which is the one we get by default when using linux.

Moving to echo does make senses as now the file is inserted by debian-based OS (FROM php:7.4-fpm).

Just for future user that may stumble upon this problem.
I’ve also had the same problem. Thank you for sharing your solution.