Custom Content Images

Creating Custom Images for Content Execution

Sometimes it is necessary to customize the image that is used to execute content in a Kubernetes environment. This can be necessary when one of your R or Python dependencies requires an external OS dependency on the underlying host, like GDAL. In this example we build a new container image with GDAL available for use by our R or Python content. We then update our Posit Connect installation to use the new content image.

Note

Posit provides a default set of content runtime images with various R and Python versions already installed. These images also include many common OS dependencies, such as GDAL.

Starting with a minimal Dockerfile:

FROM ubuntu:jammy

# Install GDAL and curl
RUN export DEBIAN_FRONTEND=noninteractive && \
        apt-get update && \
        apt-get install -y \
        curl \
        gdal-bin \
        libgdal-dev \
        && \
        rm -rf /var/lib/apt/lists/*

# Install R
ARG R_DISTRIBUTION=ubuntu-2204
ARG R_VERSION=3.6.3
ARG R_INSTALLER=r-${R_VERSION}_1_amd64.deb
RUN curl -fsSL -O https://cdn.rstudio.com/r/${R_DISTRIBUTION}/pkgs/${R_INSTALLER} && \
    export DEBIAN_FRONTEND=noninteractive && \
    apt-get update && \
    apt-get install -f -y ./${R_INSTALLER} && \
    rm ${R_INSTALLER} && \
    rm -rf /var/lib/apt/lists/*

Build the Docker image:

docker build . -t myorg/myrepo/rstudio/custom-content-with-gdal:jammy
Note

You also need to docker push the image to your organization’s Docker registry so that it is accessible from your Kubernetes cluster.

Next, we use the Connect Server API POST /v1/environments endpoint to create a new execution environment. This execution environment can then be used by content.

Note

The value for matching in the environment created is exact. This indicates that the environment should only be used if it is explicitly requested by a piece of content. Connect will never choose this environment during automatic selection.

curl -XPOST -H "Authorization: ${ADMIN_API_KEY}" ${CONNECT_SERVER_URL}/__api__/v1/environments -d '{
  "title": "Custom GDAL image",
  "description": "My custom image with GDAL",
  "cluster_name": "Kubernetes",
  "name": "myorg/myrepo/rstudio/custom-content-with-gdal:jammy",
  "matching": "exact",
  "r": {
    "installations": [
      {
        "version": "3.6.3",
        "path": "/opt/R/3.6.3/bin/R"
      }
    ]
  }
}'

Finally, we can use the PATCH /v1/content/{guid} endpoint to modify an existing piece of content to request this image the next time it executes.

CONTENT_GUID=<replace with a valid content guid>

curl -XPATCH -H "Authorization: ${ADMIN_API_KEY}" ${CONNECT_SERVER_URL}/__api__/v1/content/${CONTENT_GUID} -d '{
  "default_image_name": "myorg/myrepo/rstudio/custom-content-with-gdal:jammy"
}'