containr 0.2.0
Breaking changes
r_mode = "tidystudio"has been removed. Renamed to"verse", matching the Rocker project’s own name for the underlying image (rocker/verse) –"studio"was misleading, since RStudio Server is already present via"tidyverse"two modes earlier, and nothing in the old name hinted at the TeX Live installation that’s the actual differentiator. No deprecation alias; regenerate any Dockerfile built withr_mode = "tidystudio"usingr_mode = "verse"instead.The
toolargument (a single tool name orNULLfor auto-detect) onbuild_image(),push_image(), andlist_images()is replaced bytool_preference, a non-empty character vector tried in order. Defaults toc("podman", "docker"), matching today’s default behavior. A length-1 vector (e.g.tool_preference = "docker") behaves like the oldtool = "docker"; a longer vector lets you set a custom auto-detect order, e.g.tool_preference = c("docker", "podman").tool = NULLhad no direct equivalent kept – passingNULLtotool_preferencenow errors, since the empty/auto-detect case is expressed by supplying more than one candidate instead.push_image()‘snetidargument is renamed tonamespace.netidonly ever made sense for the default"registry.doit.wisc.edu"registry – the same argument, and the same position in the assembled{registry}/{namespace}/{project}:{tag}path, is a GitHub username or organization forghcr.io, or a Quay namespace forquay.io.namespaceis the term those registries’ own documentation uses for this segment, not a namecontainrinvented. No alias kept; updatenetid = ...calls tonamespace = ....
New features
Two new
r_modevalues ongenerate_dockerfile():"shiny_server"(rocker/shiny) for serving Shiny apps, and"rstudio_shiny"(rocker/rstudiowith Shiny Server layered on top via Rocker’s owninstall_shiny_server.sh) for RStudio Server and Shiny Server in the same image. Both require R >= 4.0.0 and error informatively otherwise –/rocker_scripts/(which the Shiny Server install depends on) only exists in images built from therocker-versioned2project, which covers R >= 4.0.0; older tags on the same Docker Hub repositories predate that entirely.EXPOSEnow supports more than one port on a single line forrstudio_shiny, which exposes both8787and3838.data_file,code_file, andmisc_fileare copied to/srv/shiny-server/for these two modes, matching Shiny Server’s own default app directory – the four existing modes are unaffected,COPYdestinations for those stay/home/exactly as before.expose_portremains an override for"rstudio"only; the two new modes expose fixed port(s) and ignore it, with a warning if supplied.push_image()now works against any OCI-compliant registry, not just the defaultregistry.doit.wisc.edu– tested againstghcr.ioandquay.io. Login-check guidance (both the pre-pushcommentsmessage and the not-logged-in error) is registry-aware: the default registry keeps its existing specific PAT-creation instructions, while any other registry gets generic guidance pointing at that registry’s own documentation instead of DoIT-specific instructions that would be wrong for it.containrnow ships a ready-to-use GitHub Actions template atinst/templates/build-and-push.yaml, for building and pushing your own project’s image from CI rather than locally. Callsbuild_image()/push_image()directly (the same functions you’d run yourself, not a hand-written shell equivalent) on a GitHub-hosted runner, which is nativelyx86_64– a direct fix, not a workaround, for QEMU emulation issues buildinglinux/amd64images locally on Apple Silicon. SeeREADME.md’s “Building in CI” section.
Bug fixes
- Fixed a bug where
push_image()’s pre-push login check always failed under Docker regardless of whether the user was actually logged in.<tool> login --get-login <registry>is a Podman-only flag; running it under Docker always exits with a usage error (125), which is whycheck_login = FALSEwas previously necessary as a Docker workaround. Podman keeps its native--get-logincheck; Docker (and, permissively, any othertool_preferencevalue) now checks~/.docker/config.jsondirectly for a cached credential, the same approach most CI tooling uses since Docker itself has no query subcommand for this. This is a best-effort local check either way – it confirms a credential exists, not that it’s still valid; an expired token can still fail at push time.
Internal changes
The three previously-independent, hand-maintained mappings of
r_modeto image name (generate_dockerfile()), Docker Hub repo (.get_r_ver_tags()), and valid-values list (.r_ver_exists()) are now a single shared registry (.r_mode_registry). No user-facing effect beyond thetidystudioremoval and the two new modes above.tool_preferenceis not validated against a fixed list of tool names – any string on the system’s PATH that responds to<tool> infois accepted. This is intentional:tool_preferenceshould not need a companion validation update every time a new container tool gains support (Apptainer support is planned for a future release). Structural validation still applies –tool_preferencemust be a non-empty character vector with no missing values. Error messages for an unrecognized tool that’s installed but not responding fall back to generic guidance rather than Docker- or Podman-specific instructions that would be wrong for a different tool;dockerandpodmankeep their existing specific guidance.Removed a redundant internal check:
build_image(),push_image(), andlist_images()each called.check_tool_responsive()immediately after.resolve_tool(), which already guarantees the resolved tool is responsive. No user-facing behavior change.Added integration tests (
CONTAINR_INTEGRATION_TESTS=true) forbuild_image()andpush_image(), backfilling the two that were previously only covered at the argument-validation and command- construction layers.push_image()’s integration test additionally requiresCONTAINR_TEST_NAMESPACEandCONTAINR_TEST_PROJECTto be set, so it never pushes a test image to an unintended destination. These now run automatically in CI on every push/PR touching the relevant files, via a newcontainer-integration-tests.yamlGitHub Actions workflow.
containr 0.1.3.9000
New functions
build_image()builds a container image from aDockerfileusing eitherpodmanordocker. Auto-detects which tool is available, preferringpodman. Newplatformargument defaults to"linux/amd64"for HPC/HTC cluster compatibility. When the target platform differs from the host architecture (e.g. buildinglinux/amd64on Apple Silicon), the function automatically usesdocker buildx buildwith--loadfor Docker, or passes--platformdirectly for Podman. A warning is emitted for cross-platform builds to alert the user about potential QEMU emulation issues. Supportsdry_run = TRUEto preview the build command without executing it.verboseandcommentsfollow the same contract asgenerate_dockerfile().push_image()tags a locally built container image with a full registry path and pushes it to a container registry in a single call, handling both thepodman tagandpodman pushsteps internally. Arguments:image_id,netid,project,tag(defaults to"latest"),registry(defaults to"registry.doit.wisc.edu"). Supports login verification,dry_run = TRUE, and guided output viaverboseandcomments.list_images()returns a data frame of container images in the local image store, as reported bypodman image lsordocker image ls. Useful for finding the image ID to pass topush_image()after building an image withbuild_image(). Prints the data frame to the console and returns it invisibly.Two new internal helpers shared by
build_image(),push_image(), andlist_images():.resolve_tool()auto-detectspodmanordockeron the PATH, and.check_tool_responsive()verifies the daemon is running before attempting any build, push, or list operation.
Changes to generate_dockerfile()
Breaking change:
COPYinstructions generated bydata_file,code_file, andmisc_filenow preserve the local directory structure inside the container under/home/. Previously, all files were flattened into/home/data/or/home/regardless of their source path. For example,data_file = "data-raw/sample.csv"now producesCOPY data-raw/sample.csv /home/data-raw/sample.csvinstead ofCOPY data-raw/sample.csv /home/data/sample.csv. This means R scripts inside the container can use the same relative paths they use locally.Breaking change:
COPYsource paths are now always written as relative to the build context (the current working directory). Previously, absolute paths could leak into the Dockerfile if.validate_file_arg()normalized them, causingpodman buildto fail with “no such file or directory.”generate_dockerfile()refactored:r_modevalidated before file and network operations,dplyrdependency removed,expose_portnow warns whenr_modeis not"rstudio", build loop simplified,invisible(NULL)added to return value.generate_dockerfile()now requires anrenv.lockfile in the current working directory. Errors informatively if none is found, with instructions to runrenv::snapshot().New
auto_syslibsargument (defaultTRUE) readsrenv.lock, queries the Posit Package Manager sysreqs database viaremotes::system_requirements(), and automatically includes the system libraries required by all packages in the lock file. Warns and continues without auto-detection if the lookup fails.New
install_syslibsargument (defaultNULL) accepts a character vector of additionalaptpackage names to install on top of the auto-detected set, e.g.install_syslibs = c("libuv1-dev", "libwebp-dev").curlis now always installed as a baseline system package regardless ofauto_syslibsorinstall_syslibs. It is required byrenvfor package downloads inside the container.Breaking change: the hardcoded system library list (
cmake,libcurl4-openssl-dev,libssl-dev, etc.) has been removed. Libraries are now determined entirely byauto_syslibsandinstall_syslibs. The oldinstall_syslibs = TRUEargument no longer works – pass a character vector of library names instead.generate_dockerfile()now callsrenv::status()defensively and warns if the lock file appears to be out of sync with the project library.A success message now reports the path where the
Dockerfilewas written whenverbose = TRUE.
Tests and documentation
- Added
tests/testthat/test-generate-dockerfile-content.Rcovering Dockerfile output content for all arguments. - Updated tests to expect directory-preserving
COPYdestinations instead of the old flattened/home/data/pattern. - Added lifecycle and Codecov badges.
- Updated hex sticker and favicon.
- Added tests for
build_image()platformparameter: invalid platform validation,--platformflag inclusion/omission,docker buildxvsdocker buildselection,--loadflag for cross-arch Docker builds, cross-compilation warning, and same-architecture no-warning behavior. -
.validate_file_arg()now returns paths relative to the working directory instead of absolute paths. Files outside the build context (including files on a different drive on Windows) produce an informative error. This fixes cross-drive build failures on Windows CI wherefs::path_rel()could not compute a relative path
Dependency changes
-
httr2added toImports. Used by.get_r_ver_tags()for Docker Hub API calls. -
httrremoved fromImports. All HTTP calls now usehttr2. -
remotesadded toImports. Used by.fetch_sysreqs()to query system library requirements. -
jsonliteadded toImports. Used by.read_renv_packages()to parserenv.lock. -
dplyrremoved fromImports. Ther_modelookup ingenerate_dockerfile()now uses a named vector instead ofdplyr::case_when().
Internal changes
-
.get_r_ver_tags()migrated fromhttrtohttr2. - New internal helpers
.read_renv_packages()and.fetch_sysreqs()added inR/sysreqs-helpers.R. - New internal helpers
.resolve_tool()and.check_tool_responsive()added inR/container-helpers.R.
containr 0.1.3
CRAN release: 2026-04-26
Changes
- Internal helpers renamed with a dot prefix:
get_r_ver_tags()->.get_r_ver_tags(),r_ver_exists()->.r_ver_exists(), andvalidate_file_arg()->.validate_file_arg(). These are not user-facing but the change enforces the package convention for internal functions. -
tidystudioadded as a validr_modeingenerate_dockerfile(),.get_r_ver_tags(), and.r_ver_exists(). Maps torocker/verse.
Bug fixes
-
generate_dockerfile(): replacedstop()andprint()/Sys.sleep()calls withcli::cli_abort()andcli::cli_inform()throughout for consistent, styled error and progress messages. -
generate_dockerfile(): fixedcommentscondition for Quarto block fromquarto_install_line == TRUEtoinstall_quarto. -
generate_dockerfile(): fixedcommentsconditions forcode_fileandmisc_fileblocks to check the correct variables. -
generate_dockerfile(): RStudio run instructions split into two cleaner comment lines. -
.get_r_ver_tags(): replacedstopifnot()withcli::cli_abort()andmessage()withcli::cli_inform(). Removed barereturn()from final list expression. -
.r_ver_exists(): replacedstop()withcli::cli_abort()andmessage()withcli::cli_inform(). -
.validate_file_arg(): replacedstop()withcli::cli_abort().
containr 0.1.2
CRAN release: 2026-04-07
- Added
inst/CITATIONwith DOI for proper academic citation viacitation("containr") - Added
inst/WORDLISTfor spell check consistency - Added
Language: en-UStoDESCRIPTION - Improved documentation and README
- Added rhub v2 GitHub Actions workflow for cross-platform checks
