Dotnet Core Series
Jenkins is an open source “automation server” written in Java. It more than a typical build system / tool. With its additional features and plugins; it can help to automate the non-human part of the software development process. Its a server based system that needs a servlet container such as Tomcat. There are number of plugins available for integration with different version control systems and databases, setting up automated tests using the framework of our choice including MSTest and NUnit and doing lot more during the build than compiling the code. If Java and Servlet Containers are not your daily food; running Jenkins in the Docker provides enough black box around these that getting started with it cant be more simpler. There is an official image on the Docker Hub and we just need to map its two exposed port; one for its web interface and the other that its additional agents uses to connect to the server. All that needs to run its instance is docker run –p 8080:8080 –p 50000:50000 jenkins; we can optionally map the container’s /var/jenkins_home to some local folder as well. To learn more options that can be set using the environment variables like JVM options; visit https://hub.docker.com/_/jenkins
We can use Jenkins to build Dotnet Core projects; all we need is to install the Dotnet Core SDK on the system running the Jenkins. For the Container; we can expand the official image and write a Dockerfile to install the required things; but first we need to check which Linux jenkins image is based on and for that; do this
Knowing that its Debian 8 and its running the things under jenkins user; lets make a Dockerfile for our custom Jenkins docker image
- Note that we used information from https://www.microsoft.com/net/core#linuxdebian on how to install the latest Dotnet Core SDK on Debian
- Note that we added git plugin as per guideline at https://github.com/jenkinsci/docker where this official image is maintained; they have provided the install-plugins.sh script; and we can install the plugins while making the image; and we will not have to reinstall these plugins when running the Jenkins
If we build this Dockerfile and tag the image as dotjenkins; we can run it using docker run –rm –p 8080:8080 –p 50000:50000 dotjenkins; running on a console is required so we can get the initial admin password from the info that gets emitted; its required on the first run setup wizard when we will open the http://localhost:8080
- Visit Dockerfile; if you need the heads up on how to build Docker image from such file
- During the setup; you can choose Custom Plugins; and then select none; and we will have the minimalist Jenkins ready to build the Dotnet Core project from Git Repository
You can setup a test project; giving https://github.com/khurram-aziz/HelloDocker as Git path that has a Dotnet Core MVC application
And then can use Execute shell Build step type and enter the familiar dotnet restore and dotnet build commands to build the Dotnet Core application with the Jenkins
Once the test job is setup; we can build it; and it will download the code from Git and build it as per the steps we have defined. We can see the Console output from the web interface as well!
If you are following the Dotnet Core Series; in the last post; Docker Registry; we also needed to build the mvcapp Docker Container after publishing the Mvc application. In that post; the developer had to have the Docker for Windows installed, as to build the Docker image; we need the Docker Daemon; and we also needed the access of the Docker Registry so we can push the Mvc application as the Docker Container from where the Swarm Nodes will pick it when System Administrator will deploy the “Stack” on the Docker Swarm. We can solve this using the Jenkins; that it can not only automate this manual work; but also we will neither need Docker for Windows at the developer machine nor will need to give access of Docker Registry to the developer.
To build Docker Container Image; from Jenkins running in Docker Container; we first need to technically assess how it can be done.
- We need to study the Dockerfile of Jenkins at its GitHub Repo, as its creating jenkins user with uid 1000 and running the things under this user.
- We will need the Docker CLI tools in the container
- We will need the access of Docker Daemon in the container so that it can build the Docker Images using the Docker daemon
Lets make a separate Dockerfile first to technically assess it without the Jenkins overhead.
If we build and tag the above Dockerfile as dockcli; we can run it as docker run -v /var/run/docker.sock:/var/run/docker.sock -it dockcli
- Note that we exposed /var/run/docker.sock file as VOLUME in the Dockerfile; so that we can map it when running the container passing the docker.sock file of the Docker Daemon where its “launching” this way we dont need to run the Docker Daemon in the Container and we can “reuse” the Docker Daemon where our image will run; there exists “Docker in Docker” image using which we can run the Docker Daemon inside the Container; but we dont need it here
- We created a jenkins user similar to how its made and configured in the official Jenkins image
- We need to add jenkins into sudoers (and for that we also need to install sudo first) so we can access docker.sock using sudo; else it will not have enough permissions
With these arrangements we can access the Docker Daemon from with in the Docker Container!
Now lets add back this work to our dotjenkins Dockerfile; so we can create the Docker Image after the Dotnet Core build in the Jenkins. Here’s the final Dockerfile
Lets run our customized Jenkins image using docker run --name jenk --rm -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock dotjenkins
We can now add Docker Image Creation step in our project build steps
- Note the usage of Jenkins variable as the tag for the image we are creating
If we do a Jenkins build; we will see the Docker step output in the Console Output and shortly afterwords we will have the required image in the Docker Daemon where Jenkins Container is running
We can use docker-compose to define all the related switches needed to run the docker image so it becomes a simple docker-compose up command. On the similar lines; we can now add additional step to push the generated Docker image to the Docker Registry!