How to Use Docker in Jenkins Declarative Pipeline | Day 27 of 90 Days of DevOps

Ajit Fawade
5 min readAug 30, 2023

Hello, everyone!

I hope you are having a wonderful day and learning something new every day. Today, I will show you how to use Docker in the Jenkins declarative pipeline.

What is Docker?

Docker is a tool that allows you to create, run, and manage containers. Containers are isolated environments that contain everything you need to run an application, such as code, libraries, dependencies, and configuration. Containers are lightweight, portable, and scalable.

Docker provides various commands and features that help you work with containers, such as:

  • docker build: Builds an image from a Dockerfile.
  • docker run: Runs a command in a new container.
  • docker ps: Lists the running containers.
  • docker stop: Stops one or more running containers.
  • docker rm: Removes one or more stopped containers.
  • docker images: Lists the available images.
  • docker rmi: Removes one or more images.
  • docker pull: Pulls an image from a registry.
  • docker push: Pushes an image to a registry.

How to Use Docker Commands in Jenkins Declarative Pipeline?

To use Docker commands in the Jenkins declarative pipeline, you need to have:

  • Docker installed on your machine or server where Jenkins runs.
  • A Dockerfile that defines how to build your image for your application.
  • A Jenkinsfile that defines your pipeline using the declarative syntax.

In this tutorial, I will use the same Node.js app that I used in the previous blog post. The app is a simple to-do app that uses Express and EJS. The source code for the app is available on GitHub: [https://github.com/ajitfawade/node-todo-cicd.git]

The Dockerfile for the app looks like this:

# Use node:14-alpine as base image
FROM node:14-alpine
# Set /app as working directory
WORKDIR /app
# Copy package.json and package-lock.json files to /app
COPY package*.json /app/
# Install dependencies
RUN npm install
# Copy app source code to /app
COPY . /app/
# Expose port 8000
EXPOSE 8000
# Run app.js as entrypoint
CMD ["node", "app.js"]

The Jenkinsfile for the pipeline looks like this:

pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'docker build . -t node-todo-app'
}
}
stage('Run') {
steps {
sh 'docker run -d -p 8000:8000 --name node-todo-app node-todo-app'
}
}
}
}

This pipeline defines two stages: Build and Run. Each stage has one step that executes a shell command using the sh step.

The Build stage runs the docker build command to build the image from the Dockerfile in the current directory and tag it as node-todo-app.

The Run stage runs the docker run command to run a new container from the image and map port 8000 of the container to port 8000 of the host. It also names the container as node-todo-app.

To create and run this pipeline, follow these steps:

  1. Go to your Jenkins dashboard and click on New Item.
  2. Enter a name for your pipeline (e.g., Node Todo App with Docker) and select Pipeline. Then click OK.
  3. On the configuration page, scroll down to the Pipeline section and select Pipeline script from SCM from the Definition drop-down menu.
  4. Select Git from the SCM drop-down menu and enter the repository URL: [https://github.com/ajitfawade/node-todo-cicd.git]. You can leave the other fields as default.
  5. Under Build Triggers, select the GitHub hook trigger for GITScm polling. This will enable the pipeline to be triggered by GitHub webhooks.
  6. Click Save to save your pipeline.

Now, whenever you push any changes to your GitHub repository, your pipeline will be triggered automatically, and build and run your app using Docker.

You can also manually trigger your pipeline by clicking on Build Now on your Jenkins dashboard.

You can see the status and details of your pipeline under Build History. You can also click on Console Output to see the logs of your pipeline.

You can verify that your app is running by going to your browser and typing http://localhost:8000. You should see a to-do app where you can add, edit, and delete tasks.

However, there is a problem with this pipeline. If you run the pipeline more than once, you will get an error like this:

docker: Error response from daemon: Conflict. The container name "/node-todo-app" is already in use by container "8a5b9c7f8f6c6f5a5b9c7f8f6c6f5a5b9c7f8f6c". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.

This is because the docker run command tries to create a new container with the same name as the existing one. To avoid this error, we need to use a different approach to run the container.

How to Use Docker Syntax in Jenkins Declarative Pipeline?

To use Docker syntax in the Jenkins declarative pipeline, you need to have:

  • The same prerequisites as the previous section.
  • A Jenkinsfile that defines your pipeline using the declarative syntax and the Docker syntax.

The Jenkinsfile for the pipeline looks like this:

pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'docker build . -t node-todo-app'
}
}
stage('Run') {
agent {
docker {
image 'node-todo-app'
reuseNode true
}
}
steps {
sh 'node app.js'
}
}
}
}

This pipeline defines two stages: Build and Run. The Build stage is the same as the previous one.

The Run stage has a different agent directive that uses the docker option. This option allows you to specify a Docker image and other parameters to run a container for this stage.

The image parameter specifies the image name or ID to use for the container. In this case, we use the node-todo-app image that we built in the previous stage.

The reuseNode parameter specifies whether to reuse the same node for this stage as the previous one. In this case, we set it to true to avoid creating a new node for this stage.

The steps block contains one step that executes a shell command using the sh step. In this case, we run node app.js to start the app inside the container.

To create and run this pipeline, follow the same steps as in the previous section.

Now, whenever you run the pipeline, you will not get any error because the container will be created and removed automatically for each run.

You can verify that your app is running by going to your browser and typing http://localhost:8000. You should see a to-do app where you can add, edit, and delete tasks.

I hope this blog post helps you understand how to use Docker in the Jenkins declarative pipeline. In the next blog post, I will show you how to use different types of stages, steps, directives, and options in the Jenkins declarative pipeline.

If you have any questions or feedback, please feel free to connect with me on:

Thank you for reading! 😊

--

--