4

I'm new to Docker, but have a Java web app project for which my Maven build produces and installs a Docker image. i.e.

mvn clean install

Produces:

REPOSITORY                             TAG                  IMAGE ID            CREATED             SIZE
registry.gitlab.com/me/myapp   0.0.1-SNAPSHOT-dev   12d69e5ab28b        45 minutes ago      666 MB

I'm making use of Spotify's Maven plugin to build this, which I can then deploy to the repository using:

mvn docker:push

Which works great. However: I'm using GitLab for CI, and my .gitlab-ci.yml file contains:

image: maven:3.3.9-jdk-8

build:
  script: "mvn clean install && mvn docker:push"

This nearly works, but fails as Docker is not installed in my container which is running the build:

[INFO] Building image registry.gitlab.com/me/myapp
Dec 31, 2016 8:30:45 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.io.IOException) caught when processing request to {}->unix://localhost:80: No such file or directory
Dec 31, 2016 8:30:45 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request to {}->unix://localhost:80
Dec 31, 2016 8:30:45 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.io.IOException) caught when processing request to {}->unix://localhost:80: No such file or directory
... (more of the same) ...

It seems the solution here is to install Docker into the container. I can't find a pre-built image that has Java, Maven and Docker, but I did try configuring Docker as a service:

services:
  - docker:1.13-rc

But the result is the same - it seems services are meant to be used as external services that can be connected to, but that are not immediately installed within the same container.

How should I go about updating my .yml file so that the GitLab build can build and push a Docker image?

1 Answer 1

8

I think you're very close.

Gitlab works in stages, and you've correctly defined a proper build stage for your java app. However, you need another stage that will then build your docker image. I'm not all that familiar with Maven and what's configured for your mvn docker:push step, but I'm going to assume that it's a pretty simple wrapper around the docker build and docker push commands.

I'd recommend separating things out into different stages and using artifacts to transfer the built files between containers.

I'd imagine your .gitlab-ci.yml file should look something like this:

image: maven:3.3.9-jdk-8
stages:
  - build_application
  - build_image

# This stage builds your application
build_application:
  stage: build_application
  script:
    - mvn clean install
  artifacts:
    paths:
      - my-application.jar

build_image:
    image: docker:latest
    services:
      - docker:dind
    stage: build_image
    # Remember that even though the JAR file was built in a separate image
    #  Gitlab CI will make it available in this image because I specified it in artifacts
    #
    # All I really need to build the Docker image is the artifact(s) & Dockerfile
    script:
      - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
      - docker build --no-cache=true -t registry.gitlab.com/me/myapp .
      - docker push registry.gitlab.com/me/myapp
Sign up to request clarification or add additional context in comments.

5 Comments

This is super helpful Ben, thank you for the clarification - I'll give things a quick spin and let you know how it goes.
This is the solution I came up with too. However, I would be interested in seeing a solution that works with the docker maven plugin.
@rolve It's certainly possible, but more involved. What you have to do is have an image that has both mvn and docker. I'd look at the Dockerfiles of each image in order to create another image that is fit for your purpose.
I ended up creating my own image by starting up maven:3-jdk-8, installing docker, and then pushing it as my own craigotis/buildtools:v1 image. It's been working well so far - the only thing I really don't like is my Maven build downloading the entire ~/.m2 repository for each build. I'm considering updating my image to start with a pre-populated repository folder - since my dependency versions rarely change, and now I can build without needing internet access.
If you want to make your image more generic, you could always utilise Gitlab CI Cache so that your dependencies are cached. However, you'd need to make sure that the dependencies are downloaded in the project directory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.