Skip to content
AgileLogics
6 min read

R in Production: Scheduling, Docker, and CI

Prerequisites: Reproducibility: renv, Git, and projects, Interactive web apps with Shiny

Moving R from your laptop to a place where it runs reliably without you — a nightly report, a model API, a dashboard — involves a few extra practices.

Scripts that run unattended

  • Run with Rscript script.R from the command line or a scheduler.
  • Read configuration from environment variables or a config file (the config package), not hard-coded values.
  • Log what happens (the logger package), and exit with an error status when something fails, so the scheduler notices:
result <- tryCatch(
  run_nightly_report(),
  error = function(e) {
    message("Report failed: ", conditionMessage(e))
    quit(status = 1)
  }
)

Scheduling

  • cron (Linux/macOS) or Task Scheduler (Windows) run scripts on a schedule; the cronR and taskscheduleR packages set them up from R.
  • GitHub Actions can run scheduled R jobs in the cloud.
  • Posit Connect schedules and emails Quarto reports, and hosts Shiny apps and plumber APIs.

Docker

A container bundles R, system libraries, and your packages, so the code runs identically everywhere. The Rocker project provides official R images:

# Dockerfile
FROM rocker/r-ver:4.6.1

WORKDIR /app
COPY renv.lock renv.lock
RUN R -e "install.packages('renv'); renv::restore()"

COPY . .
RUN useradd --create-home app
USER app
CMD ["Rscript", "run_report.R"]
  • Pinning the R version in the image tag and restoring packages from renv.lock makes the environment exactly reproducible.
  • Copying renv.lock before the rest of the code lets Docker cache the slow package installation.

Continuous integration

Run tests and checks automatically on every change with GitHub Actions. The r-lib/actions repository provides ready-made steps:

# .github/workflows/check.yml
name: R-CMD-check
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: r-lib/actions/setup-r@v2
      - uses: r-lib/actions/setup-renv@v2
      - run: Rscript -e 'testthat::test_dir("tests/testthat")'

Monitoring models

A deployed model's accuracy drifts as the world changes. Log predictions, compare them with actual outcomes when they arrive, and retrain on a schedule. The vetiver package (from Posit) versions, deploys, and monitors models built with tidymodels.

Congratulations

You've reached the end of Level 3. Build one of the Advanced Projects, then read What You Should Know Now — and What's Next for where to go from here.