Skip to content

Docker

Goal

Learn how to...

  • build a container image...
  • ...using a service

Preparation

Building a container image requires a Dockerfile which can be fetched with the following command:

git checkout upstream/160_gitlab_ci/230_docker -- Dockerfile

Task: Build a container image

For building a container image, you will need to...

  1. Add a new stage package to the pipeline
  2. Add a new job package to the pipeline
  3. Use the image docker:20.10.18 for the job
  4. Add a rule to limit execution to pushes to the default branch
  5. Add a service to the job:
    1. using the image docker:20.10.18-dind
    2. using the command set to [ "dockerd", "--host", "tcp://0.0.0.0:2375" ]
  6. Add a job variable DOCKER_HOST with value tcp://docker:2375
  7. Execute the command docker build --tag hello .

Heads-Up

The GitLab runner must be configured to run services in privileged mode so that the Docker daemon is able to start.

Afterwards check the pipeline in the GitLab UI. You should see a successful pipeline run.

Hint (Click if you are stuck)

The service should be set to:

services:
- name: docker:20.10.18-dind
  command: [ "dockerd", "--host", "tcp://0.0.0.0:2375" ]
Solution (Click if you are stuck)

.gitlab-ci.yml:

workflow:
  rules:
  - if: $CI_DEPLOY_FREEZE
    when: never
  - if: $CI_PIPELINE_SOURCE == 'push'
  - if: $CI_PIPELINE_SOURCE == 'web'
  - if: $CI_PIPELINE_SOURCE == 'schedule'
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
  - if: $CI_PIPELINE_SOURCE == 'pipeline'
  - if: $CI_PIPELINE_SOURCE == 'api'
    when: never
  - if: $CI_PIPELINE_SOURCE == 'trigger'
    when: never

include:
- local: go.yaml

.run-on-push-to-default-branch:
  rules:
  - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'

.run-on-push-and-in-mr:
  rules:
  - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

stages:
- check
- build
- test
- deploy
- package
- trigger

default:
  image: golang:1.19.2

lint:
  stage: check
  extends:
  - .run-on-push-and-in-mr
  script:
  - go fmt .

audit:
  stage: check
  extends:
  - .run-on-push-and-in-mr
  script:
  - go vet .

unit_tests:
  stage: check
  extends:
  - .run-on-push-and-in-mr
  script:
  - go install gotest.tools/gotestsum@latest
  - gotestsum --junitfile report.xml
  artifacts:
    when: always
    reports:
      junit: report.xml

build:
  stage: build
  extends:
  - .run-on-push-and-in-mr
  - .build-go

test:
  stage: test
  extends:
  - .run-on-push-and-in-mr
  - .test-go

deploy:
  stage: deploy
  rules:
  - if: '$CI_COMMIT_REF_NAME == "dev" || $CI_COMMIT_REF_NAME == "live"'
  environment:
    name: ${CI_COMMIT_REF_NAME}
  before_script:
  - apt-get update
  - apt-get -y install curl ca-certificates
  script:
  - |
    curl https://seat${SEAT_INDEX}.${CI_COMMIT_REF_NAME}.webdav.inmylab.de/ \
        --fail \
        --verbose \
        --upload-file hello-linux-amd64 \
        --user seat${SEAT_INDEX}:${PASS}

pages:
  stage: deploy
  extends:
  - .run-on-push-to-default-branch
  image: alpine
  script:
  - cp hello-linux-amd64 public/hello
  artifacts:
    paths:
    - public

package:
  image: docker:20.10.18
  stage: package
  rules:
  - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'
  variables:
    DOCKER_HOST: tcp://docker:2375
  services:
  - name: docker:20.10.18-dind
    command: [ "dockerd", "--host", "tcp://0.0.0.0:2375" ]
  script:
  - docker build --tag hello .

trigger:
  stage: trigger
  extends:
  - .run-on-push-to-default-branch
  trigger:
    include: child.yaml

If you want to jump to the solution, execute the following command:

git checkout upstream/160_gitlab_ci/230_docker -- '*'