Search code examples
docker-composecronalpine-linux

How do I get crond to autostart on Alpine in a Docker container?


I want to be able to run a simple bash script within a container service on the hour using cron. I'm using Alpine Linux via docker-compose with a custom Dockerfile to produce a php-fpm based image, on which I hope to get crond running as well - except I can't.

Executing ps aux | grep cron on the container once built, returns nothing.

From what I understand, the usual Linux startup processes don't exist in Docker containers - fine - so how do I auto-start crond? Its dirs under /etc/periodic/ are created automatically, so I don't understand why the applicable process that consumes those dirs, isn't also running.

I tried creating a dedicated service definition within docker-compose.yml, which actually worked but the shell script to be run hourly needs access to a php binary which is running in a different container, so this isn't a viable solution.

If I shell into the container and run rc-service crond start I get this - but it never "finishes":

/var/www/html # rc-service crond start
 * WARNING: crond is already starting
#> docker --version
Docker version 19.03.8, build afacb8b7f0
#> docker-compose --version
docker-compose version 1.23.2, build 1110ad01

I need a solution that I can place into my Dockerfile or docker-compose.yml files.

Dockerd is running on Ubuntu Xenial FWIW.


Solution

  • to run a cronjob container (Alpine), you need to make sure sure that the command of your docker container is

    exec crond -f
    

    if you want to add this to a docker file

    CMD ["exec", "crond", "-f"]
    

    you also may need to update the corn files before running the above command

    Update based on the docker file and compose

    To be able to solve your issues you need to update your docker-compose to have two containers one for cron and one for web

     service_php_cron:
        build:
          context: .
          dockerfile: .docker/services/php/Dockerfile.dev
        container_name: base_service_php
        command: 'cron_jobs'
        volumes:
          - ./app:/var/www/html/public
        env_file:
          - ./.env
        # Low level container logging
        logging:
          driver: "json-file"
          options:
            max-size: "1m"
            max-file: "5"
    
      service_php:
        build:
          context: .
          dockerfile: .docker/services/php/Dockerfile.dev
        ports:
          - "9000:9000"
        command: 'web_server'
        container_name: base_service_php
        volumes:
          - ./app:/var/www/html/public
        env_file:
          - ./.env
        # Low level container logging
        logging:
          driver: "json-file"
          options:
            max-size: "1m"
            max-file: "5"
    

    you also need to update your docker file to be able to handle multiple commands using docker entry points

    Add the below line to your docker file + remove the CMD one

    COPY ./docker-entrypoint.sh /
    RUN chmod a+x /docker-entrypoint.sh
    ENTRYPOINT ["/docker-entrypoint.sh"]
    

    and finally, create the entry point (make sure it hash execute permissions)

    #!/bin/sh -e
    
    case $1 in
    
      web_server)
        YOUR WEB SERVER COMMAND 
      ;;
    
      cron_jobs)
         exec crond -f
      ;;
    
      *)
        exec "$@"
      ;;
    
    esac
    
    exit 0
    

    you can check this link for more info about entrypoints