Skip to main content

CircleCI Dockerhub Authentication

This runbook shows how to setup and use “service” DockerIDs to service CircleCI builds.

Please use Github Actions instead of CircleCI

Context

as of 1st november 2020, anonymous pulls for docker images will be rate limited to 100 per 6 hours. There are higher rates for personal accounts and unlimited pulls for organisational accounts. See:

This will significantly hamper our ability to run builds in CircleCI without action. in order to resolve this, CircleCI recommends adding docker hub authentication.

Fortunately, we have access to a DockerHub organisation in the Ministry of Justice, which has free unlimited pulls of images.

Security

We are not using CircleCI contexts as this is a shared organisational level construct, that any pipeline could use. We’re not set up with context restrictions or groups in CircleCI at time of writing.

We need to ensure that each of the circleci projects has an individual DockerID and token added in project level environment variables, reducing blast radius should it become compromised.

Prerequisites

You will need:

  • Your own Docker ID, which has been:
    • Added to the ministryofjustice dockerhub organisation as an owner.
    • added to the opgdockerhubusers team.
  • Access to the OPG webops team google group email.
  • Access to the project settings on the CircleCI project you are working on.

Ask one of your webops colleagues to help if you don’t have details of these.

Steps

there are 3 main steps:

  1. Create a service Docker ID
  2. Add service user to docker organisation and team
  3. Add docker hub credentials to CircleCI

1. Create a service Docker ID

  1. On hub.docker.com create a Docker ID, using:
    • A strong randomised password
    • A name that makes sense for the pipeline.
    • The email associated with OPG Webops Google Group, using a + email alias to associate with the new Docker ID.
  2. Take note of the above credentials and store in the webops secure vault for safekeeping.
  3. Log out of hub.docker.com.
  4. This will send a validation email to the opg team google group, but look out for one with the correct alias.
  5. Validate the email.
  6. Once validated successfully, log back in with the new credentials
  7. Go to the profile name, drop down to Account Settings and select Security on the screen.
  8. In the Access Tokens click New Access Token.
  9. Give the token a useful name e.g. CircleCI access token and click Create
  10. On the next dialog, copy the access token provided.
  11. Paste into the relevant secure vault entry for safekeeping.
  12. Click Copy and Close.

2. Add the service account to organisation and team

  1. Log in to your own DockerID on hub.docker.com.
  2. under Organisations click ministryofjustice and then click Add Member
  3. Enter the DockerID of the new service user and select opgdockerhubusers from the dropdown
  4. Click Add.

This user will have Member permissions, which will be enough to pull images. No higher permission level should be set.

3. Add dockerhub credentials to a CircleCI Project

  1. Create AWS Secrets Manager secrets for the DockerID and access token in your product’s module in opg-org-infra. Our intention is to create these secrets in the opg-management AWS account.

    module "ci_dockerhub_secrets" {
      source         = "../modules/ci_dockerhub_secrets"
      product_prefix = "the_name_of_the_product_to_namespace_secrets"
      providers      = { aws = aws.management }
    }
    output "aws_secretsmanager_secret_dockerhub_id" {
      value = module.ci_dockerhub_secrets.aws_secretsmanager_secret_dockerhub_id
    }
    output "aws_secretsmanager_secret_dockerhub_token" {
      value = module.ci_dockerhub_secrets.aws_secretsmanager_secret_dockerhub_token
    }
    
  2. Use the aws_secretsmanager_secret_version data source to provide the secret string as an environment variable to CircleCI. You can use the opg-org-infra repository module to create environment variables for CircleCI. Applying this module will set a value of default for each secret, to be replaced later.

    data "aws_secretsmanager_secret_version" "product_dockerhub_id" {
      secret_id = module.product.aws_secretsmanager_secret_dockerhub_id.id
      provider  = aws.management
    }
    
    data "aws_secretsmanager_secret_version" "product_dockerhub_token" {
      secret_id = module.product.aws_secretsmanager_secret_dockerhub_token.id
      provider  = aws.management
    }
    
    module "product" {
      source         = "./modules/repository"
      name           = "product"
      ...
      circleci_env_vars = {
        DOCKER_USER           = data.aws_secretsmanager_secret_version.product_dockerhub_id.secret_string
        DOCKER_ACCESS_TOKEN   = data.aws_secretsmanager_secret_version.product_dockerhub_token.secret_string
    
  3. When the secrets have been created, the value of each can be set from the command line with aws-cli

    aws-vault exec management -- aws secretsmanager put-secret-value --secret-id product_prefix-dockerhub_id --secret-string 'somesecretstringvalue'
    aws-vault exec management -- aws secretsmanager put-secret-value --secret-id product_prefix-dockerhub_token --secret-string 'somesecretstringvalue'
    

    Alternatively, these values can be set in Secrets Manager in the AWS console.

  4. Once these are set, rerun the build workflow on opg-org-infra’s master branch in CircleCI to update your project settings.

4. Adding Docker Authenticated Pulls to CircleCI jobs

  1. CircleCI pulls for executors should be updated to include auth details.

    executors:
      puppeteer:
        docker:
          - image: buildkite/puppeteer
            auth:
              username: $DOCKER_USER
              password: $DOCKER_ACCESS_TOKEN
        resource_class: small
    
  2. Use the docker orb to create a command that installs the credential helper and completes a docker login.

    orbs:
      path-to-live:
        orbs:
          docker: circleci/docker@1.4.0
        commands:
          dockerhub_login:
            steps:
              - docker/install-docker-credential-helper
              - docker/check:
                  docker-password: DOCKER_ACCESS_TOKEN
                  docker-username: DOCKER_USER
    
  3. Docker pulls inside your jobs can then be authorised just prior to any step that will attempt a docker pull. For example,

    docker_build_front_app:
      executor: python
      steps:
        - checkout
        - setup_remote_docker:
            version: 19.03.12
            docker_layer_caching: false
        - dockerhub_login
        - run:
            name: Build
            command: docker build --file ./docker/app/Dockerfile --tag front-app:latest .
    

More information available at using Docker Authenticated Pulls and circleci/docker orb

This page was last reviewed on 15 August 2024. It needs to be reviewed again on 14 August 2025 by the page owner #opg-webops-community .
This page was set to be reviewed before 14 August 2025 by the page owner #opg-webops-community. This might mean the content is out of date.