Many companies struggle with their legacy IT applications – also coined the “Shit Of Yesterday” (SOY). These applications have become unmaintainable and unmanageable. This is partly due to outdated design paradigms in software development. In a waterfall methodology, project specifications are ought to be captured, documented and implemented in a sequential way. Countering this, newer paradigms – such as agile development and DevOps – offer a more realistic and contemporary view on delivering software. One aspect of it considers the step from codebase to deployment, which is not a trivial step in legacy IT.
Continuous Delivery
In this article, I will explore the set-up for Continuous Delivery of a Java software application. This means that every change to the software code base can be released and deployed automatically to UAT (User Acceptance Testing) or Production environments. This means:
- Deploying to a new environment is just a click on a button
- Releasing new functionality becomes a predictable, routine task
- Maintenance and management of applications is cheaper, faster and better
The desired flow becomes:
Hands-on: Infrastructure
Service and tools
For this demo, we will use:
- Azure for Virtual Machines – Infrastructure as a Service (IaaS)
- Ubuntu Server as guest OS
- Jenkins (Blue Ocean) as continuous delivery service
- Maven as build tool for Java
- Putty, SSH client for Windows
- GitHub as version control repository for source code
- Apache Archiva, as build artefact repository manager
Set-up
We will set up our pipeline as follows:
Step-by-step:
- Azure servers: To get started, I will use two virtual machine Ubuntu Servers from Microsoft Azure. For the demo-purposes, even the cheapest servers will do fine (2x B1S – €4.32/month). To save money, you can stop the servers whenever you’re not using them or use the auto-shutdown feature. Only the disk space will be charged then.
On a Windows workstation, you can login via SSH to the servers using Putty: http://www.putty.org/ - GitHub: Set up a GitHub repository for your project, and add a webhook in its settings: {YOUR_JENKINS_URL}/github-webhook/
- Jenkins: Install the latest version of Jenkins on the INFR server. Instructions: https://pkg.jenkins.io/debian-stable/ .
- SSH into your machine and create /var/lib/jenkins/env/server.xml (for Maven)
- Optional: SSH into your machine and change the Jenkins port to 8080 in /etc/default/Jenkins
- Make sure to open the port in the firewall (use Azure Portal)
- Login to Jenkins and install global tools: Java SDK, Maven
- Login to Jenkins and install plugins: Blue Ocean, SSH Agent
- Open Jenkins Blue Ocean, and add a new pipeline on your GitHub project with an empty Jenkinsfile
- Add credentials to Jenkins:
PRODUCTION_SERVER | IP / DNS name of the PROD server |
PRODUCTION_SERVER_USER | Username to login on PROD server |
PRODUCTION_SSH | Username and SSH key to login on PROD server |
- Apache Archiva: Install Archiva. Instructions: https://www.mkyong.com/maven/how-to-install-apache-archiva-in-ubuntu/
- Debian repository: Create a Debian repository in /var/lib/repo with reprepro. Instructions: https://blog.packagecloud.io/eng/2017/03/23/create-debian-repository-reprepro/ . Serve this repo with Apache2 or any other web server.
Hands-on: Code
Service and tools
- Spring MVC, as bootstrap for the Hello World Java application
Set-up
- Set up a new java application (with Spring Boot)
- Add the pom.xml for Maven
- Config with your repository
- Add a Jenkinsfile
- Add Debian packaging instructions and files
- Initialize a Git repository and push it to the remote repository on the master branch
For a bootstrap of the project, see https://github.com/Dockflow/ciboilerplate
Done, now start coding!
Every commit to the codebase that successfully passes the automatic test now triggers an automatic build and deploy to production.
Also, all artefacts of previous builds are saved in a repository, so one could easily revert to a previous version if things go wrong.
Please feel free to ask questions or share your opinion on this setup, cheers!