Debian Packages For Spinnaker
A Debian “package”, or a Debian archive file, contains the executable files, libraries, and documentation associated with a particular suite of programs or set of related programs. Normally, a Debian archive file has a filename that ends in .deb.
Here in this blog, you will learn why you should use Debian packages in your Spinnaker CI/CD pipelines.
Why use Debian packages?
Spinnaker is flexible to use any dependency management system. It is predisposed to manage Debian packages due to its default settings with Rosco, Orca, and Jenkins.
Spinnaker checks for an archived package with a .deb suffix within Jenkins. It also grabs the version from the package and automatically appends it to the package name within Rosco. This makes it easy to specify your package in Rosco without the version number, during the bake provisioning process it will install the version that was specified by the build: myapp-1.16.8
Using Jenkins and the Netflix Nebula plugin, you can build a Debian package, containing the executable JAR and configuration files.
Creating Debian packages
Creating a Debian package can be done through various open-source packaging tools. If you’re using Java, using the OS Package library is a good place to start. Also, use the packaging tools provided by Debian. Install Gradle and use the below content for creating the Debian package.
Example: Debian package with OSPackage Gradle plugin
Begin by creating a build.gradle. Below is an example of what a Gradle file might look like for an application that builds a jar.
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'nebula.ospackage-base'
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE"
classpath 'com.netflix.nebula:gradle-ospackage-plugin:3.1.0'
}
}
jar {
manifest { attributes('Main-Class': 'hello.Application')}
baseName = 'myapp'
version = '1.16.8'
}
springBoot {
// Allows us to run the jar directly from the command line, e.g. ./springboot-0.0.1.jar
executable = true
// Excludes the devtools package from production builds
excludeDevtools = true
embeddedLaunchScriptProperties = [useStartStopDaemon: 'false']
}
repositories {
mavenCentral()
jcenter()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web"){
exclude module: "spring-boot-starter-tomcat"
}
compile 'org.apache.tomcat.embed:tomcat-embed-*:7.0.59'
compile("org.springframework.boot:spring-boot-starter-actuator")
compile 'com.google.api-client:google-api-client:1.22.0'
compile 'com.google.oauth-client:google-oauth-client:1.22.0'
compile 'com.google.http-client:google-http-client-jackson2:1.22.0'
compile 'com.google.oauth-client:google-oauth-client-jetty:1.22.0'
compile 'org.apache.commons:commons-lang3:3.4'
compile 'com.google.apis:google-api-services-monitoring:v3-rev10-1.22.0'
compile 'com.google.apis:google-api-services-compute:v1-rev105-1.20.0'
compile 'joda-time:joda-time:2.9.4'
compile 'com.google.code.gson:gson:2.7'
compile group: 'postgresql', name: 'postgresql', version: '9.1-901-1.jdbc4'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('com.jayway.jsonpath:json-path')
compile 'javax.xml.bind:jaxb-api:2.3.0'
}
task fatJar(type: Jar) {
destinationDir = file("$rootDir/pkg_scripts")
manifest {
attributes('Main-Class': 'hello.Application')
}
baseName = 'myapp' + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
wrapper {
gradleVersion = '5.0'
}
task packDeb(type: Deb, dependsOn: bootRepackage) {
packageName = 'myapp'
version = 1.16.8
requires('openjdk-7-jre-headless')
from('build/libs/.') {
into "/opt/appfolder"
}
postInstall = file('pkg_scripts/deb/postInstall.sh')
from(jar.outputs.files) {
into 'lib'
}
from('build/scripts') {
into 'bin'
fileMode = 0550
}
from(configurations.runtime) {
into 'lib'
}
}
}
pkg_scripts/deb/postInstall.sh looks like this
#!/bin/bash
ln -sfn /opt/myapp/myapp-1.16.8.jar
update-rc.d -f myapp defaults
Then build your Debian package based on your Gradle build file:
gradlew build fatJar packDeb
If the build succeeds and the tests pass, the build artifact (JAR file) is bundled into a Debian package using the Nebula Packaging plugin, then you should find a Debian package in the following path:
./build/distributions/myapp_1.16.8_all.deb
Summary/Conclusion:
Finally, after a completely successful build, you found the Debian package in the relevant location. Based on the source code in Debian, you can access the desired output. You can install the Debian package by using the following command.
Install debian package
dpkg -i myapp_1.16.8_all.deb
Although this was a brief, whirlwind overview of deployment tools, it shows the power of delivery tools like Spinnaker, when seamlessly combined with other tools, like Jenkins and the Nebula plugins. Together, these tools are capable of efficiently, repeatedly, and securely deploying large numbers of containerized and non-containerized applications to a variety of private, public, and hybrid cloud infrastructure.
If you want to know more about Spinnaker or request a demonstration, please book a meeting with us.
OpsMx is a leading provider of Continuous Delivery solutions that help enterprises safely deliver software at scale and without any human intervention. We help engineering teams take the risk and manual effort out of releasing innovations at the speed of modern business. For additional information, contact us.