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.Rfrom 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
cronRandtaskscheduleRpackages 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.lockmakes the environment exactly reproducible. - Copying
renv.lockbefore 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.