Easy Dockerfile Creation from R
Overview
Build a Dockerfile straight from your R session. 'dockerfiler' allows you to create step by step a Dockerfile, and provide convenient tools to wrap R code inside this Dockerfile.
First major release. The version is bumped to 1.0.0 to signal API
maturity after a stabilisation cycle that overhauled the
input-validation surface, hardened the codegen against renv.lock /
DESCRIPTION injection, removed the vendored copy of {renv}, and
flipped the high-level generators' defaults to multi-arch
rocker/r-ver + binary packages from Posit Public Package Manager.
See below.
Breaking changes
- The vendored copy of
{renv}(~30,000 lines underinst/vendor/) is removed. Lockfiles are now parsed withjsonlite::read_json()(already in Imports). The exporteddockerfiler::renvsymbol is removed: it was a public-API surface only because the vendor pattern required it. The fallbackrenv_versionvalue, when both the user argument is missing and the lockfile does not pin renv, is nowNULL(install the latest renv from the configured repos), aligned with the existingrenv_version = NULLbehaviour. Closes #94.
Show all changes in 1.0.0Hide the rest of the changes in 1.0.0
dock_from_renv()now defaults to running the runtime container as therstudiouser (previously root). The generated Dockerfile gains a defensiveRUN id -u rstudio || useradd -m -d /home/rstudio -s /bin/bash rstudioearly so the user is created if the FROM image does not already ship one (no-op on rocker/* images, realuseraddonr-base,ubuntu:*,debian:*). The renv cache is auto-derived to/home/<user>/.cache/R/renvand chowned to<user>before theUSERdirective drops privilege; theUSERdirective itself is emitted right before therenv::restore()cache-mount RUN, so every step that needs root (apt-get, R installs) still runs as root. Passuser = NULLto opt out and keep the previous root behaviour. debian/ubuntu only; for alpine-based images you must passuser = NULLand create the user yourself. Closes #100.dock_from_renv()defaultFROMflips from"rocker/r-base"(amd64-only) to"rocker/r-ver"(multi-arch: linux/amd64 + linux/arm64), and the R version from therenv.lockfile is now appended at codegen time (e.g.rocker/r-ver:4.5.0). Apple Silicon and ARM Linux hosts (Ampere, AWS Graviton) now build natively without Rosetta. Pass the legacyFROM = "rocker/r-base"to opt out.dock_from_desc()'s defaultFROMwas alreadyrocker/r-ver:<R version>and is unchanged. Closes #47.dock_from_renv()anddock_from_desc()defaultreposflips from"https://cran.rstudio.com/"(source-only CRAN mirror) to"https://p3m.dev/cran/latest"(Posit Public Package Manager), with automatic rewrite to the__linux__/$VERSION_CODENAME/shape at codegen time so the build pulls pre-compiled Linux binaries instead of compiling from source. Build time on packages with C/C++ deps drops from minutes to seconds. The PPM rewrite logic now matches all three Posit-managed PPM hosts:packagemanager.posit.co,packagemanager.rstudio.com, andp3m.dev. Pass the legacyrepos = c(CRAN = "https://cran.rstudio.com/")to opt out. Closes #57.
Security
dock_from_desc()anddock_from_renv()now validate every user-supplied parameter that flows into a Dockerfile shell context (FROM,AS,reposvalues and names,extra_sysreqs,renv_version,renv_paths_cache,lockfilebasename,use_pak,strict_install, plusr_versionread from the lockfile). Inputs that contain shell metacharacters, newlines, or do not match the documented format raise an explicit error at function entry, rather than silently producing a malformed Dockerfile or one that executes attacker-controlled commands atdocker buildtime. This closes the post-#106 audit follow-up for all five sites surfaced by Copilot review.- Fixed a long-standing code-injection path in
dock_from_renv(): therenvpackage version resolved from the lockfile (lock$Packages$renv$Version) was interpolated raw into the generatedR -e 'remotes::install_version("renv", version = "<x>")'line without passing through.validate_renv_version(). A craftedrenv.lockcould break out of the inner R string and execute arbitrary code as root atdocker buildtime. The user-suppliedrenv_version=argument has been validated since the 1.0.0 shell-context hardening above, but the lockfile-fallback path was missed; the bug itself predates 1.0.0 (it existed while the vendored{renv}parser was in use). The validator is now applied to the resolved value whatever its source. Found by an internal security audit before release. - Tightened the
.validate_r_version()"X.Y.Z Patched" branch to require a single literal space (it previously used\s, which in R also matches a newline or tab): a lockfile whoseR$Versioncarried an embedded newline would pass validation and then emit a two-lineFROMdirective. Not exploitable for command injection, but it could silently breakdocker build. - Fixed a long-standing code-injection path in
dock_from_desc(): package names read from theDESCRIPTIONwere interpolated into generated Dockerfile directives without validation.read.dcf()anddesc::desc_get_deps()both join DCF continuation lines with\n, so a craftedPackage:field, or a craftedImports:/Depends:/Suggests:/LinkingTo:entry, could carry a continuation line that injects an extra Dockerfile directive (e.g. aRUN) executing as root atdocker buildtime -- thePackage:field via theCOPY <pkg>_*.tar.gz /app.tar.gzline and the tar.gz-cleanup glob on thebuild_from_source = FALSEpath, and the dependency names via theremotes::install_version("<name>", ...)install RUNs on the defaultbuild_from_source = TRUEpath. Both the package name and every dependency-field name are now validated against the CRAN package-name grammar at function entry. The bug predates 1.0.0. Found by the same internal security audit as thedock_from_renv()fix above.
New features
dock$ARG()and the internaladd_arg()helper gain adefaultparameter to emitARG <name>=<default>instead ofARG <name>. Closes #8.dock_from_desc()anddock_from_renv()gain agithub_patparameter (default"none") controlling how a GitHub PAT is provided toremotes::install_github()/remotes::install_local()/renv::restore()for private dependency repositories. Set to"build_arg"to emitARG GITHUB_PAT+ENVpropagation (passed via--build-arg GITHUB_PAT=$GITHUB_PAT), or"secret"to use BuildKit secret mounts (the PAT is never persisted in image metadata; recommended for published images). Closes #18.dock_from_renv()gains arenv_paths_cacheparameter that controls theRENV_PATHS_CACHEbuild-arg default, the propagatedENVvalue, and the cache mount target. WhenNULL(the default), the path is auto-derived fromuser:/root/.cache/R/renvforuser = NULL, and/home/<user>/.cache/R/renvotherwise. Users can override the renv cache location at image build time with--build-arg RENV_PATHS_CACHE=...without regenerating the Dockerfile.dock_from_desc()gains astrict_installparameter (defaultTRUE). WhenTRUE, every install RUN in the generated Dockerfile is prefixed withoptions(warn = 2);so any R warning during install (missing CRAN package, partial download, archived package, 404 on a remote) becomes a hard error and aborts the docker build. This is a behaviour change for users regenerating their Dockerfile: install RUNs now refuse to silently swallow warnings. Passstrict_install = FALSEif your build environment routinely emits benign warnings (locale defaulting, NTP time-verification, ABI-version notices) that you do not want to fail the build. Closes #9.
Bug fixes
r()no longer silently rewrites user code. The previous implementation calledgsub(" [2,]", " ", code)(a typo for{2,}) which deleted any digit2or comma preceded by a space:r(c(1, 2, 3))returnedR -e 'c(1, , 3)'. The replacement approach (gsub("[ ]{2,}", " ", code)) still collapsed runs of spaces inside string literals (r(cat("a b"))would emitR -e 'cat("a b")'). The fix usestrimws()on eachdeparse()line thenpaste(collapse = " "): only the line-wrap indentation added bydeparse()is removed, internal whitespace is preserved. Closes #95.r()now wraps the deparsed R expression withshQuote(., type = "sh")instead of inlining it inside a hand-rolled single-quoted shell string. Apostrophes inside string literals no longer break the emitted command:r(message("don't"))used to emitR -e 'message("don't")', which the shell refuses to parse (unterminated quoted string). The new wrapping is shell-safe by construction.dock_from_desc(build_from_source = FALSE)no longer carries a dead-code branch (if (missing(out))) on the locally-assigned result ofpkgbuild::build().missing()only reports unsupplied function arguments, so the branch was unreachable; the success path always ran whenbuild()returned. The branch is removed; failures ofpkgbuild::build()propagate normally viastop(). Closes #98.dock_from_desc(): fixed twolength(x > 0)typos in the dependency handling (the intent waslength(x) > 0); the conditions now behave as documented.- The
<pkg>_*.tar.gzcleanup glob indock_from_desc(build_from_source = FALSE)is now built withglob2rx(), so a dot in a package name (e.g.R.utils) is matched literally and a sibling package's tarball is no longer swept up. - Internal tidy-ups with no user-visible effect: dropped a duplicate
@exportindockerignore.R; the codegen now uses the newdock$ARG(name, default = ...)form instead of inlining the=.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-07-05
- ERROR12 OK, 1 ERROR2026-07-04
- OK13 OK2026-05-14
Show 2 earlier changesHide 2 earlier changes
- ERROR11 OK, 1 ERROR2026-04-25
- OK14 OK2026-03-10
Documentation
- Help pages
- 9 (1 internal)includes a package overview page
- Examples that run
- 50%4 run in a plain check · 4 never run
- Exported functions with examples
- 100%
- Documented parameters
- 96%
- Return-value docs
- 88%
- Help pages citing references
- 0%
Downloads
Repository
- PRs merged (all time)
- 88%
- Median days to close, 50 most recently updated closed issues
- 418
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
Commit identities over time
13 development-tooling and community-health practices detected across 8 families in the upstream repository
Checks run against github.com/thinkr-open/dockerfiler on 2026-10-25.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-15 · The repository has a site deploy workflow
Show all practicesHide 4 practices
This repository shows signs of AI coding tools.
- GitHub Copilotfirst seen 2026-09-15Pull request: opened by its own accountCommits: 2 by its own account
Dependencies
Installing dockerfiler adds 42 packages (21 with compiled code, 14 MB of source tarballs). Heaviest: pak 3.8 MB, fs 1.4 MB, openssl 1.1 MB.
Code & Tests
People & History
Pick two releases to compare their code metrics.
- 1.0.0Latest
- RR 4.6.0 released · 2026-04-24
- 0.2.52025-05-07 · diff ↗
- RR 4.5.0 released · 2025-04-11
- 0.2.42024-08-23 · diff ↗
- 0.2.32024-07-09 · diff ↗
- RR 4.4.0 released · 2024-04-24
- 0.2.2
- RR 4.3.0 released · 2023-04-21
- 0.2.12023-01-18 · diff ↗
- 0.2.0
- RR 4.2.0 released · 2022-04-22
- 0.1.4
- RR 4.1.0 released · 2021-05-18
- RR 4.0.0 released · 2020-04-24
- RR 3.6.0 released · 2019-04-26
Package metadata
- First published
- 2018-03-01
- Total releases
- 11 / 8 yrs
- License
- MIT + file LICENSE OSI
- Download size
- 66 KB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("dockerfiler")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-26, which the citation names so these numbers can be found later. More on citing and the projects behind them.