Docker and Jenkins.
Orchestrating Continuous Delivery
Software is eating the world
Key is Automation
Containers Codify
OS Config
How I build a Docker image?
$ docker run -ti ubuntu:12.10 bash
[a2b] apt-get update
[a2b] apt-get install curl
[a2b] exit
$ docker commit -m "curl installed" a2b username/image
$ docker build .
Jenkins: Docker and CD
- Docker Hub Notification: triggers downstream jobs when a tagged container is pushed to Docker Hub
- Docker Traceability: identifies which build pushed a particular container, displays on Jenkins builds page
- Docker Custom Build Environment: specifies customized build environments as Docker containers
- Docker: use a docker host to dynamically provision a slave, run a single build, then tear-down
- Build and Publish : builds projects that have a Dockerfile and pushes the resultant tagged image to Docker Hub
Build, Test, & Deploy Docker Images from Jenkins
Docker Hub Notification Plugin
Docker Traceability Plugin
Docker Custom Build Environment Plugin
No More Build Jobs/Up/Downstreams PLEASE!!!!
Pipeline Plugin
Continuous Delivery as Code
Features of Pipeline Plugin
- Configuration in Source Repositories
- Less click-and-type, more code
- From simple to complex
- Survives Jenkins restarts & connection losses ($)
- Reusable Definitions
- Build history/trend segregated per branches
- UI ($ -> OSS)
Jenkinsfile (1/3)
stage 'compileAndUnit'
node {
git branch: 'master', url: 'https://github.com/lordofthejars/starwars.git'
gradle 'clean test'
stash excludes: 'build/', includes: '**', name: 'source'
stash includes: 'build/jacoco/*.exec', name: 'unitCodeCoverage'
step([$class: 'JUnitResultArchiver', testResults: '**/build/test-results/*.xml'])
}
stage 'codeQuality'
parallel 'pmd' : {
node {
unstash 'source'
gradle 'pmdMain'
step([$class: 'PmdPublisher', pattern: 'build/reports/pmd/*.xml'])
}
}, 'jacoco': {
node {
unstash 'source'
unstash 'unitCodeCoverage'
gradle 'jacocoTestReport'
}
}
Jenkinsfile (2/3)
stage 'assemble-binaries'
node('linux') {
unstash 'source'
withEnv(["SOURCE_BUILD_NUMBER=${env.BUILD_NUMBER}"]) {
gradle 'assemble'
}
}
input message: "Deploy Application to QA ?"
stage name: 'Deploy to QA', concurrency: 1
node {
echo "Application Deployed to QA."
}
Jenkinsfile (3/3)
gradle = load 'jenkins/gradle.groovy'
withCredentials([[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'MyID', usernameVariable: 'GIT_USERNAME',
passwordVariable: 'GIT_PASSWORD']]) {
sh "git tag -a some_tag -m 'Jenkins'"
sh "git push https://${env.GIT_USERNAME}:${env.GIT_PASSWORD}@ --tags"
}
def mvnHome tool 'Maven 3.3.3'
sh "${mvnHome}/bin/mvn -B verify"
Docker Pipeline Integration
Jenkinsfile (1/2)
docker.withRegistry('https://lordofthejars-docker-continuous_delivery.bintray.io', 'd4fc3fa9-39f7-47ea-a57c-795642f90989') {
git 'git@github.com:lordofthejars/busybox.git'
def newApp = docker.build "lordofthejars-docker-continuous_delivery.bintray.io/lordofthejars/javatest:${env.BUILD_TAG}"
newApp.push()
}
docker.image('lordofthejars/javatest').withRun {c ->
sh './executeTests.sh'
}
Jenkinsfile (2/2)
docker.image('maven:3.3.3-jdk-8').inside('-v ~/.m2/repository:/m2repo -u 1000:50') {
git '…your-sources…'
sh 'mvn -Dmaven.repo.local=/m2repo clean install'
}
docker.withServer('tcp://swarm.mycorp.com:2376', 'swarm-certs') {
docker.image('httpd').withRun('-p 8080:80') {c ->
sh "curl -i http://${hostIp(c)}:8080/"
}
}
def hostIp(container) {
sh "docker inspect -f {{.Node.Ip}} ${container.id} > hostIp"
readFile('hostIp').trim()
}
Different Ways of Doing Same Things with DSL
Simple Build for Pipeline Plugin
Jenkinsfile
simpleBuild {
machine = "hi-speed"
docker = "java:1.9"
env = [
FOO : 42,
BAR : "YASS"
]
git_repo = "https://github.com/cloudbeers/PR-demo"
before_script = "echo before"
script = 'echo after $FOO'
after_script = 'echo done now'
notifications = [
email : "foo@bar.com"
]
}
Conclusions
- Automation is the Key
- Docker Simplifies Environment Problems
- Jenkins is Ready For Docker and CD
- Pipleline as Code gives you Freedom
Only One Piece of the Jigsaw
Follow the Rules, Adapt to your Needs
It is not necessary to change.
Survival is not mandatory.
W. Edwards Deming