Kyle Rockman
Lead Infrastructure Engineer OpsLevel.com
Going over the workflow from code commit to built and tested docker image ready for deployment
Kyle Rockman
View slides in real time:
http://slides.com/rocktavious/docker-jenkins-and-you/live
The highlevel concept of the organization of phases taken in a CI/CD world
A Jenkins DSL of the discrete actions taken to achieve the buildflow
The bundle/package which is produced from your project generally during its "Build" phase
build - test - publish - release
KEY POINT:
The Artifact that was tested is the same artifact that was released
This is the most common buildflow currently in use by almost all of the MMF projects using docker containers
PROJECT_ROOT
├─── DockerFile
├─── docker
│ ├─── Build
│ │ ├─── *.yml
│ │ └─── *.properties
│ ├─── Test
│ │ ├─── *.yml
│ │ └─── *.properties
│ └─── Release
│ ├─── *.yml
│ └─── *.properties
└─── ...
Only two changes from v1
PROJECT_ROOT
├─── DockerFile
├─── docker
│ ├─── Build
│ │ ├─── *.yml
│ │ └─── *.properties
│ ├─── Test
│ │ ├─── *.yml
│ │ └─── *.properties
│ └─── Release
│ ├─── *.yml
│ └─── *.properties
└─── ...
PROJECT_ROOT
├─── Jenkinsfile
└─── ...
Documentation: http://bit.ly/1TLbSQt
node() {
sh 'ls -al'
}
Workflow Steps:
Its just groovy with some special jenkins objects/methods mixed in
def tests = [:]
for ( i = 0 ; i < test_configs.size() ; i++ ) {
def test_config = test_configs[i][1]
tests["parallel_${i}"] = {
node('docker') {
git url: 'https://github.com/ua/sample.git'
println test_config
}
}
}
parallel tests
node('docker'){
retry(5){
sh 'docker pull my_image_name'
}
withEnv("NAMESPACE=my_namespace") {
try {
sh 'docker-compose -p "${NAMESPACE}" run unittest'
} finally {
sh 'docker-compose -p "${NAMESPACE}" stop || true'
sh 'docker-compose -p "${NAMESPACE}" rm --force || true'
}
}
}
stage "Build"
node('docker'){
checkout scm
sh 'docker build --force-rm --pull=true -t "${DOCKER_REGISTRY_HOST}/parlour/parlour:example" -f "./parlour.dockerfile" .'
retry(5) {
sh 'docker push "${DOCKER_REGISTRY_HOST}/parlour/parlour:example"'
}
}
stage "Test"
node('docker'){
checkout scm
sh 'sed "s|CIVERSION|`git rev-parse HEAD`|g" "./docker-compose.yml" > ./docker-compose-ci.yml'
retry(5) {
sh 'docker-compose -f "./docker-compose-ci.yml" pull'
}
def extra_env = "BUILD_NAMESPACE=" + env["BRANCH_NAME"].replaceAll(/[\W-]/, "_").toLowerCase() + "_" + env["BUILD_NUMBER"]
withEnv(extra_env) {
try {
sh 'docker-compose -f "./docker-compose-ci.yml" -p "${BUILD_NAMESPACE}" run -d -T ci-unittest > CONTAINER_NAME.txt'
sh 'docker logs -f `cat CONTAINER_NAME.txt`'
sh '(docker cp `cat CONTAINER_NAME.txt`:/out/. ./out)|| true
sh 'docker wait `cat CONTAINER_NAME.txt`'
} finally {
sh 'docker-compose -f "./docker-compose-ci.yml" -p "${BUILD_NAMESPACE}" stop || true'
sh 'docker-compose -f "./docker-compose-ci.yml" -p "${BUILD_NAMESPACE}" rm --force || true'
}
}
step([$class: 'JUnitResultArchiver', testResults: 'out/TEST-*.xml'])
}
PROJECT_ROOT
├─── parlour.dockerfile
├─── Jenkinsfile
├─── docker-compose.yaml
└─── ...
docker-compose run unittest
...
docker-compose run pep8
...
docker-compose run smoketest
docker-compose run ci-unittest
...
docker-compose run ci-pep8
...
docker-compose run ci-smoketest
CI Runs Like
Local Runs Like
By Kyle Rockman