Ubuntu VM/Azure: Install & Run Jenkins in Docker/Docker Compose with persistent container volume located on the external Cloud Data Disk

Kanan Rahimov
Jun 28, 2019 · 4 min read

As you can see from the title that’s a lot of configuration going on here. Basically, I am trying to set up a very simple development workflow using very fully customizable (and cheap) configuration.

Why in Windows Azure? I have a running commercial project and paid a subscription so why not also use it for development purposes.

But before diving into the technical details let’s try to visualize it. That’s what I wanted to achieve:

Image for post
Image for post
desired setup for development nodes

Ubuntu 18.04 and disk storage

Actually, the configuration is quite straight forward. We have Ubuntu 18.04 virtual machine running in Microsoft Azure. 1TB external storage mounted as /apps/data (about the steps to mount it I will talk a bit later). This storage is needed to keep our configuration and data persistent. Hence, I configured it as managed and premium storage. In terms of Microsoft Azure, shortly, managed disk storage means it is highly durable and available, has integration with availability zones (to avoid a single point of failure) and eligible for Azure Backup support. It’s also Premium SSD which deliver high performance and low-latency disk support for VMs.

VM with Docker/Docker Compose and mounted data storage

Check this article to setup and run Ubuntu with Docker in Microsoft Azure. Once Docker installed, follow this article to install Docker Compose as well.

As a next step, we need to setup disk for our VM. Check this article on how to add a data disk to Linux VM. For the instructions to actually mount the disk to Linux VM I used these 3 articles:

My final fstab configuration for the disk looked like this:

UUID=uuid-of-disk /apps/data ext4 defaults,nofail 0 1

Running Jenkins in Docker/Docker Compose with external volume

Now, when we have all configured VM with Docker/Docker Compose, it is time to add our Docker configuration. Our Docker Compose file looks like this:

version: "3.2"services:
context: .
dockerfile: ./Dockerfile
- "8080:8080"
- "50000:50000"
- /apps/data/jenkins-data:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
restart: always

The most important and interesting part here is how we setup volumes. But about this a bit later. Let’s see Dockerfile that we use to build an actual image:

FROM jenkinsci/blueoceanUSER rootRUN addgroup jenkins && adduser -D -G jenkins jenkinsUSER master

It’s based on jenkinsci/blueocean and what we do here is a little trick to deal with user permissions.

As you know we will use persistent volume to keep our Jenkins data and it will be stored in mounted storage. The thing is actual files in the volume is stored in a host machine and used in Docker containers. To avoid permission errors you need to have proper user and group configuration. And that’s why in Dockerfile we add a new user called jenkins with jenkins group. Official image from is also using this user. More about this you can read here.

And in the host machine, for the directory /apps/data/jenkins-data, we have jenkins:jenkins user and group. To do this you can use the following command:

chown -R jenkins:jenkins /apps/data/jenkins-data

Hence, when you mount this directory to the container (see docker compose conf) you have the same user and group and as a result, you do not get permission denied error.

In Ubuntu 18.04 to create this user and group you can use following commands:

groupadd jenkins
useradd -G jenkins jenkins

And finally to our docker container use the following command

docker-compose up -d

restart: always configuration in docker compose will make sure that it is always running after system or docker reboot.


I tried very hard to keep this article short and to the point. I highly recommend checking articles on Docker volumes and how they work. Please check following links for this:


Also, once you installed Docker in Linux machine make sure to check post-installation steps here: https://docs.docker.com/install/linux/linux-postinstall/.

If you’ve any feedback, feel free to tell me what I can improve, or provide better examples.

Feel free to clap as many times as you like :)



Senior Coder, Junior Vlogger

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store