Skip to content

Releases: ThinkR-open/dockerfiler

dockerfiler 1.0.0

13 May 09:19
4c166e2

Choose a tag to compare

First major release, now on CRAN.

install.packages("dockerfiler")

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 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 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 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 1.0.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 =.

Full changelog: h...

Read more

v0.2.5

21 May 08:58
db5ddac

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.2.3...v0.2.5

dockerfiler 0.2.3

19 Jul 10:20
44919b7

Choose a tag to compare

  • remove sysreqs.r-hub.io to use {pak} instead for system requirement detection
  • move from pak::pkg_system_requirements to pak::pkg_sysreqs() thanks to @B0ydT
  • dock_from_renv allow to specify user to use in Dockerfile
  • the dependencies parameter in dock_from_renv if set to TRUE will install required dependencies plus optional and development dependencies. defaut is NA only required (hard) dependencies,
  • Set the minimum version of the {pak} package to 0.6.0.
  • Parameterize the sysreqs_platform used to find system dependencies in pkg_sysreqs (only debian/ubuntu based images are supported)

dockerfiler 0.2.2

13 Nov 14:49

Choose a tag to compare

  • 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.1

18 Jan 08:48

Choose a tag to compare

  • fix: graceful failing in case no internet

  • feat: Added dock_from_renv(), to create a Dockerfile from a renv.lock file (@JosiahParry, @statnmap)