Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repository Purpose
## Repository purpose

This repository provides examples for using and extending Posit's container images. It demonstrates two approaches:
- **bakery/**: Managing images with Posit's [Bakery tool](https://github.com/posit-dev/images-shared/tree/main/posit-bakery) (Jinja2-based templating system)
- **extending/**: Extending Posit's publicly available container images with customer-specific layers

> **Note**: These images are under active development and not yet officially supported by Posit. See [rstudio/rstudio-docker-products](https://github.com/rstudio/rstudio-docker-products) for officially supported images.
> [!NOTE]
> These images are under active development and not yet officially supported by Posit. See [rstudio/rstudio-docker-products](https://github.com/rstudio/rstudio-docker-products) for officially supported images.

## Build Commands
## Build commands

Build an extending example:
```bash
Expand All @@ -19,11 +20,11 @@ docker build -f extending/{example}/Containerfile -t {tag} extending/{example}/

CI runs on pull requests and builds all examples in `extending/` using Docker Buildx.

## Bakery Tool Architecture
## Bakery tool architecture

Bakery uses Jinja2 templates to generate version-specific container build files.

### Directory Structure for Bakery Images
### Directory structure for Bakery images
```
bakery/{example}/
├── bakery.yaml # Repository config (registries, images, versions)
Expand All @@ -38,12 +39,12 @@ bakery/{example}/
└── test/goss.yaml
```

### Bakery Template Variables
### Bakery template variables
- `{{ Image.Version }}` - Current image version string
- `{{ Path.Version }}` - Path to the version directory
- Import macros: `{%- import "apt.j2" as apt -%}`

### bakery.yaml Structure
### bakery.yaml structure
```yaml
repository:
url: "github.com/posit-dev/images-examples"
Expand All @@ -59,17 +60,17 @@ images:
latest: true
```

## Containerfile Conventions
## Containerfile conventions

### Base Image Naming
### Base image naming
- Format: `docker.io/posit/{product}:{version}-{variant}`
- Variants: `-min` (minimal), `-std` (standard), `-ubuntu-22.04-min`
- Examples:
- `posit/workbench:2025.09.0-min`
- `posit/connect:2025.07.0-ubuntu-22.04-min`
- `posit/package-manager:{version}-ubuntu-22.04-min`

### Version Pinning Pattern
### Version pinning pattern
Always declare product versions as ARGs at the top:
```dockerfile
ARG PWB_VERSION="2025.09.0"
Expand Down Expand Up @@ -99,7 +100,7 @@ RUN RUN_UNATTENDED=1 R_VERSION=4.5.1 bash -c "$(curl -fsSL https://rstd.io/r-ins

R installs to `/opt/R/{version}/`.

### Package Installation Patterns
### Package installation patterns

Python packages:
```dockerfile
Expand All @@ -123,13 +124,13 @@ RUN apt-get update -yqq && \
apt-get clean -yqq && rm -rf /var/lib/apt/lists/*
```

### Cleanup Requirements
### Cleanup requirements
- Always clean apt caches: `apt-get clean -yqq && rm -rf /var/lib/apt/lists/*`
- Delete R installer artifacts: `find . -type f -name '[rR]-{version}.*\.(deb|rpm)' -delete`
- Use `--no-cache-dir` with pip
- Use `clean = TRUE` with R `install.packages()`

## Key Resources
## Key resources

- [Posit Public Package Manager](https://p3m.dev/) - Package repositories for R and Python
- [R installer script](https://rstd.io/r-install) - Automated R installation
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Image Examples
# Image examples

> [!IMPORTANT]
> These images are under active development and testing and are not yet supported by Posit.
Expand All @@ -12,18 +12,18 @@
| [bakery](./bakery/) | Examples of managing images with [bakery](https://github.com/posit-dev/images-shared/tree/main/posit-bakery) |
| [extending](./extending/) | Examples of extending Posit Container images |

## Share your Feedback
## Share your feedback

We invite you to join us on [GitHub Discussions](https://github.com/posit-dev/images/discussions) to ask questions and share feedback.

## Issues

If you encounter any issues or have any questions, please [open an issue](https://github.com/posit-dev/images-examples/issues). We appreciate your feedback.

## Code of Conduct
## Code of conduct

We expect all contributors to adhere to the project's [Code of Conduct](CODE_OF_CONDUCT.md) and create a positive and inclusive community.

## License

Posit Container Images and associated tooling are licensed under the [MIT License](LICENSE.md)
Posit Container Images and associated tooling are licensed under the [MIT License](LICENSE.md).
16 changes: 8 additions & 8 deletions bakery/01-basic-image/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Basic Image Example
# Basic image example

This example demonstrates the simplest use case for Bakery: a single [image][Image] with one [version][ImageVersion]. It builds an Ubuntu 24.04 image with basic development tools installed.

Expand All @@ -22,7 +22,7 @@ Bakery commands can also use the `--context PATH` option to specify the path to
└── test/goss.yaml
```

## What This Example Builds
## What this example builds

- **Base**: Ubuntu 24.04
- **Packages**: `build-essential`, `ca-certificates`, `curl`, `git`
Expand All @@ -32,9 +32,9 @@ Bakery commands can also use the `--context PATH` option to specify the path to

This example demonstrates Bakery's usage in its most basic form. It consists of a [`bakery.yaml` file][BakeryConfiguration] that defines the Bakery project configuration and a single image directory. The image directory, `example-image/`, contains a `template/` directory with Jinja2 templates and a version directory, `1.0.0/`, with generated files.

Each time you add a new [version][ImageVersion] to the `bakery.yaml` file, Bakery renders the templates to generate the necessary files for that version. In many cases, the image's version will correlate to the primary software it packages (e.g. a product version, an R version, etc.), but in this example, the version is arbitrary and does not correspond to any software version.
Each time you add a new [version][ImageVersion] to the `bakery.yaml` file, Bakery renders the templates to generate the necessary files for that version. In many cases, the image's version will correlate to the primary software it packages (e.g., a product version, an R version, etc.), but in this example, the version is arbitrary and does not correspond to any software version.

## Creation of this Example
## Creation of this example

Starting a new Bakery project can be done with a couple bootstrapping commands, editing templates, and then adding the first version. The commands below were used to create this example from scratch.

Expand All @@ -51,7 +51,7 @@ bakery create image example-image
bakery create version example-image 1.0.0
```

## Building with Bakery command-line interface (CLI)
## Building with Bakery CLI

Bakery manages the full lifecycle of rendering templates, building images, and running tests.

Expand All @@ -66,7 +66,7 @@ bakery build
bakery run dgoss
```

## Building Directly with Docker
## Building directly with Docker

You can build the image directly using Docker without Bakery. The build context must be the example directory (not the version directory) because the Containerfile references paths relative to it.

Expand All @@ -87,7 +87,7 @@ docker buildx build \

The goss.yaml file uses Go templates to dynamically read the package list and verify each package is installed.

### Running Tests Manually
### Running tests manually

Like building, you can run tests without Bakery. The commands below would be functionally equivalent to running `bakery build` followed by `bakery run dgoss`. Always build and load the image locally, or pull it, before running tests.

Expand Down Expand Up @@ -116,7 +116,7 @@ dgoss run \
ghcr.io/posit-dev/example-image:1.0.0
```

## Template Variables
## Template variables

The Containerfile template uses these Bakery variables:

Expand Down
24 changes: 12 additions & 12 deletions bakery/02-multiple-images-and-versions/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Multiple Images and Versions Example
# Multiple images and versions example

This example demonstrates managing multiple image families with multiple versions each using Bakery. It builds multiple versions of two base images for different OS families, Ubuntu and Rocky Linux, showcasing Bakery's ability to handle diverse container configurations in a single project.

Expand Down Expand Up @@ -39,7 +39,7 @@ Bakery commands can also use the `--context PATH` option to specify the path to
└── test/goss.yaml
```

## What This Example Builds
## What this example builds

**ubuntu-base**:
- **Base**: Ubuntu 24.04 (noble) and Ubuntu 22.04 (jammy)
Expand All @@ -55,21 +55,21 @@ Bakery commands can also use the `--context PATH` option to specify the path to

This example demonstrates several key Bakery features:

### Multiple Image Families
### Multiple image families

A single Bakery project can manage multiple distinct images. The [`bakery.yaml` file][BakeryConfiguration] defines two images (`ubuntu-base` and `rocky-base`), each with their own templates and version directories. This allows related images to share project configuration while maintaining separate build definitions.

While this example treats base OSes as a primary component, Bakery can also define them as a secondary dimension as demonstrated in [Example 4](../04-image-oses).

### Version Matrices
### Version matrices

Each image can have multiple versions. This example produces 4 container images total (2 images × 2 versions each):
- `ghcr.io/posit-dev/ubuntu-base:24.04`
- `ghcr.io/posit-dev/ubuntu-base:22.04`
- `ghcr.io/posit-dev/rocky-base:9`
- `ghcr.io/posit-dev/rocky-base:8`

### Subpath for Custom Directory Names
### Subpath for custom directory names

Ubuntu versions use codenames (`noble`, `jammy`) instead of version numbers for directory names. The `subpath` field in `bakery.yaml` enables this:

Expand All @@ -83,7 +83,7 @@ versions:

The `{{ Image.Version }}` variable still resolves to the version name (e.g., "24.04"), while `{{ Path.Version }}` uses the subpath (e.g., "ubuntu-base/noble").

### Package Manager Abstraction
### Package manager abstraction

Bakery provides macros for different package managers. Ubuntu uses `apt.j2` while Rocky Linux uses `dnf.j2`:

Expand All @@ -101,7 +101,7 @@ Bakery provides macros for different package managers. Ubuntu uses `apt.j2` whil

These macros abstract away the differences between package managers, handling cache updates, installation, and cleanup automatically.

### Latest Tag Management
### Latest tag management

The `latest: true` flag in `bakery.yaml` controls which version receives the `:latest` tag:

Expand All @@ -114,7 +114,7 @@ images:
- name: "22.04" # Tagged only as ubuntu-base:22.04
```

## Creation of this Example
## Creation of this example

The commands below were used to create this example from scratch.

Expand Down Expand Up @@ -154,7 +154,7 @@ bakery build
bakery run dgoss
```

## Building Directly with Docker
## Building directly with Docker

You can build images directly using Docker without Bakery. The build context must be the example directory (not the version directory) because the Containerfile references paths relative to it.

Expand Down Expand Up @@ -198,7 +198,7 @@ docker buildx bake --file docker-bake.json --load

The goss.yaml files use Go templates to dynamically read the package list and verify each package is installed.

### Running Tests Manually
### Running tests manually

You can run tests without Bakery. The commands below would be functionally equivalent to running `bakery build` followed by `bakery run dgoss`. Always build and load the image locally, or pull it, before running tests.

Expand Down Expand Up @@ -248,7 +248,7 @@ dgoss run \
ghcr.io/posit-dev/rocky-base:9
```

## Template Variables
## Template variables

The Containerfile templates use these Bakery variables:

Expand All @@ -261,7 +261,7 @@ Note that when using `subpath`, `Image.Version` contains the version name while

See [TEMPLATING.md](https://github.com/posit-dev/images-shared/blob/main/posit-bakery/TEMPLATING.md) for a list of available variables and macros.

## Bakery Macros
## Bakery macros

This example uses Bakery's package manager macros to abstract differences between distributions:

Expand Down
Loading