Skip to main content
Let’s talk about job containers in GitHub Actions.
A turquoise-to-light-green gradient presentation slide with the title "Job Containers" in white text near the center-right. Small "© Copyright KodeKloud" text appears in the bottom-left corner.
When authoring a GitHub Actions workflow, you select a runner for each job. The most common choice is a GitHub-hosted virtual machine such as ubuntu-latest. These hosted VMs include a pre-configured environment with many common tools and runtimes (language runtimes, package managers, CLI tools, browsers, and cached Docker images). If a required runtime or package version is not preinstalled, you add steps to the job to install them. For example, a typical workflow that sets up Node.js, installs dependencies, and runs tests looks like this:
Installing runtimes and packages at job runtime increases execution time, which can lengthen feedback loops and raise GitHub Actions usage costs. Job containers let you avoid repeated setup by running the job inside a Docker image that already contains the required runtime and tools. What is a job container?
  • A job container is a Docker image that GitHub starts on the hosted runner and uses to execute all the job’s steps.
  • The hosted VM still boots, but the job steps run inside the container’s environment.
  • This provides a fast, consistent environment that you control via the image.
Benefits of running jobs inside containers:
  • Isolation — Jobs run in isolated containers, reducing conflicts with the host VM and other jobs.
  • Reproducibility — A specific image yields the same environment across runs and runners.
  • Security — Containerization limits access to the host and lets you constrain permissions for untrusted workloads.
To use a job container, specify the container key under the job. If your container image already contains Node.js 20 and the test packages, you can remove the runtime/setup steps and rely on the image:
When this workflow runs, GitHub creates the hosted runner (for example, the Ubuntu VM), pulls the specified container image, starts the container, and executes the job steps inside it. Because the image already contains the runtime and test packages, jobs start and finish faster and behave more predictably.
Using a container image with preinstalled runtimes and tools reduces per-run setup time, speeds up CI feedback, and can lower your GitHub Actions usage costs.
A common caution: avoid connecting CI jobs directly to production databases or services. Tests that run against production resources can affect performance and compromise data integrity. For tests that need databases or other services, use dedicated test instances or GitHub Actions service containers.
Do not run CI tests directly against production databases or services. Use isolated test instances or service containers to protect production systems.
Service containers
  • Service containers run as additional Docker containers alongside your job container and are accessible via network hostnames.
  • Use service containers for databases, caching layers, or any supporting service your tests require.
Example: provide a PostgreSQL service to a job:
Combining job containers (for prebuilt environments) with service containers (for supporting services like databases) yields fast, reproducible, and safer CI pipelines. Further reading and references

Watch Video