1

I have a java project, and I'm generating .jar file. My question is what is the best practice to use docker and jenkins for build and deploy the project? Is it build the jar with one docker image, then put the Jar file in another docker image and run a container from the last image in the production env or is there a better way to do that?

2

I do not know how how about Jenkins, but GitLab CI has feature called artifacts which allow you to

  • explitely share some files/directories between builds
  • download them from GitLab Pipeline view

Additional pro is that allows you to make deployments manual actions.

Also if you are building fat JARs you do not need Docker for your deployments at all.

So the best solution for you is to have separate task for building release and separate for deployment (which can be manual job or not).

  • Jenkins has artifacts, and has the ability to copy artifacts between tasks. for docker I think it is better to deploy jar in docker then use docker container in production. – Wissam Roujoulah Sep 6 '17 at 8:56
  • 1
    It is not better and this is not worse either. However Inga general it is quite reasonable to use Ockham’s razor and o not spawn beings needlessly. Docker is one of the possible solution but isn’t always the best one or even the right one. Fat JAR solves the same problem as containerization, so think if Docker is what you need, not follow the herd because it is “fashion” now. Check out other solutions like not using containers at all or using different implementation like rkt. – Hauleth Sep 6 '17 at 9:21
  • @chupasaurus what? Since when? As far as I know this never was a case. – Hauleth Sep 6 '17 at 12:04
  • @ŁukaszNiemier my bad, garbage collector haven't been run in my head for a long time. – chupasaurus Sep 6 '17 at 12:12
0

So, assuming Docker and Jenkins are set as stated, I would say your approach covers it: Build Jar in one container, grab the Jar and build an image with it, then build containers from that image for your environments.

For some thoughts on how to set it up:

Have a Docker Host (or swarm) running and start a Jenkins service on it. This is a compose file that I have running:

version: '3.7'

services:
  jenkins-local:
    user: root
    image: jenkinsci/blueocean
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ../../..:/var/projects
      - ./jenkins_home:/var/jenkins_home
    ports:
      - "9000:8080"

volumes:
  jenkins-home:

The important part is the volume where /var/run/docker.sock of the host is mounted to /var/run/docker.sock of the container. This allows Jenkins to access the host's Docker daemon via the Docker socket (make sure "user" is "root"). Find some reading about this here: https://getintodevops.com/blog/the-simple-way-to-run-docker-in-docker-for-ci

The reason why I'd choose the jenkinsci/"blueocean" image is because it allows for usage of blueocean pipelines. https://jenkins.io/projects/blueocean/

Within pipelines you write Jenkinsfiles to define your build pipelines:

node {
    stage('checkout scm') {
        checkout scm
    }
    stage('Build artifact') {
        // Connect to our Nexus Docker repository with the nexus_jenkins_user user credentials managed in Jenkins
        docker.withRegistry('https://registry.swarm', 'nexus_jenkins_user') {
            // Run a Maven builder image and attach it to the nexus network
            // Add a volume to cache the maven-repo in for consecutive runs
            docker.image('registry.swarm/builder/maven:maven-3.3.9').inside('-v maven-repo:/root/.m2 --network=nexus_nexus') {
                sh 'mvn clean package -Dmaven.test.failure.ignore=true'
            }
        }
    }
    stage('archive artifacts and save test results') {
        archiveArtifacts artifacts: "target/*.jar", fingerprint: true
        junit 'target/surefire-reports/*.xml'
    }
    stage('Build run container image, push Docker image to nexus') {
        docker.withRegistry('https://registry.swarm', 'nexus_jenkins_user') {
            docker.build("app/my-service:current").push()
        }
    }
}

Since everything happens in Jenkins Workspace, the only important line for the Dockerfile is this one:

COPY ./target/my-service-*.jar ./my-service.jar

CMD [ "java", "-Duser.timezone=UTC", "-jar", "my-service.jar"]

This will grab the jar, copy it over and use it for the run command in the image.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.