Testing a Docker image created by GitLab CI
We have already see how to set up a GitLab Runner and how to build a Docker image in a GitLab pipeline.
Now we are going to see how to test the image.
For this we need a little project, this is our directory layout:
. ├── app.py ├── Dockerfile └── .gitlab-ci.yml
The application that we would like to add to the Docker image is a really small Python Flask application:
examples/gitlab-test-docker-image/app.py
from flask import Flask from datetime import datetime import os import socket version = 1 app = Flask('Demo') @app.route("/") def main(): return f""" Version {version}<br> At {datetime.now()}<br> PID {os.getpid()}<br> Hostname {socket.gethostname()}<br> """
The Docker image is also not very complex:
examples/gitlab-test-docker-image/Dockerfile
FROM alpine:latest RUN apk add python3 py3-pip RUN pip install flask WORKDIR /opt COPY app.py . CMD ["flask", "run", "--host", "0.0.0.0"]
GitLab CI pipeline
The interesting part is the GitLab pipeline:
examples/gitlab-test-docker-image/.gitlab-ci.yml
stages: - build - test build: image: docker:19.03.12 stage: build variables: DOCKER_TLS_CERTDIR: "/certs" services: - docker:19.03.12-dind script: - docker build -t mydocker:latest . - docker tag mydocker:latest $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/flasker:latest - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker push $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/flasker:latest tags: - docker-runner-tls test-image: services: - name: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/flasker:latest alias: flasker #command: ["flask", "run", "--host", "0.0.0.0", "--port", "5000"] image: python:3.7.2 script: #- curl https://code-maven.com/ - curl http://flasker:5000/
There are two jobs.
The build job will build the image and upload it to the Docker registry of GitLab.
The test-image job will start the newly built image as a GitLab CI service. GitLab will automatically map the ports that are opened in the image and the "alias" field can used to define a hostname for the service. One could also add a command to be executed on the docker container, but in our case that's not necessary as we have it inside the Dockerfile.
Then we have the "image" field that tells GitLab what image to use for the CI job and finally we have simple "script" tag that uses curl to access the web application running in our container that was created from the image we just built.
At this point you could write any types of test that would access the application from the outside. You could also launch other services, for example a database server and thus you can have an environment that resembles your production system.
One caveat that I think I bumped into at a client, is that you might have created the GitLab username and/or the project name with mixed case letter and I using the $CI_PROJECT_NAMESPACE and variable $CI_PROJECT_NAME will retain the case, but as I recall the Docker registry did not like that. However now thinking back, that might have been a totally different issue. In any case, let me leave this warning here.
Published on 2021-08-16