Using custom images

Create, manage, and use custom images for GitHub-hosted larger runners in your organization or enterprise.

Custom images

You can create a custom image to define the exact environment that your GitHub-hosted larger runners use. Custom images let you preinstall tools, dependencies, and configurations to speed up workflows and improve consistency across jobs.

When your runner uses a custom image, it acts as a “pre-warmed” environment, allowing workflows to complete quicker, by downloading packages and binaries once during image creation instead of every time a workflow is run. For more information about custom images, see Runner images.

The process of using a custom image involves three main steps:

  1. Setting up an image-generation runner: Create a larger runner to build and store your custom image.
  2. Generating a custom image: Generate your custom image by running a workflow using the image-generation runner.
  3. Installing custom images: Create a runner that uses your custom image.

Prerequisites

Before you can create custom images, make sure the following requirements are met.

Setting up an image-generation runner

To create a custom image, you must first set up an image-generation runner. When you create the runner, the platform that you select for your runner must match the platform of the image you want to build. The platform of the runner can be Linux x64, Linux ARM64, or Windows x64.

  1. Create a larger runner:
  2. When configuring the runner, select the following configurations for your image-generation runner:

Generating a custom image

After you create an image-generation runner, run a workflow that includes the snapshot keyword to generate a custom image.

To configure a workflow for image generation:

Note

GitHub recommends configuring image generation as a scheduled workflow on a weekly basis. This approach ensures dependencies remain up-to-date and have the latest security patches. For more information, see Events that trigger workflows.

It can take some time for your image to be fully generated and ready to use after the workflow completes. Provisioning time varies based on runner size and configuration, and may take several hours for larger runners.

The image is generated only when the job completes successfully. This prevents new image versions from being created when a workflow fails or ends in an incomplete state.

Once the image is generated, it is available for use in your workflows. For more information about managing custom images, see Managing custom images.

String syntax

You can use the string syntax with snapshot to define the image name. This method creates a new image or adds a new version to an existing image with the same name. You cannot specify a version number using this syntax.

jobs: 
  build:
    runs-on: my-image-generation-runner
    snapshot: my-custom-image
    steps:
      # Add any steps to download and setup any dependencies here

Mapping syntax

You can use the mapping syntax with snapshot to define both the image-name and the optional version. When you specify a major version, the minor versioning automatically increments if that major version already exists. Patch versions are not supported.

jobs: 
  build:
    runs-on: my-image-generation-runner
    snapshot: 
        image-name: my-custom-image
        version: 2.*
    steps:
      # Add any steps to download and setup any dependencies here

Versioning

When you generate custom images, GitHub automatically assigns version numbers to help you manage updates and track image history.

Default behavior

If an image with the specified name does not exist in your organization or enterprise, GitHub creates it with an initial version number of 1.0.0.
If an image with the same name already exists, GitHub creates a new version by incrementing the minor version number (for example, 1.1.0, 1.2.0, etc.).

If you do not specify a version in your YAML file, image generation uses this default behavior.

Specifying a version in your workflow

If you include a version in the YAML mapping, GitHub checks the major version number first.

Patch versions are not supported.

Latest tag

The most recent workflow run for an image is always tagged as latest.
If you specify an older major version in the YAML (for example, version: 1.* when a 2.0 version exists), GitHub generates a new minor version under the older major version and marks it as latest.

Note

GitHub-hosted larger runner creation does not support wildcards in image version selection.

Billing and storage for custom images

Jobs that use custom images are billed at the same per-minute rate as the larger runner that uses the image. Storage for custom images is billed separately through GitHub Actions storage.

If you rebuild images frequently and retain older versions, your storage usage can grow quickly because each successful workflow job that includes the snapshot keyword creates a new image version. For more information, see GitHub Actions billing and Enforcing policies for GitHub Actions in your enterprise.

Managing custom images

You can view detailed information about each image, delete unused images or specific versions, and track image versions over time.

  1. On GitHub, navigate to the main page of the organization.

  2. Under your organization name, click Settings. If you cannot see the "Settings" tab, select the dropdown menu, then click Settings.

    Screenshot of the tabs in an organization's profile. The "Settings" tab is outlined in dark orange.

  3. In the left sidebar, click Actions, then click Custom images.

  4. On the "Custom images" page, you can view all custom images that have been created in your organization or enterprise.

  5. To view details about a specific image, click the image name.

Installing custom images

Once your custom image is ready, you can install it on a new GitHub-hosted larger runner.

  1. Follow the steps for creating a larger runner:

  2. When configuring the runner:

  3. In your GitHub Actions workflow job, set the runs-on key to the name of your runner.

    jobs: 
      build:
        runs-on: my-custom-runner
        steps:
        # Add any steps for your workflow here
    
  4. Run your workflow to verify that it completes successfully. The job logs will show the image name and version in the "Set up job" section.

Security best practices for custom images

To prevent unauthorized changes to your images, follow these best practices.