Kickaha
Kickaha

Reputation: 3857

How do I keep the local docker image made by Jenkins?

Jenkins with docker-pipeline is downloading my git repository, and installing it.

pipeline {
    agent {
        docker {
            image 'node:6-alpine'
            args '-p 8989:8989' 
         }
    }
    stages {
        stage("install") {
            steps {
                sh 'npm install -production'
            }
        }
    }
}

But then it's cleaning up and deleting the image:

$ docker stop --time=1 4b3220d100fae5d903db600992e91fb1ac391f1226b2aee01c6a92c3f0ff009c $ docker rm -f 4b3220d100fae5d903db600992e91fb1ac391f1226b2aee01c6a92c3f0ff009c

All of the many deployment examples online are for publishing to a registry.

how do I just stop it being cleaned up?

How do I name & save and the image locally ?

Upvotes: 2

Views: 3508

Answers (1)

Szymon Stepniak
Szymon Stepniak

Reputation: 42254

You may want to use dockerfile agent instead of the docker one. It uses a Dockerfile that is part of your project to build the local docker image. All image layers will be cached, so the next time you run the build, it won't spend time on re-building the image. It is also useful to put commands like npm install -production inside the Dockerfile, so those dependencies are downloaded and installed only one time.

Take a look at the following example.

Dockerfile:

FROM node:6-alpine

RUN npm install -production

Jenkinsfile:

pipeline {
    agent {
        dockerfile {
            filename "Dockerfile"
            args '-p 8989:8989'
            additionalBuildArgs "-t my-custom-node:latest"
        }
    }

    stages {
        stage("Test") {
            steps {
                sh "npm --version" // this command gets executed inside the container
            }
        }
    }
}

The output:

Running on Jenkins in /home/wololock/.jenkins/workspace/pipeline-dockerfile
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Declarative: Agent Setup)
[Pipeline] isUnix
[Pipeline] readFile
[Pipeline] sh
+ docker build -t a3f11e979e510758f10ac738e7e4e5c1160db2eb -f Dockerfile .
Sending build context to Docker daemon 2.048 kB

Step 1/2 : FROM node:6-alpine
Trying to pull repository docker.io/library/node ... 
sha256:17258206fc9256633c7100006b1cfdf25b129b6a40b8e5d37c175026482c84e3: Pulling from docker.io/library/node
bdf0201b3a05: Pulling fs layer
e9fa13fdf0f5: Pulling fs layer
ccc877228d8f: Pulling fs layer
ccc877228d8f: Verifying Checksum
ccc877228d8f: Download complete
bdf0201b3a05: Verifying Checksum
bdf0201b3a05: Download complete
bdf0201b3a05: Pull complete
e9fa13fdf0f5: Verifying Checksum
e9fa13fdf0f5: Download complete
e9fa13fdf0f5: Pull complete
ccc877228d8f: Pull complete
Digest: sha256:17258206fc9256633c7100006b1cfdf25b129b6a40b8e5d37c175026482c84e3
Status: Downloaded newer image for docker.io/node:6-alpine
 ---> dfc29bfa7d41
Step 2/2 : RUN npm install -production
 ---> Running in e058ab280807
[91mnpm[0m[91m WARN[0m[91m enoent[0m[91m ENOENT: no such file or directory, open '/package.json'
[0m[91mnpm [0m[91mWARN[0m[91m !invalid#1 No description
[0m[91mnpm[0m[91m [0m[91mWARN[0m[91m !invalid#1 No repository field.
[0m[91mnpm [0m[91mWARN[0m[91m !invalid#1 No README data
[0m[91mnpm [0m[91mWARN[0m[91m !invalid#1 No license field.
[0m ---> d685094800d9
Removing intermediate container e058ab280807
Successfully built d685094800d9
[Pipeline] dockerFingerprintFrom
[Pipeline] }
[Pipeline] // stage
[Pipeline] sh
+ docker inspect -f . a3f11e979e510758f10ac738e7e4e5c1160db2eb
.
[Pipeline] withDockerContainer
Jenkins does not seem to be running inside a container
$ docker run -t -d -u 1000:1000 -w /home/wololock/.jenkins/workspace/pipeline-dockerfile -v /home/wololock/.jenkins/workspace/pipeline-dockerfile:/home/wololock/.jenkins/workspace/pipeline-dockerfile:rw,z -v /home/wololock/.jenkins/workspace/pipeline-dockerfile@tmp:/home/wololock/.jenkins/workspace/pipeline-dockerfile@tmp:rw,z -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** a3f11e979e510758f10ac738e7e4e5c1160db2eb cat
$ docker top 84ca2e4a30487f114de81dbd60e53219a8cfa3959fb5b05d2c908f872bfe790c -eo pid,comm
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] sh
+ npm --version
3.10.10
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
$ docker stop --time=1 84ca2e4a30487f114de81dbd60e53219a8cfa3959fb5b05d2c908f872bfe790c
$ docker rm -f 84ca2e4a30487f114de81dbd60e53219a8cfa3959fb5b05d2c908f872bfe790c
[Pipeline] // withDockerContainer
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

In this example I used additionalBuildArgs option to add additional tag. Now, when I do docker images on my host, I can see this image as:

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED              SIZE
my-custom-node         latest              d685094800d9        About a minute ago   56.1 MB
docker.io/node         6-alpine            dfc29bfa7d41        6 months ago         56.1 MB

This is the good first step to start with. If at some point you will find building the docker image too consuming, you can consider building this image in the separate pipeline and push it to some private repository. But because docker caches all layers, I wouldn't think about remote docker repository at this stage. Use local Dockerfile, experiment with your build environment and then see if publishing the docker image would be any improvement for you.

And btw, Jenkins Pipeline terminates the docker container when it terminates the Jenkins job. Your current workspace is mounted and the container workspace is set to the current Jenkine job one, so any file(s) that get created inside your workspace inside the container will be persisted.

To read more about Jenkins Pipeline agents, go here - https://jenkins.io/doc/book/pipeline/syntax/#agent

Upvotes: 2

Related Questions