Today I’m going to tell about my experience developing C++ application inside the docker container. I’ve been working on some project for a couple of months already. And at the beginning of this project I’ve decided to create a full development environment inside Docker, even with Qt Creator IDE. So, I’ll show how to use this approach with a simple example. There’re two containers, one for building and another one with Qt Creator IDE inside for developing. And the whole building process is automated with GitLab. Full example you can find here.

Key features:

Doesn’t pollute your host system

Fast start for a new team member

Easy to maintain

Everything is automated with GitLab

Known limitations and issues:

Linux only

X11 only

Bad HiDPI support

Build environment

It’s a docker container with compiler, dependencies and all the other essential stuff that you need to build your application. It will be used mainly for building application on GitLab CI.

FROM amd64/ubuntu:bionic

RUN apt-get update && apt-get install -y cmake g++ make qt5-default

CMD ["/bin/bash"]

Development environment

This container is built on top of the first one and contains Qt Creator.

FROM <your docker registry>:5000/build-env

RUN apt-get update && apt-get install -y git qtcreator libxrender1 gdb fonts-ubuntu

CMD ["/usr/bin/qtcreator"]

Note that <Your GitLab Server> has to be replaced with your Docker registry host name.

We can’t just start Qt Creator inside the container, so we need a special bash script for that.

#!/bin/bash

set -ex SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" IMAGE=<your docker registry>:5000/dev-env

CONTAINER_NAME=qtcreator

FAKE_HOME=$SCRIPTDIR/dev-env-home mkdir -p $FAKE_HOME FONTCONF=.config/fontconfig/fonts.conf

if [ ! -e $FAKE_HOME/$FONTCONF ] ; then

mkdir -p `dirname $FAKE_HOME/$FONTCONF`

cp $HOME/$FONTCONF $FAKE_HOME/$FONTCONF

fi xhost +

docker run --rm --name $CONTAINER_NAME --privileged --net=host \

-u `id -u`:`id -g` -e DISPLAY \

-e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 \

--volume="/etc/passwd:/etc/passwd:ro" \

--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \

--volume="$FAKE_HOME:/home/$(id -un)" \

$IMAGE

So, what does this script do. It makes possible to use host’s X server, hardware, font settings and current user inside the container. It also makes fake home directory for storing Qt Creator’s settings and all the C++ projects. You can also bind another directories if you want to store projects somewhere else, for example --volume="$HOME/projects:/home/$(id -un)/projects" . If you need a console access just run docker exec -it qtcreator bash .

Building containers with GitLab CI

I’m putting both docker files in a separate GitLab project. This project has a ci configuration file that looks like this.

variables:

REGISTRY: '<your docker registry>:5000' stages:

- build-env

- dev-env build-env:

stage: build-env

script:

- cd build-env

- IMAGE_NAME='build-env'

- docker build --network host -t $IMAGE_NAME .

- docker image tag $IMAGE_NAME $REGISTRY/$IMAGE_NAME

- docker push $REGISTRY/$IMAGE_NAME

only:

- master dev-env:

stage: dev-env

script:

- cd dev-env

- IMAGE_NAME='dev-env'

- docker build --network host -t $IMAGE_NAME .

- docker image tag $IMAGE_NAME $REGISTRY/$IMAGE_NAME

- docker push $REGISTRY/$IMAGE_NAME

only:

- master

It builds both containers on every commit in the master branch.

Building application

And here’s ci config for some test application

image: <your docker registry>:5000/build-env build:

script:

- mkdir -p build

- cd build

- cmake ..

- make

Full example you can find here.

In case if you don’t know how to setup GitLab CI or Docker registry:

Main GitLab help page

Building Docker images with GitLab CI

Setup your own Docker registry or GitLab Docker registry