Deploy docker image with Jenkins
In this topic, I will try to cover my way to test
, build
and deploy
docker's images for my own projects
Prerequisite
Vagrant
VirtualBox
Jenkins 2.x
Nginx
Docker CE
Likes my older post about jenkins pipeline, we also make a public vagrant box for this post. Therefore, please open a new folder with a new Vagrantfile
then copy & paste below content into it
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "dotronglong/jenkins-docker"
config.vm.network "private_network", ip: "192.168.33.97"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
end
end
Let’s start it and have a coffee time :)
vagrant up
Then go to url http://192.168.33.97
with user admin
, password 123456
Pipeline — Docker
Let’s create pipeline job with following script
pipeline {
agent none
environment {
QUAY_REPO = 'quay.io/dotronglong/go-demo'
QUAY_REPO_TAG = 'latest'
}
stages {
stage('CheckOut') {
agent { label 'master' }
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/dotronglong/demo-jenkins-docker.git']]])
}
}
stage('Prepare') {
agent { label 'master' }
steps {
sh 'make get-go.sh'
}
}
stage('ResolveDependencies') {
agent { label 'master' }
steps {
script {
docker.image('golang:1.9').inside('') {
sh 'make deps'
}
}
}
}
stage('TestUnit') {
agent { label 'master' }
steps {
script {
docker.image('golang:1.9').inside('-v $WORKSPACE:/go/src/demo-jenkins-docker') {
sh '''
cd /go/src/demo-jenkins-docker
make test
'''
}
}
}
}
stage('Build') {
agent { label 'master' }
steps {
script {
docker.image('golang:1.9').inside('') {
sh 'make build'
}
}
}
}
stage('Deploy') {
agent { label 'master' }
steps {
script {
withDockerRegistry([credentialsId: 'quay-io-bot', url: 'https://quay.io']) {
docker.build('$QUAY_REPO:$QUAY_REPO_TAG', '-f Dockerfile .').push('latest')
}
sh 'docker rmi -f $QUAY_REPO:$QUAY_REPO_TAG'
}
}
post {
always {
deleteDir()
}
}
}
}
}
In this script, I will try to push image to docker repository; hence, it requires to add a credential first. Go to Jenkins
> Credentials
then add a credential, for example:
Now, we build job, and result should be similar to
TIPS
docker.image('your_image:your_image_tag')
lets you run a container from proposed image, theninside
allows you to run scripts inside newly created containerwithDockerRegistry
allows to specify your docker repository, default it would use hub.docker.comIn your system, you should create a new node, and mark it with a remindable name, such as
docker
instead of usingmaster
as always.
Conclusion
Running docker insides jenkins might make bad performance, however, it allows us to perform various actions without installation.
Should specify a credential via
withDockerRegistry
instead of giving it explicitly in pipeline script.Define
environment
variables is a convenient way to perform tasks in multiple purposes.
Appendix
The docker variable offers convenient access to Docker-related functions from a Pipeline script.
Methods needing a Jenkins agent will implicitly run a node {…} block if you have not wrapped them in one. It is a good idea to enclose a block of steps which should all run on the same node in such a block yourself. (If using a Swarm server, or any other specific Docker server, this probably does not matter, but if you are using the default server on localhost it likely will.)
Some methods return instances of auxiliary classes which serve as holders for an ID and which have their own methods and properties. Methods taking a body return any value returned by the body itself. Some method parameters are optional and are enclosed with []. Reference:
withRegistry(url[, credentialsId]) {…}
Specifies a registry URL such as https://docker.mycorp.com/, plus an optional credentials ID to connect to it.
withServer(uri[, credentialsId]) {…}
Specifies a server URI such as tcp://swarm.mycorp.com:2376, plus an optional credentials ID to connect to it.
withTool(toolName) {…}
Specifies the name of a Docker installation to use, if any are defined in Jenkins global configuration. If unspecified, docker is assumed to be in the $PATH of the Jenkins agent.
image(id)
Creates an Image object with a specified name or ID. See below.
build(image[, args])
Runs docker build to create and tag the specified image from a Dockerfile in the current directory. Additional args may be added, such as '-f Dockerfile.other --pull --build-arg http_proxy=http://192.168.1.1:3128 .'. Like docker build, args must end with the build context. Returns the resulting Image object. Records a FROM fingerprint in the build.
Image.id
The image name with optional tag (mycorp/myapp, mycorp/myapp:latest) or ID (hexadecimal hash).
Image.run([args, command])
Uses docker run to run the image, and returns a Container which you could stop later. Additional args may be added, such as '-p 8080:8080 --memory-swap=-1'. Optional command is equivalent to Docker command specified after the image. Records a run fingerprint in the build.
Image.withRun[(args[, command])] {…}
Like run but stops the container as soon as its body exits, so you do not need a try-finally block.
Image.inside[(args)] {…}
Like withRun this starts a container for the duration of the body, but all external commands (sh) launched by the body run inside the container rather than on the host. These commands run in the same working directory (normally a Jenkins agent workspace), which means that the Docker server must be on localhost.
Image.tag([tagname])
Runs docker tag to record a tag of this image (defaulting to the tag it already has). Will rewrite an existing tag if one exists.
Image.push([tagname])
Pushes an image to the registry after tagging it as with the tag method. For example, you can use image.push 'latest' to publish it as the latest version in its repository.
Image.pull()
Runs docker pull. Not necessary before run, withRun, or inside.
Image.imageName()
The id prefixed as needed with registry information, such as docker.mycorp.com/mycorp/myapp. May be used if running your own Docker commands using sh.
Container.id
Hexadecimal ID of a running container.
Container.stop
Runs docker stop and docker rm to shut down a container and remove its storage.
Container.port(port)
Runs docker port on the container to reveal how the port port is mapped on the host.