Continuous integration with Docker and GitLab

Assembly Line

Working with Shell Scripts

Basically, each shell script should call precisely the commands that execute the correspondingly named build process. In the pre_cleanup step, is designed to ensure that the Runner does not already have a Docker container with the same name as the container to be built – it would be impossible to launch a new container otherwise on running

Similarly, ensures that a Docker image does not exist with the same name and version in the Runner's local image list; otherwise, the build would again fail.

All commands that build the container belong in – first of all, Docker build and possibly additional necessary commands (Figure 3). The most interesting part is certainly Here, you have the possibility to define arbitrary tests in shell syntax so that you can check whether the automatically built container is really working as intended.

Figure 3: A example: This variant of the script builds the image and tags it.

For example, if you want the container to launch Nginx on port 80 and port 443, a for loop in combination with netstat or ss could check whether an existing Nginx instance actually opens a TCP/IP socket within 30 seconds of the Docker run call. The IP addresses of the loopback interface (e.g., are ideal for this test. The Docker run call must of course be filled with appropriate parameters, and the Docker container itself must be able to use these environment variables.

The output behavior of the shell script is also very important: It must return 1 immediately if it encounters an error. If the tests run successfully, it should return   at the end, so that GitLab CI can check off the test as "successful" in its database. Uploading the image to the Docker registry with is now possible. However, you should make sure you not only upload the image, but also set an appropriate tag.

Incidentally, you can track GitLab CI/CD jobs live by opening the web interface, navigating to the respective project and clicking CI/CD . GitLab lists both the Pipelines (Figure 4) and the Jobs (Figure 5). If a test goes wrong, GitLab informs you – by email, as well.

Figure 4: Right in the thick of it: GitLab shows an overview of all processed pipelines, as well as …
Figure 5: … the individual jobs and the output created when the job was processed.

Where's the Beef?

If you've built Docker images before, you might be asking yourself where the Dockerfile got to. After all, it contains all the relevant statements for Docker build. Clearly, besides the various CI scripts, you still need all the other files that you would need without CI – first and foremost, the Dockerfile.


GitLab CI and its Docker integration prove to be a very practical GitLab add-on. If you use GitLab anyway and want to build Docker containers, you should take a close look at GitLab CI, especially if you do not want to distribute your apps with Docker but are looking for a very lean and efficient method to operate deep infrastructure components.


  1. "Security issues when dealing with Docker images" by Nils Magnus, ADMIN , issue 39, 2017, pp. 18-21,
  2. GitLab docs:
  3. Container Linux:
  4. Ignition for Container Linux:
  5. GitLab Runner for Debian-based systems:
  6. GitLab Runner for RPM-based systems:
  7. GitLab CI documentation:

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs

Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.

Learn More”>


		<div class=