Prog blog

How to build and push a docker image to a private repository in Concourse CI task

How to build and push a docker image to a private repository in Concourse CI task

For various projects I often create custom docker images, but not all of them are destined to go to the dock hub for security reasons, or just to avoid littering the global registry with something that will only be useful for me. That's why I decided to integrate Concourse CI with local private registry and use private images in tasks that are systematically done for me by continuous integration system. Below is an example of how these services can be described in docker-compose.

docker-compose.yml

version: '3.4'

services:
  concourse-db:
    image: postgres
    networks:
      - default
    restart: always
    environment:
      TZ: 'EST5EDT'
      POSTGRES_DB: concourse
      POSTGRES_PASSWORD: concourse_pass
      POSTGRES_USER: concourse_user
      PGDATA: /database
  concourse:
    image: concourse/concourse
    command: quickstart
    privileged: true
    depends_on: [concourse-db]
    ports: ["8080:8080"]
    restart: always
    environment:
      TZ: 'EST5EDT'
      CONCOURSE_POSTGRES_HOST: concourse-db
      CONCOURSE_POSTGRES_USER: concourse_user
      CONCOURSE_POSTGRES_PASSWORD: concourse_pass
      CONCOURSE_POSTGRES_DATABASE: concourse
      CONCOURSE_EXTERNAL_URL: http://localhost:8080
      CONCOURSE_ADD_LOCAL_USER: test:test
      CONCOURSE_MAIN_TEAM_LOCAL_USER: test
      CONCOURSE_WORKER_BAGGAGECLAIM_DRIVER: overlay
      CONCOURSE_CLIENT_SECRET: Y29uY291cnNlLXdlYgo=
      CONCOURSE_TSA_CLIENT_SECRET: Y29uY291cnNlLXdvcmtlcgo=
  registry.local:
    image: registry
    restart: always
    # ports:
      # - "5000:5000"

The beginning of the compose is a copy of the content from https://concourse-ci.org/docker-compose.yml. The service registry.local was added to it. The ending of the .local is important because without this concourse will automatically connect to the docker hub for the resource.

Then we create a pipeline with the source of our image and the target address for it in our private register. The first task of the build-and-push-image creates an example-image. And the next task some-task shows how we can use the built image in the task.

pipeline.yml

---
resources:
# Repo with Dockerfile
- name: example-image-source
  type: git
  source:
    uri: git@github.com:example/example-image.git
    branch: master
    private_key: ((example-image-private-key))
# Private registry example-image resource
- name: example-image
  type: registry-image
  icon: docker
  source:
    repository: registry.local:5000/example-image

jobs:
- name: build-and-push-image
  plan:
  - get: example-image-source
  - task: build-task-image
    privileged: true
    config:
      platform: linux
      image_resource:
        type: registry-image
        source:
          repository: vito/oci-build-task
      inputs:
      - name: example-image-source
      outputs:
      - name: image
      params:
        CONTEXT: example-image-source
      run:
        path: build
  - put: example-image
    params:
      image: image/image.tar

- name: some-task
  plan:
  - get: some-resource
    passed: [build-and-push-image]
  - task: print-hello-world
    config:
      platform: linux
      image_resource:
        type: docker-image
        source: 
          repository: registry.local:5000/example-image
          insecure_registries: [ "registry.local:5000" ]
      inputs:
      - name: some-resource
      run:
        path: bash
        args:
        - -exc
        - |
          cd some-resource
          echo "Hello World"

That's all. The article is very short because I just wanted to show a case of using a private register in Concourse CI. If you want to know more about building images from concourse I recommend the article: How To Build and Publish a Container Image. And if you want to know more about private registry, I recommend reading: Deploy a registry server