<!-- TITLE: Crontab In Docker --> <!-- SUBTITLE: Dockerfile to run crontab tasks --> # Crontab in Docker for Rails This approach allows to run cron tasks of Rails application usually maintained by Whenever gem. Dockerfile with Cron ```Dockerfile FROM ruby:2.4.3-slim-stretch RUN apt-get update -qq && apt-get install --no-install-recommends -y \ build-essential \ patch \ ruby-dev \ zlib1g-dev \ liblzma-dev \ libxml2 \ libxml2-dev \ libpq-dev \ default-libmysqlclient-dev \ imagemagick \ git \ wget \ gnupg2 \ curl \ nodejs-dev \ node-gyp \ libssl1.0-dev \ cron \ && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch"-pgdg main | tee /etc/apt/sources.list.d/pgdg.list \ && apt-get update -qq && apt-get install --no-install-recommends --no-upgrade -y \ postgresql-client-11 \ && rm -rf /var/lib/apt/lists/* RUN curl -fsSLO --compressed "https://nodejs.org/dist/v8.17.0/node-v8.17.0-linux-x64.tar.xz" \ && tar -xJf "node-v8.17.0-linux-x64.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \ && rm "node-v8.17.0-linux-x64.tar.xz" \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && npm install -g yarn WORKDIR /opt/app COPY ./config/entrypoint.sh /usr/bin/entrypoint.sh RUN chmod +x /usr/bin/entrypoint.sh && crontab -l | { cat; echo ""; } | crontab - RUN gem install bundler -v 2.0.1 ADD Gemfile* /opt/app/ RUN bundle install ARG RAILS_ENV ARG ACTION_CABLE_URL COPY . /opt/app RUN yarn install --check-files RUN RAILS_ENV=$RAILS_ENV bundle exec rake assets:precompile EXPOSE 9292 ``` The docker-compose.yml part to start container with cron ```sh version: "3" services: crontab: image: ${PROJECT_HUB}/${PROJECT_NAME}/backend:${IMAGE_TAG} container_name: ${PROJECT_NAME}_crontab restart: on-failure networks: overlay: aliases: - crontab working_dir: /opt/app env_file: - ./.env command: bash -c 'env > /opt/app/cronenv && bundle exec whenever --update-crontab && cron -f' depends_on: - redis - db ``` This file is required to run cron tasks in the same enviroment. We create it on startup. ```sh env > /opt/app/cronenv ``` Setup whenever to generate tasks with following additions: ```sh * * * * * /bin/bash -l -c 'for line in `cat /opt/app/cronenv` ; do export $line ; done && cd /opt/app && RAILS_ENV=production bundle exec rake addons:process_repeat_addons >> /var/log/cron.log 2>&1' ``` The approach is a bit naive, but whenever does not allow to edit command before /bin/bash, otherwise we can do as follows: ```sh * * * * * env - `cat /opt/app/cronenv` /bin/bash -l -c 'cd /opt/app && bundle install && RAILS_ENV=production bundle exec rake addons:process_repeat_addons >> /var/log/cron.log 2>&1' ```