Changelog
Source:NEWS.md
dockerfiler 0.3.0
Breaking changes
- The vendored copy of renv (~30,000 lines under
inst/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. -
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 0.3.0 shell-context hardening above, but the lockfile-fallback path was missed; the bug itself predates 0.3.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 0.3.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=.
dockerfiler 0.2.6
-
dock_from_renv()now auto-configures the generated Dockerfile to fetch Linux binaries from Posit Package Manager whenreposis a single CRAN-keyed PPM URL. Four things happen: the PPM URL is rewritten to include__linux__/$VERSION_CODENAME/(resolved at image build time from/etc/os-release) when it wascranorcran/latest;HTTPUserAgentis set to the strict format PPM requires;renv.config.repos.overrideis set so thatrenv::restore()uses PPM instead of the lockfile’s repo URL; and the RUN is prefixed with. /etc/os-release &&when the line uses$VERSION_CODENAME. User-pinned codenames and snapshot-date URLs (e.g.cran/2024-01-15) are preserved as-is. The user’s PPM scheme and host (so apackagemanager.rstudio.comURL stays on rstudio.com) are preserved on rewrite. Non-PPM repos (including internal mirrors not on the official PPM hosts) and multi-entryreposvectors are left untouched. -
dock_from_renv()no longer installsremoteswhenrenv_version = NULL, sinceremoteswas only needed for theinstall_version()path.
dockerfiler 0.2.5
CRAN release: 2025-05-07
- feat: allow multistage dockerfile creation
- feat: COPY function can now specify a stage to copy from.
- feat: add dedicated cache for
renv::restore - feat: add COMMENT function to add comment in Dockerfile thanks to @jcrodriguez1989
dockerfiler 0.2.4
CRAN release: 2024-08-23
- remove native pipe thanks to @HenningLorenzen-ext-bayer, this enable to use of older R versions
- update
dock_from_renv()test to catch all output lines
dockerfiler 0.2.2
CRAN release: 2023-11-13
fix : create a
use_pakparameters indock_from_renvto setrenv.config.pak.enabled = FALSEinstead ofrenv.config.pak.enabled = TRUEto avoid issues with {pak} duringrenv::restore()feat: use of {memoise} to cache call to
pak::pkg_system_requirementsfix : dont depend anymore to {renv} use an internalised {renv} version (1.0.3)
fix : remove
renv:::lockfileand uselockfile_readinsteadfeat: Added
dock_from_renv(), to create a Dockerfile from a renv.lock file (@JosiahParry, @statnmap)feat: Added
parse_dockerfile(), to Create a Dockerfile object from a Dockerfile file (@JosiahParry)feat: Added
renv_versionparameter todock_from_renvto be able to fix the renv version to use duringrenv::restore()(@campbead)
dockerfiler 0.2.0
CRAN release: 2022-07-06
fix: graceful failing in case no internet
fix: the dedicated
compact_sysreqsfunction allow to deal with ‘complex’ sysreqs, such as chromimum installationfeat: add jammy ubuntu distro in available distro
dockerfiler 0.1.3
CRAN release: 2019-03-19
- Added the
add_after()R6 method - Added
dock_from_desc(), to create a Dockerfile from a DESCRIPTION