Greetings, fellow developers! My name is Tristan and I’m excited to share with you my journey on setting up a Docker image build pipeline for a .NET Core application using Jenkins.
In this post, we will walk through the process of setting up a Docker image build pipeline for a .NET Core application using Jenkins. We will cover the prerequisites, such as installing and configuring Jenkins, and then show you step-by-step instructions for creating a Jenkins pipeline that will build a Docker image from your .NET Core code. We will also cover some tips for troubleshooting common issues and for deploying your image to DockerHub.
By the end of this tutorial, you will have a working pipeline for building and deploying your .NET Core application as a Docker image, and you will have a better understanding of how Jenkins can be used to automate your CI/CD process.
Before we begin, I want to assume that you already have an Ubuntu server set up and Docker is already installed on it. If that is not the case, not to worry you can easily install Docker by following the instructions provided by Docker’s official documentation.
Also your source code should have a Dockerfile. A Dockerfile is a script that contains instructions for building a Docker image. It specifies the base image, the dependencies, the environment variables, and other configurations needed to run the application inside a container. this can be easily generated by an IDE such as Rider.
In this tutorial we will be using an Ubuntu server as the environment and It is assumed that you are familiar with the basic concepts of Docker.
Starting a Jenkins container
Alright, let’s get started. The first step in setting up our Jenkins pipeline is to run the following command on your Ubuntu server :
docker run --name jenkins --user root -d --privileged -v jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -p 50000:50000 --restart=always jenkins/jenkins:lts-jdk11
This command does the following:
- it specifies the container name as jenkins
- it runs the container with root user
- it runs the container in detached mode
- it runs the container with privileged access
- it maps the host directory jenkins_home to the container’s /var/jenkins_home
- it maps the host’s /var/run/docker.sock to the container’s /var/run/docker.sock
- it maps container ports 8080 and 50000 to host ports 8080 and 50000 respectively
- it runs the container with always restart policy
- it runs the Jenkins image jenkins/jenkins:lts-jdk11
The -v options maps the host directories to the container, it allows the container to store data and configuration on the host file system, so that the data can persist even if the container is deleted.
Mapping the /var/run/docker.sock allows Jenkins container to interact with the Docker daemon on the host and perform operations like building, pushing and pulling images.
The –restart=always flag makes sure that the container starts automatically when the host is restarted.
It’s worth mentioning that the jenkins/jenkins:lts-jdk11 image used in this command is the long-term support (LTS) version of Jenkins that uses JDK 11. This is the recommended version of Jenkins for most users, as it is the most stable version and receives regular security updates. However, you can use the jenkins/jenkins:latest instead, if you’d like to use the latest version of Jenkins.
Setting up the container
After starting the Jenkins container, you will need to install some additional packages inside the Jenkins container in order for it to be able to build .NET Core applications.
Please keep in mind that each time you start the Jenkins container, these packages will need to be installed again. To make sure that they are installed automatically every time the container starts, you can add them to a shell script and run that script when starting the container.
To do so you will first need to obtain the container ID of your Jenkins container.
You can use the command docker ps to list all running containers on your system. You can look for the container with the name you used while creating container, in our case jenkins, and use the container ID that corresponds to that container.
Once you have obtained the container ID of your Jenkins container, you can use the docker exec command to run a command inside the container.
In this case, you will need to use the following command to start a bash shell inside the container with root privileges:
docker exec -it -u root Container_ID bash
This command does the following:
- -it option allows for an interactive terminal session
- -u root option specifies that the command should run as the root user
- Container_ID should be replaced with the container ID that you obtained from docker ps command
- bash is the command that will be executed inside the container, in this case it starts a bash shell
This command will give you a shell inside the running container and you will be able to perform any actions that you would like to perform as root inside the container.
Once you have started a bash shell inside the Jenkins container using the docker exec command, you will be able to run commands inside the container to install the necessary packages.
The first command you should run is:
curl -sSL https://get.docker.com/ | sh
This command downloads and runs the script provided by Docker that adds the Docker repository to your system and installs the latest version of Docker. This will give you access to the docker command inside the Jenkins container, so that you can use it to build and deploy Docker images.
The next command is:
apt-get update && apt-get install -y apt-transport-https
This command will updates the package lists to obtain the latest package versions and then installs the package apt-transport-https which is necessary to securely download packages over HTTPS, which is the default package manager for Ubuntu and many other Linux distributions.
The final command is:
apt-get install -y libicu-dev
This command installs the package libicu-dev which is a C/C++ and Java library that provides Unicode and Globalization support, it is a necessary dependency for .NET Core on Linux, it’s required for .NET Core runtime to function properly and should be installed before installing .NET Core SDK.
Please note that these commands are meant for Ubuntu and some other Linux distributions, If you are using a different distribution, you may need to adjust the commands accordingly, check the official documentation.
Once you have installed the necessary packages inside the Jenkins container, you will also need to install several Jenkins plugins.
To install these plugins, you will need to navigate to the Jenkins web interface by visiting http://your-server-ip:8080 in a web browser.
Once you are in the Jenkins web interface, you can go to the Dashboard, then select Manage Jenkins from the menu on the left. In the Manage Jenkins page, select Plugin Manager.
In the Plugin Manager page, you can find and install the following plugins:
- CloudBees Docker Build and Publish
- Docker Pipeline
- Docker Build Step
- .NET SDK Support
You do not have to restart Jenkins after the installation. But if you do, you will have to install the necessary packages inside the Jenkins container again.
Creating the build pipeline
Create a Jenkins Freestyle project via the web interface. This type of project in Jenkins allows you to configure various build options and settings.
To create the Jenkins Freestyle project, log in to the Jenkins web interface and navigate to the “New Item” page. Give the project a name and select the “Freestyle project” type.
For the purpose of this guide, we will be using Jenkins to pull the source code from a GitHub repository and use it to build a Docker image. Once the image is built, we will push it to DockerHub, which is a popular online repository for storing and sharing Docker images.
In the General section of the Jenkins Freestyle project configuration page, you will need to check the “GitHub project” checkbox. Once the checkbox is selected, a field will appear where you can enter the URL of your GitHub repository. This will allow Jenkins to pull the source code from the repository when building the project.
In the “Source Code Management” section of the Jenkins Freestyle project configuration page, you will need to select the “Git” option. This will allow Jenkins to pull the source code from a Git repository, such as GitHub.
Once the “Git” option is selected, you will need to enter the URL of your GitHub repository in the “Repository URL” field. You should use the same URL you entered in the “General” section.
You will also be able to provide the credentials for the repository, if it is private, otherwise you can skip this step. Jenkins will use these credentials to authenticate with the repository when pulling the source code.
You can also configure other option available in this section such as choosing a specific branch or tag, or configure advanced options for git polling.
In the “Build Triggers” section, you have the option to configure how and when the project should be built. To set the project to automatically build at regular intervals, you will need to check the “Poll SCM” checkbox.
Once the checkbox is selected, a field labeled “Schedule” will appear, where you can enter a CRON expression to define the schedule on which Jenkins will poll the GitHub repository for changes.
A CRON expression is a string of characters that represent a schedule.
The most simple and common schedule is to build every minute, this can be achieved using the CRON expression “* * * * *” which tells Jenkins to poll the GitHub repository every minute.
This is useful if you want to build your project automatically every time there is a new change in the repository, otherwise, you can set a custom schedule that works best for you.
It’s important to keep in mind that Jenkins will build the project every time the code changes and that this can consume a lot of resources, so it’s important to set a schedule that works best for your use case.
In the “Build” section, you can configure the steps that Jenkins should take when building the project.
To build a .NET Core project, you will need to add a build step of type “.NET: Build project (build)“. This build step will use the .NET SDK to build your project.
We will set the .NET SDK version to .NET 6.0 by selecting it from the dropdown menu. You will also need to enter the path to your project or solution file, this is usually in the format of “solution\project.csproj”
This step will invoke the dotnet build command to build the project, it is also possible to configure other options such as the configuration (Debug or Release) or add additional command line arguments.
Add an “Execute shell” step to run a shell command.
To authenticate the Jenkins node with DockerHub, you can add a shell command to execute a docker login command. The command should be in the format of docker login -u <username> -p <password>. This will login with the specified credentials, allowing Jenkins to push the built Docker image to the specified DockerHub repository.
Add a final step of type “Docker Build and Publish” to create and push the Docker image to a specified Docker registry.
You will need to enter the repository name and the Docker registry URL. The repository name is the name of the repository on the Docker registry where the image should be pushed. The Docker registry URL is the URL of the registry, for example, DockerHub is https://index.docker.io/v1/
That concludes the guide on how to create a Jenkins Freestyle project to automate the building and deploying of a .NET Core application as a Docker image.
I hope this guide has been helpful in understanding the process of setting up a Jenkins pipeline for building and deploying Docker images, and that you were able to successfully create your own pipeline.
Don’t hesitate to reach out if you have any questions or if there is anything else I can assist you with. Thank you for reading!