Skip to contents

dockerfiler 0.3.0

Breaking changes

  • The vendored copy of renv (~30,000 lines under inst/vendor/) is removed. Lockfiles are now parsed with jsonlite::read_json() (already in Imports). The exported dockerfiler::renv symbol is removed: it was a public-API surface only because the vendor pattern required it. The fallback renv_version value, when both the user argument is missing and the lockfile does not pin renv, is now NULL (install the latest renv from the configured repos), aligned with the existing renv_version = NULL behaviour. Closes #94.
  • dock_from_renv() now defaults to running the runtime container as the rstudio user (previously root). The generated Dockerfile gains a defensive RUN id -u rstudio || useradd -m -d /home/rstudio -s /bin/bash rstudio early so the user is created if the FROM image does not already ship one (no-op on rocker/* images, real useradd on r-base, ubuntu:*, debian:*). The renv cache is auto-derived to /home/<user>/.cache/R/renv and chowned to <user> before the USER directive drops privilege; the USER directive itself is emitted right before the renv::restore() cache-mount RUN, so every step that needs root (apt-get, R installs) still runs as root. Pass user = NULL to opt out and keep the previous root behaviour. debian/ubuntu only; for alpine-based images you must pass user = NULL and create the user yourself. Closes #100.
  • dock_from_renv() default FROM flips from "rocker/r-base" (amd64-only) to "rocker/r-ver" (multi-arch: linux/amd64 + linux/arm64), and the R version from the renv.lock file 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 legacy FROM = "rocker/r-base" to opt out. dock_from_desc()’s default FROM was already rocker/r-ver:<R version> and is unchanged. Closes #47.
  • dock_from_renv() and dock_from_desc() default repos flips 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, and p3m.dev. Pass the legacy repos = c(CRAN = "https://cran.rstudio.com/") to opt out. Closes #57.

Security

  • dock_from_desc() and dock_from_renv() now validate every user-supplied parameter that flows into a Dockerfile shell context (FROM, AS, repos values and names, extra_sysreqs, renv_version, renv_paths_cache, lockfile basename, use_pak, strict_install, plus r_version read 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 at docker build time. 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(): the renv package version resolved from the lockfile (lock$Packages$renv$Version) was interpolated raw into the generated R -e 'remotes::install_version("renv", version = "<x>")' line without passing through .validate_renv_version(). A crafted renv.lock could break out of the inner R string and execute arbitrary code as root at docker build time. The user-supplied renv_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 whose R$Version carried an embedded newline would pass validation and then emit a two-line FROM directive. Not exploitable for command injection, but it could silently break docker build.
  • Fixed a long-standing code-injection path in dock_from_desc(): package names read from the DESCRIPTION were interpolated into generated Dockerfile directives without validation. read.dcf() and desc::desc_get_deps() both join DCF continuation lines with \n, so a crafted Package: field, or a crafted Imports: / Depends: / Suggests: / LinkingTo: entry, could carry a continuation line that injects an extra Dockerfile directive (e.g. a RUN) executing as root at docker build time – the Package: field via the COPY <pkg>_*.tar.gz /app.tar.gz line and the tar.gz-cleanup glob on the build_from_source = FALSE path, and the dependency names via the remotes::install_version("<name>", ...) install RUNs on the default build_from_source = TRUE path. 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 the dock_from_renv() fix above.

New features

  • dock$ARG() and the internal add_arg() helper gain a default parameter to emit ARG <name>=<default> instead of ARG <name>. Closes #8.
  • dock_from_desc() and dock_from_renv() gain a github_pat parameter (default "none") controlling how a GitHub PAT is provided to remotes::install_github() / remotes::install_local() / renv::restore() for private dependency repositories. Set to "build_arg" to emit ARG GITHUB_PAT + ENV propagation (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 a renv_paths_cache parameter that controls the RENV_PATHS_CACHE build-arg default, the propagated ENV value, and the cache mount target. When NULL (the default), the path is auto-derived from user: /root/.cache/R/renv for user = NULL, and /home/<user>/.cache/R/renv otherwise. 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 a strict_install parameter (default TRUE). When TRUE, every install RUN in the generated Dockerfile is prefixed with options(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. Pass strict_install = FALSE if 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 called gsub(" [2,]", " ", code) (a typo for {2,}) which deleted any digit 2 or comma preceded by a space: r(c(1, 2, 3)) returned R -e 'c(1, , 3)'. The replacement approach (gsub("[ ]{2,}", " ", code)) still collapsed runs of spaces inside string literals (r(cat("a b")) would emit R -e 'cat("a b")'). The fix uses trimws() on each deparse() line then paste(collapse = " "): only the line-wrap indentation added by deparse() is removed, internal whitespace is preserved. Closes #95.
  • r() now wraps the deparsed R expression with shQuote(., 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 emit R -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 of pkgbuild::build(). missing() only reports unsupplied function arguments, so the branch was unreachable; the success path always ran when build() returned. The branch is removed; failures of pkgbuild::build() propagate normally via stop(). Closes #98.
  • dock_from_desc(): fixed two length(x > 0) typos in the dependency handling (the intent was length(x) > 0); the conditions now behave as documented.
  • The <pkg>_*.tar.gz cleanup glob in dock_from_desc(build_from_source = FALSE) is now built with glob2rx(), 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 @export in dockerignore.R; the codegen now uses the new dock$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 when repos is 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 was cran or cran/latest; HTTPUserAgent is set to the strict format PPM requires; renv.config.repos.override is set so that renv::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 a packagemanager.rstudio.com URL stays on rstudio.com) are preserved on rewrite. Non-PPM repos (including internal mirrors not on the official PPM hosts) and multi-entry repos vectors are left untouched.
  • dock_from_renv() no longer installs remotes when renv_version = NULL, since remotes was only needed for the install_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

dockerfiler 0.2.2

CRAN release: 2023-11-13

  • fix : create a use_pak parameters in dock_from_renv to set renv.config.pak.enabled = FALSE instead of renv.config.pak.enabled = TRUE to avoid issues with {pak} during renv::restore()

  • feat: use of {memoise} to cache call to pak::pkg_system_requirements

  • fix : dont depend anymore to {renv} use an internalised {renv} version (1.0.3)

  • fix : remove renv:::lockfile and use lockfile_read instead

  • feat: 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_version parameter to dock_from_renv to be able to fix the renv version to use during renv::restore() (@campbead)

dockerfiler 0.2.0

CRAN release: 2022-07-06

  • fix: graceful failing in case no internet

  • fix: the dedicated compact_sysreqs function allow to deal with ‘complex’ sysreqs, such as chromimum installation

  • feat: add jammy ubuntu distro in available distro

dockerfiler 0.1.4

CRAN release: 2021-09-03

dockerfiler 0.1.3.9000

  • Corrected bug in rthis()

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