How to run Jenkins using docker and docker-compose

do I run Jenkins as a docker container? In this guide we are going to explore how to achieve that using docker and simplifying the process using docker compose.

Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels.

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. Docker Compose file provides a way to document and configure all of the application’s service dependencies (databases, queues, caches, web service APIs, etc). Using the Compose command line tool you can create and start one or more containers for each dependency with a single command

Docker runs processes in isolated containers. A container is a process which runs on a host. The host may be local or remote. When an operator executes docker run, the container process that runs is isolated in that it has its own file system, its own networking, and its own isolated process tree separate from the host.

# Prerequisites

To follow along, ensure that you have the following:

  1. Docker installed locally or in the host server that you are using
  2. Access to docker and ability to run docker commands that create containers
  3. Internet access to download docker images

# Table of content

  1. Running using docker run command
  2. Running using docker-compose command
  3. Accessing the jenkins UI

# 1. Running using docker run command

So I want to run the latest version of Jenkins as a container in a detached mode, while mounting the Jenkins home path so the data can persist restarts.

docker run -d \
  --name my-jenkins \
  -p 8099:8080 \
  --restart=on-failure:10 \
  -v ~/apps/jenkins:/var/jenkins_home \
   jenkins/jenkins:latest

This is an explanation of the above used flags:

  • -d instructs docker to run the container in a detached mode. If this command is not used, the container will be run as a blocking process in the current terminal session.
  • --name gives the container a meaningful name. If it is not used a random name will be used.
  • -p this is used to mount the container ports to the host. In our case, the container port 8080 is mapped to the localhost 8099
  • --restart argument is used to instruct docker to restart the container if it fails for any reason. The value supplied on-failure:10 means that the container will only be restarted if there is a failure and that it will only happen 10 times before docker gives up.
  • -v is used to map container paths to local path. Containers are ephemeral services that don’t persist state. When a container stops or restarts all the data will be lost. Mounting a volume this way ensures that the data is saved in the local path that can be re-used when the container restarts. In our case, we are mounting Jenkins home /var/jenkins_home where Jenkins data is stored to local path ~/apps/jenkins.
  • Lastly, the jenkins/jenkins:latest defines the image to be used. We are using the jenkins/jenkins image, fetching the latest tag. If you have a specific version of jenkins that you want to use you can specify it with jenkins/jenkins:<version> like jenkins/jenkins: 2.315-alpine

This is the output of the above command in my terminal:

&#x276F; docker run -d \
  --name my-jenkins \
  -p 8099:8080 \
  --restart=on-failure:10 \
  -v ~/apps/jenkins:/var/jenkins_home \
   jenkins/jenkins:latest
Unable to find image &#039;jenkins/jenkins:latest&#039; locally
latest: Pulling from jenkins/jenkins
955615a668ce: Pull complete
cd7e184186ab: Pull complete
0fb38fc696f5: Pull complete
b3586488ea64: Pull complete
671c689e6abc: Pull complete
37ba6b191a9b: Pull complete
2f8e68e4f802: Pull complete
814bd5b7da6c: Pull complete
9d9ec91cbbba: Pull complete
cd9bf0229526: Pull complete
5b0ef807075b: Pull complete
3631bbdd3b86: Pull complete
a2871ddb67d1: Pull complete
9c69392dbfe4: Pull complete
70c625a6825d: Pull complete
5dc6266a42a7: Pull complete
38a2ace6a021: Pull complete
Digest: sha256:67494cdb3f078e9194320cf861d7449b7f2fe55d73861710f42d4650e3df2c98
Status: Downloaded newer image for jenkins/jenkins:latest
40a7a23b2fa16d467dd8c1987edb20408977fedcba8108a9426df7ee4e5f643b

Now that the container is running, let us check the processes:

&#x276F; docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS         PORTS                                                  NAMES
2b3b69e01102   jenkins/jenkins:latest   "/sbin/tini -- /usr/&#x2026;"   8 seconds ago   Up 8 seconds   50000/tcp, 0.0.0.0:8099->8080/tcp, :::8099->8080/tcp   my-jenkins

Logging in and running commands:

&#x279C; docker exec -it my-jenkins /bin/bash
jenkins@2b3b69e01102:/$ cat /var/jenkins_home/secrets/initialAdminPassword
102dc64be5b84383adaf28709c04e3f9
jenkins@2b3b69e01102:/$

Or:

&#x279C; docker exec -it my-jenkins cat /var/jenkins_home/secrets/initialAdminPassword
102dc64be5b84383adaf28709c04e3f9

Tail follow logs:

docker logs 2b3b69e01102 -f

# Cleaning up

First, stop the container:

&#x279C; docker stop my-jenkins
my-jenkins

Then remove the stopped container:

&#x279C; docker rm my-jenkins
my-jenkins

# 2. Running using docker-compose command

This docker-compose yaml code achieves the same functionality in a codified way. This is advantageous as you can check it in a source code management system.

Save it as docker-compose.yml

version: &#039;3.9&#039;
services:
  jenkins:
    restart: on-failure:10
    image: jenkins/jenkins:latest
    container_name: my-jenkins
    ports:
      - 8099:8080
    volumes:
      - ~/apps/jenkins:/var/jenkins_home

Bringing up

&#x279C; docker-compose up -d
Creating my-jenkins ... done

This will bring up the Jenkins container in a detached mode.

Check docker processes:

&#x276F; docker-compose ps
   Name                 Command               State                          Ports
---------------------------------------------------------------------------------------------------------
my-jenkins   /sbin/tini -- /usr/local/b ...   Up      50000/tcp, 0.0.0.0:8099->8080/tcp,:::8099->8080/tcp

To execute commands, use the exec. Example how to get the default password:

&#x279C; docker-compose exec jenkins /bin/bash
jenkins@8cb79854cee8:/$ cat /var/jenkins_home/secrets/initialAdminPassword
62ac442a3d334221a60cb5b2157a6149
jenkins@8cb79854cee8:/$

Or:

&#x279C; docker-compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
62ac442a3d334221a60cb5b2157a6149

Tail follow logs:

docker-compose logs -f

# Cleaning up

Stop the containers:

&#x276F; docker-compose stop
Stopping my-jenkins ... done

Then remove them, you will be prompted to confirm:

&#x279C; docker-compose rm
Going to remove my-jenkins
Are you sure? [yN] y
Removing my-jenkins ... done

# 3. Accessing the Jenkins UI

Now that we have our Jenkins running, we can access it in the UI using the server or local IP and the port that we mounted (in our case 8099).

Once the server is up, use the command to get the password and click Continue.

docker-compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
Citizix - Jenkins Init page
Citizix – Jenkins Init page

You should be able to set up and use your Jenkins now.

# Conclusion

Up to this point, we managed to set up Jenkins using docker while persisting the data in a locally mounted volume.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy