Skip to content

Reusing Dev Containers Within a Pipeline

Given a repository with a local development container a.k.a. dev container that contains all the tooling required for development, would it make sense to reuse that container for running the tooling in the Continuous Integration pipelines?

Options for Building Dev Containers Within a Pipeline

There are three ways to build devcontainers within pipeline:

Considered Options

  • Run CI pipelines in the native environment
  • Run CI pipelines in the dev container via building image locally
  • Run CI pipelines in the dev container with a container registry

Here are below pros and cons for both approaches:

Run CI Pipelines in the Native Environment

Pros Cons
Can use any pipeline tasks available Need to keep two sets of tooling and their versions in sync
No container registry Can take some time to start, based on tools/dependencies required
Agent will always be up to date with security patches The dev container should always be built within each run of the CI pipeline, to verify the changes within the branch haven't broken anything

Run CI Pipelines in the Dev Container Without Image Caching

Pros Cons
Utilities scripts will work out of the box Need to rebuild the container for each run, given that there may be changes within the branch being built
Rules used (for linting or unit tests) will be the same on the CI Not everything in the container is needed for the CI pipeline¹
No surprise for the developers, local outputs (of linting for instance) will be the same in the CI Some pipeline tasks will not be available
All tooling and their versions defined in a single place Building the image for each pipeline run is slow²
Tools/dependencies are already present
The dev container is being tested to include all new tooling in addition to not being broken

¹: container size can be reduced by exporting the layer that contains only the tooling needed for the CI pipeline

²: could be mitigated via adding image caching without using a container registry

Run CI Pipelines in the Dev Container with Image Registry

Pros Cons
Utilities scripts will work out of the box Need to rebuild the container for each run, given that there may be changes within the branch being built
No surprise for the developers, local outputs (of linting for instance) will be the same in the CI Not everything in the container is needed for the CI pipeline¹
Rules used (for linting or unit tests) will be the same on the CI Some pipeline tasks will not be available²
All tooling and their versions defined in a single place Require access to a container registry to host the container within the pipeline³
Tools/dependencies are already present
The dev container is being tested to include all new tooling in addition to not being broken
Publishing the container built from devcontainer.json allows you to reference it in the cacheFrom in devcontainer.json (see docs). By doing this, VS Code will use the published image as a layer cache when building

¹: container size can be reduces by exporting the layer that contains only the tooling needed for the CI pipeline. This would require building the image without tasks

²: using container jobs in AzDO you can use all tasks (as far as I can tell). Reference: Dockerizing DevOps V2 - AzDO container jobs - DEV Community

³: within GH actions, the default Github Actions token can be used for accessing GHCR without setting up separate registry, see the example below. Note: This does not build the Dockerfile together with the devcontainer.json

    - uses: whoan/docker-build-with-cache-action@v5
        id: cache
        with:
          username: $GITHUB_ACTOR
          password: "${{ secrets.GITHUB_TOKEN }}"
          registry: docker.pkg.github.com
          image_name: devcontainer
          dockerfile: .devcontainer/Dockerfile

Last update: August 22, 2024