Using the Docker execution environment
You can use the Docker execution environment to run your Jobs in Docker containers. You access the Docker execution environment using the Docker executor. Using Docker increases performance because it builds only what your application requires.
Specify a Docker image in your .circleci/config.yml file to spin up a container. All steps in your job run in this container.
| Using Docker? Authenticating Docker pulls from image registries is recommended when using the Docker execution environment. Authenticated pulls allow access to private Docker images, and may also grant higher rate limits, depending on your registry provider. For further information, see Using Docker Authenticated Pulls. |
jobs:
my-job:
docker:
- image: cimg/node:lts
A container is an instance of a specified Docker image. CircleCI refers to the first image listed in your configuration for a job as the primary container image, and this is where all steps in the job run. You can also specify secondary containers to run alongside the primary container for services such as databases.
| For an introduction to Docker concepts, see the Docker Overview documentation. |
CircleCI maintains convenience images on Docker Hub for popular languages. See the CircleCI Developer Hub for a complete list of image names and tags.
If you need a Docker image that installs Docker and has Git, consider using cimg/base:current.
|
Specifying Docker images
You can specify Docker images in two ways:
-
By the image name and version tag on Docker Hub.
-
By using the URL to an image in a registry.
CircleCI supports nearly all public images on Docker Hub and other Docker registries by default when you specify the docker: key in your config.yml file. If you want to work with private images/registries, refer to Using Docker Authenticated Pulls.
The following examples show how you can use public images from various sources:
Available Docker resource classes
The resource_class key allows you to configure CPU and RAM resources for each job.
Specify a resource class using the resource_class key, as follows:
jobs:
build:
docker:
- image: cimg/base:current
resource_class: xlarge
steps:
# ... other config
x86
For the Docker execution environment, the following resource classes are available for the x86 architecture:
Gen1
| For credit and access information, see the Resource classes page. Resource class access is dependent on your Plan. |
| Class | vCPUs | RAM | Cloud | Server |
|---|---|---|---|---|
|
1 |
2GB |
Yes |
Yes |
|
2 |
4GB |
Yes |
Yes |
|
3 |
6GB |
Yes |
Yes |
|
4 |
8GB |
Yes |
Yes |
|
8 |
16GB |
Yes |
Yes |
|
16 |
32GB |
Yes |
Yes |
|
20 |
40GB |
Yes |
Yes |
Gen2
| For credit and access information, see the Resource classes page. Resource class access is dependent on your Plan. |
| Class | vCPUs | RAM | Cloud | Server |
|---|---|---|---|---|
|
1 |
2GB |
Yes |
No |
|
2 |
4GB |
Yes |
No |
|
3 |
6GB |
Yes |
No |
|
4 |
8GB |
Yes |
No |
|
8 |
16GB |
Yes |
No |
|
16 |
32GB |
Yes |
No |
|
20 |
40GB |
Yes |
No |
Arm
The following resource classes are available for Arm with Docker:
Gen1
| Class | vCPUs | RAM | Cloud | Server |
|---|---|---|---|---|
|
2 |
8 GB |
Yes |
No |
|
4 |
16 GB |
Yes |
No |
|
8 |
32 GB |
Yes |
No |
|
16 |
64 GB |
Yes |
No |
Gen2 Beta
| Arm gen2 for Docker is currently in beta. Performance and pricing are tentative and may change when this feature becomes generally available. |
| For credit and access information, see the Resource classes page. Resource class access is dependent on your Plan. |
| Class | vCPUs | RAM | Cloud | Server |
|---|---|---|---|---|
|
2 |
8 GB |
Yes |
No |
|
4 |
16 GB |
Yes |
No |
|
8 |
32 GB |
Yes |
No |
|
16 |
64 GB |
Yes |
No |
View resource usage
To view the compute resource usage for the duration of a job in the CircleCI web app:
-
In the CircleCI web app, select your org from the org cards on your user homepage.
-
Select Pipelines from the sidebar and locate your pipeline from the list. You can use the project, branch, date, and status search options to help.
-
Select the job you want to access by selecting the job name.
-
Select the Resources tab to view CPU and RAM usage for the duration of the job.
You can use these insights to decide whether to make changes to the job’s configured resource class.
Docker gen2
Resource classes running on gen2 infrastructure offer significant performance and cost improvements over their gen1 equivalents.
Performance improvements
Using more modern compute, gen2 instances deliver significant performance improvements compared to gen1 equivalents, based on benchmarks measured during the beta period:
-
x86 gen2: up to 71% faster.
-
Arm gen2: up to 94% faster.
Actual performance gains depend on your specific workloads.
x86 gen2 resources have a higher cost in credits per minute than their gen1 equivalents. See our Pricing Page for details.
Using gen2
To use a gen2 resource class, specify a large.gen2 or equivalent class in your job configuration. For Arm, use the equivalent arm.*.gen2 class, for example arm.large.gen2:
version: 2.1
jobs:
my-job:
docker:
- image: cimg/base:current
resource_class: large.gen2
steps:
# ... steps for your job
Docker benefits and limitations
Docker also has built-in image caching and enables you to build, run, and publish Docker images via Remote Docker. Consider the requirements of your application as well. If the following are true for your application, Docker may be the right choice:
-
Your application is self-contained.
-
Your application requires additional services for testing.
-
You distribute your application as a Docker image (requires using Remote Docker).
-
You want to use
docker compose(requires using Remote Docker).
Choosing Docker limits your runs to what is possible from within a Docker container (including our Remote Docker feature). For instance, if you require low-level access to the network or need to mount external volumes, consider using machine.
The table below shows tradeoffs between using a docker image versus an Ubuntu-based machine image as the environment for the container:
| Capability | docker |
machine |
|---|---|---|
Start time |
Instant |
Instant for most (1) |
Clean environment |
Yes |
Yes |
Custom images |
Yes (2) |
No |
Build Docker images |
Yes (3) |
Yes |
Full control over job environment |
No |
Yes |
Full root access |
No |
Yes |
Run multiple databases |
Yes (4) |
Yes |
Run multiple versions of the same software |
No |
Yes |
Yes |
Yes |
|
Run privileged containers |
No |
Yes |
Use Docker compose with volumes |
No |
Yes |
Yes |
Yes |
(1) Some less commonly used execution environments may see up to 90 seconds of start time.
(2) See Using Custom Docker Images.
(3) Requires using Remote Docker.
(4) While you can run multiple databases with Docker, all images (primary and secondary) share the underlying resource limits. Performance in this regard depends on the compute capacities of your plan.
For more information on machine, see the next section below.
Docker image best practices
-
If you encounter problems with rate limits imposed by your registry provider, using Authenticated Docker Pulls may grant higher limits.
-
CircleCI has partnered with Docker to ensure that our users can continue to access Docker Hub without rate limits. You are not impacted by rate limits when pulling images from Docker Hub through CircleCI. We encourage you to Add Docker Hub Authentication to your CircleCI configuration and consider upgrading your Docker Hub plan, as appropriate, to prevent any impact from rate limits.
-
Avoid using mutable tags like
latestor1as the image version in yourconfig.ymlfile. It is best practice to use precise image versions or digests, likeredis:3.2.7orredis@sha256:95f0c9434f37db0a4f...as shown in the examples. Mutable tags often lead to unexpected changes in your job environment. CircleCI cannot guarantee that mutable tags return an up-to-date version of an image. You may specifyalpine:latestand actually get a stale cache from a month ago. -
If you experience increases in your run times due to installing additional tools during execution, consider creating and using a custom-built image that comes with those tools pre-installed. See the Using Custom-Built Docker Images page for more information.
-
When you use AWS ECR images, it is best practice to use
us-east-1region. Our job execution infrastructure is inus-east-1region, so having your image on the same region reduces the image download time. -
If your pipelines fail despite little to no changes in your project, you may need to investigate upstream issues with the Docker images you use.
More details on the Docker executor are available on the Configuration Reference page.
Using multiple Docker images
You can specify multiple images for your job. Each image spins up a separate container.
Using multiple containers for a job is useful if you need a database for your tests, or another required service.
When using a multi-container job setup, all containers run in a common network, and every exposed port is available on localhost. All containers can communicate with one another. You can also change this hostname using the name key. For a full list of options, see the Configuration Reference.
In a multi-image configuration job, the container created by the first image listed executes all steps.
jobs:
build:
docker:
# Primary container image where all steps run.
- image: cimg/base:current
# Service container image on common network.
- image: cimg/mariadb:10.6
steps:
# command will execute in an Ubuntu-based container
# and can access MariaDB on localhost
- run: sleep 5 && nc -vz localhost 3306
RAM disks
A RAM disk is available at /mnt/ramdisk that offers a temporary file storage paradigm, like /dev/shm. Using the RAM disk can help speed up your build. Ensure your resource_class has enough memory to fit the entire project contents (all files checked out from git, dependencies, assets generated, etc.).
The simplest way to use this RAM disk is to configure the working_directory of a job to be /mnt/ramdisk:
jobs:
build:
docker:
- image: alpine
working_directory: /mnt/ramdisk
steps:
- run: |
echo '#!/bin/sh' > run.sh
echo 'echo Hello world!' >> run.sh
chmod +x run.sh
- run: ./run.sh
Caching Docker images
| This section discusses caching the Docker images used to spin up a Docker execution environment. It does not apply to Docker Layer Caching, which is a feature used to speed up building Docker images in your projects. |
The time it takes to spin up a Docker container to run a job can vary based on several factors. These include the size of the image and whether some, or all, of the layers are already cached on the underlying Docker host machine.
If you are using a more popular image, such as CircleCI convenience images, then cache hits are more frequent across a larger number of layers. Most of the popular CircleCI images use the same base image. The majority of the base layers are the same between images, so you have a greater chance of having a cache hit.
The environment has to spin up for every job, regardless of whether it is in the same workflow or if it is a re-run/subsequent run. (CircleCI never reuses containers, for security reasons.) Once the job finishes, CircleCI destroys the container. Jobs, even in the same workflow, are not guaranteed to run on the same Docker host machine. This implies that the cache status may differ.
In all cases, cache hits are not guaranteed, but are a bonus convenience when available. With this in mind, account for a worst-case scenario of a full image pull in all jobs.
You cannot control caching availability via settings or configuration. Choosing a popular image, such as CircleCI convenience images, increases the chances of hitting cached layers in the "Spin Up Environment" step.
Next steps
Find out more about using Convenience Images with the Docker executor.