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:
- Docker installed locally or in the host server that you are using
- Access to docker and ability to run docker commands that create containers
- Internet access to download docker images
Table of content
- Running using
docker run
command - Running using
docker-compose
command - 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 port8080
is mapped to the localhost8099
--restart
argument is used to instruct docker to restart the container if it fails for any reason. The value suppliedon-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 thejenkins/jenkins
image, fetching the latest tag. If you have a specific version of jenkins that you want to use you can specify it withjenkins/jenkins:<version>
likejenkins/jenkins: 2.315-alpine
This is the output of the above command in my terminal:
❯ 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 'jenkins/jenkins:latest' 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:
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b3b69e01102 jenkins/jenkins:latest "/sbin/tini -- /usr/…" 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:
➜ docker exec -it my-jenkins /bin/bash
jenkins@2b3b69e01102:/$ cat /var/jenkins_home/secrets/initialAdminPassword
102dc64be5b84383adaf28709c04e3f9
jenkins@2b3b69e01102:/$
Or:
➜ 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:
➜ docker stop my-jenkins
my-jenkins
Then remove the stopped container:
➜ 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: '3.9'
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
➜ docker-compose up -d
Creating my-jenkins ... done
This will bring up the Jenkins container in a detached mode.
Check docker processes:
❯ 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:
➜ docker-compose exec jenkins /bin/bash
jenkins@8cb79854cee8:/$ cat /var/jenkins_home/secrets/initialAdminPassword
62ac442a3d334221a60cb5b2157a6149
jenkins@8cb79854cee8:/$
Or:
➜ docker-compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
62ac442a3d334221a60cb5b2157a6149
Tail follow logs:
docker-compose logs -f
Cleaning up
Stop the containers:
❯ docker-compose stop
Stopping my-jenkins ... done
Then remove them, you will be prompted to confirm:
➜ 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
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.