How to run a cron job inside a docker container?

前端 未结 20 1305
無奈伤痛
無奈伤痛 2020-11-22 05:36

I am trying to run a cronjob inside a docker container that invokes a shell script.

Yesterday I have been searching all over the web and stack overflow, but I could

相关标签:
20条回答
  • 2020-11-22 06:15

    If you're using docker for windows, remember that you have to change your line-ending format from CRLF to LF (i.e. from dos to unix) if you intend on importing your crontab file from windows to your ubuntu container. If not, your cron-job won't work. Here's a working example:

    FROM ubuntu:latest
    
    RUN apt-get update && apt-get -y install cron
    RUN apt-get update && apt-get install -y dos2unix
    
    # Add crontab file (from your windows host) to the cron directory
    ADD cron/hello-cron /etc/cron.d/hello-cron
    
    # Change line ending format to LF
    RUN dos2unix /etc/cron.d/hello-cron
    
    # Give execution rights on the cron job
    RUN chmod 0644 /etc/cron.d/hello-cron
    
    # Apply cron job
    RUN crontab /etc/cron.d/hello-cron
    
    # Create the log file to be able to run tail
    RUN touch /var/log/hello-cron.log
    
    # Run the command on container startup
    CMD cron && tail -f /var/log/hello-cron.log
    

    This actually took me hours to figure out, as debugging cron jobs in docker containers is a tedious task. Hope it helps anyone else out there that can't get their code to work!

    0 讨论(0)
  • 2020-11-22 06:15

    When you deploy your container on another host, just note that it won't start any processes automatically. You need to make sure that 'cron' service is running inside your container. In our case, I am using Supervisord with other services to start cron service.

    [program:misc]
    command=/etc/init.d/cron restart
    user=root
    autostart=true
    autorestart=true
    stderr_logfile=/var/log/misc-cron.err.log
    stdout_logfile=/var/log/misc-cron.out.log
    priority=998
    
    0 讨论(0)
  • 2020-11-22 06:15

    this line was the one that helped me run my pre-scheduled task.

    ADD mycron/root /etc/cron.d/root
    
    RUN chmod 0644 /etc/cron.d/root
    
    RUN crontab /etc/cron.d/root
    
    RUN touch /var/log/cron.log
    
    CMD ( cron -f -l 8 & ) && apache2-foreground # <-- run cron
    

    --> My project run inside: FROM php:7.2-apache

    0 讨论(0)
  • 2020-11-22 06:16

    Define the cronjob in a dedicated container which runs the command via docker exec to your service.

    This is higher cohesion and the running script will have access to the environment variables you have defined for your service.

    #docker-compose.yml
    version: "3.3"
    services:
        myservice:
          environment:
            MSG: i'm being cronjobbed, every minute!
          image: alpine
          container_name: myservice
          command: tail -f /dev/null
    
        cronjobber:
         image: docker:edge
         volumes:
          - /var/run/docker.sock:/var/run/docker.sock
         container_name: cronjobber
         command: >
              sh -c "
              echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
              && crond -f"
    
    0 讨论(0)
  • 2020-11-22 06:16

    Setup a cron in parallel to a one-time job

    Create a script file, say run.sh, with the job that is supposed to run periodically.

    #!/bin/bash
    timestamp=`date +%Y/%m/%d-%H:%M:%S`
    echo "System path is $PATH at $timestamp"
    

    Save and exit.

    Use Entrypoint instead of CMD

    f you have multiple jobs to kick in during docker containerization, use the entrypoint file to run them all.

    Entrypoint file is a script file that comes into action when a docker run command is issued. So, all the steps that we want to run can be put in this script file.

    For instance, we have 2 jobs to run:

    Run once job: echo “Docker container has been started”

    Run periodic job: run.sh

    Create entrypoint.sh

    #!/bin/bash
    
    # Start the run once job.
    echo "Docker container has been started"
    
    # Setup a cron schedule
    echo "* * * * * /run.sh >> /var/log/cron.log 2>&1
    # This extra line makes it a valid cron" > scheduler.txt
    
    crontab scheduler.txt
    cron -f
    

    Let’s understand the crontab that has been set up in the file

    * * * * *: Cron schedule; the job must run every minute. You can update the schedule based on your requirement.

    /run.sh: The path to the script file which is to be run periodically

    /var/log/cron.log: The filename to save the output of the scheduled cron job.

    2>&1: The error logs(if any) also will be redirected to the same output file used above.

    Note: Do not forget to add an extra new line, as it makes it a valid cron. Scheduler.txt: the complete cron setup will be redirected to a file.

    Using System/User specific environment variables in cron

    My actual cron job was expecting most of the arguments as the environment variables passed to the docker run command. But, with bash, I was not able to use any of the environment variables that belongs to the system or the docker container.

    Then, this came up as a walkaround to this problem:

    1. Add the following line in the entrypoint.sh
    declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
    
    1. Update the cron setup and specify-
    SHELL=/bin/bash
    BASH_ENV=/container.env
    

    At last, your entrypoint.sh should look like

    #!/bin/bash
    
    # Start the run once job.
    echo "Docker container has been started"
    
    declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
    
    # Setup a cron schedule
    echo "SHELL=/bin/bash
    BASH_ENV=/container.env
    * * * * * /run.sh >> /var/log/cron.log 2>&1
    # This extra line makes it a valid cron" > scheduler.txt
    
    crontab scheduler.txt
    cron -f
    

    Last but not the least: Create a Dockerfile

    FROM ubuntu:16.04
    MAINTAINER Himanshu Gupta
    
    # Install cron
    RUN apt-get update && apt-get install -y cron
    
    # Add files
    ADD run.sh /run.sh
    ADD entrypoint.sh /entrypoint.sh
    
    RUN chmod +x /run.sh /entrypoint.sh
    
    ENTRYPOINT /entrypoint.sh
    

    That’s it. Build and Run the Docker image!

    0 讨论(0)
  • 2020-11-22 06:19

    When running on some trimmed down images that restrict root access, I had to add my user to the sudoers and run as sudo cron

    FROM node:8.6.0
    RUN apt-get update && apt-get install -y cron sudo
    
    COPY crontab /etc/cron.d/my-cron
    RUN chmod 0644 /etc/cron.d/my-cron
    RUN touch /var/log/cron.log
    
    # Allow node user to start cron daemon with sudo
    RUN echo 'node ALL=NOPASSWD: /usr/sbin/cron' >>/etc/sudoers
    
    ENTRYPOINT sudo cron && tail -f /var/log/cron.log

    Maybe that helps someone

    0 讨论(0)
提交回复
热议问题