Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way)

Introduction

I just started learning and practicing Kamal. While I found it’s a joy to finally be able to deploy Docker images on my own machine, there are some challenges. One of the biggest challenges is that it’s unreasonably difficult to…


This content originally appeared on DEV Community and was authored by Kevin Luo

Introduction

I just started learning and practicing Kamal. While I found it's a joy to finally be able to deploy Docker images on my own machine, there are some challenges. One of the biggest challenges is that it's unreasonably difficult to run cron jobs 🥲 On top of that, I like to use the whenever gem to manage cron jobs, which makes it even harder.

I came across a helpful blog post by Alan Morales, which already solves this issue. However, after some research and experiments, I came up with a simpler version, and I'd like to share it here.

Some terms

We know cron is the program that runs routine jobs—like running a script every 5 minutes. cronjobs just means the jobs that will be run by cron. crontab is the command used to edit the cronjobs. (I guess crontab stands for cron table, but I don't have proof for that 😄)

Official Tutorial

The official tutorial suggests running "cron" jobs as a separate server in Kamal. If you check out the tutorial at https://kamal-deploy.org/docs/configuration/cron/, it gives a very concise (but actually clever) example:

bash -c "(env && cat config/crontab) | crontab - && cron -f"

If you follow this exactly, I bet 99% of the time it won’t work for you. Let’s have a close look at this command:

  1. bash -c: starts a new Bash session to execute the commands.
  2. (env && cat config/crontab): env prints all current environment variables. cat config/crontab outputs the contents of the crontab file, which should have cronjob entries like 0 5 * * * /path/to/script.sh.
  3. | crontab -: pipes the combined output into crontab -, which updates the cron jobs.
  4. cron -f: runs cron in the foreground so the Docker container stays alive.

From this, we know we need:

  1. The cron program installed in the Docker image.
  2. An existing cronjobs file to set up with crontab.
  3. Environment variables (env) at the top of the crontab file because cron doesn’t source profile files like .bashrc or .zshrc. Rails commands need variables like PATH, BUNDLE_PATH, RAILS_ENV, etc.
  4. One more thing: cron is designed to run as the root user. Running it as a non-root user often causes "Permission Denied" errors.

Proposed Method

1. Install cron in the Dockerfile

Just like the blog post suggests, you need to have cron installed:

# Install cron
RUN apt-get update -qq && \ 
    apt-get install --no-install-recommends -y cron && \ 
    rm -rf /var/lib/apt/lists /var/cache/apt/archives && \ 
    rm -rf /etc/cron.*/*

2. Modify the cmd

In your deploy.yml, set up the cron server like this:

servers:
  cron:
    hosts:
      - www.xxx.yyy.zzz # your server IP
    cmd: bash -c "bundle exec whenever --update-crontab && (env && crontab -l) | crontab - && cron -f"
    options:
      user: root

Explanation:

  1. bundle exec whenever --update-crontab: updates the crontab using whenever.
  2. (env && crontab -l): prints environment variables and current crontab.
  3. | crontab -: sets the new crontab.
  4. cron -f: runs cron in the foreground.
  5. options.user: root: indicates to use root to run the server

The key part is this single line:

bash -c "bundle exec whenever --update-crontab && (env && crontab -l) | crontab - && cron -f"

3. (Optional) Print cron output to Docker’s stdout

Debugging cron in Docker is hard because you can't see the logs. Here's a simple trick: redirect the cron output to Docker’s stdout. Add this line to the top of your config/schedule.rb:

set :output, { standard: '/proc/1/fd/1', error: '/proc/1/fd/2' }

The mysterious /proc/1/fd/1 and /proc/1/fd/2 point to the Docker container logs. You can then check the cron output with:

kamal app logs -r cron -f

Conclusion

In every stage of my career, I’ve found that running cron jobs on production servers is never easy. Running them in Docker makes it even trickier 😆. I hope this changes in the future, but until then, we just have to figure out our own ways.

References


This content originally appeared on DEV Community and was authored by Kevin Luo


Print Share Comment Cite Upload Translate Updates
APA

Kevin Luo | Sciencx (2025-07-09T02:25:59+00:00) Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way). Retrieved from https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/

MLA
" » Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way)." Kevin Luo | Sciencx - Wednesday July 9, 2025, https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/
HARVARD
Kevin Luo | Sciencx Wednesday July 9, 2025 » Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way)., viewed ,<https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/>
VANCOUVER
Kevin Luo | Sciencx - » Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/
CHICAGO
" » Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way)." Kevin Luo | Sciencx - Accessed . https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/
IEEE
" » Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way)." Kevin Luo | Sciencx [Online]. Available: https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/. [Accessed: ]
rf:citation
» Running Cron Jobs by Kamal with the Whenever Gem (The Simple Way) | Kevin Luo | Sciencx | https://www.scien.cx/2025/07/09/running-cron-jobs-by-kamal-with-the-whenever-gem-the-simple-way/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.