Docker: In Dockerfile, copy files temporarily, but not for final image

I have a Java service I’d like to package, and the only thing the final docker image needs is the JAR file and a config file. However, I need to run my gradle command first to build the JAR, but I don’t want all the things that gradle uses to be in the result docker image.

Here’s my current DockerFile:

  • How to enable faster container rescheduling with Docker Swarm and Consul?
  • Temporary failure in name resolution [Errno -3] with Docker
  • spinning up multiple jenkins docker slaves for a single job
  • issue with exposing ports using docker compose
  • Docker-Compose Postgresql import dump
  • Issues running cron in Docker on different hosts
  • RUN apt-get update && apt-get install -y openjdk-7-jdk
    COPY . /
    RUN ./gradlew shadowJar
    CMD ["java", "-jar", "service/build/libs/service.jar", "server", "service/service.yml"]
    

    You can see I have to COPY everything first so that I can run ./gradlew (otherwise it says the command cannot be found). But in the end, all I need is the service.jar and service.yml files.

    I’m probably missing something, but how I can make everything available during the ./gradlew build step, but only have the result image include the service.jar and service.yml.

  • Setting nginx reverse proxy to serve from another docker container
  • Patterns for Docker DB Snapshot
  • Docker using mysql
  • Get containers running a given image version
  • Is there a way to download docker hub images whitout “docker pull” for a machine with out Internet access?
  • How to set a specific (fixed) IP address when I create a docker machine or container?
  • 2 Solutions collect form web for “Docker: In Dockerfile, copy files temporarily, but not for final image”

    Building an image works as follows.

    … The docker build command will use whatever directory contains the Dockerfile as the build context (including all of its subdirectories). The build context will be sent to the Docker daemon before building the image, which means if you use / as the source repository, the entire contents of your hard drive will get sent to the daemon …

    See https://docs.docker.com/reference/builder/

    I see no way to achieve what you want. There are two options:

    1. Having all the build dependencies inside the image and build your JAR file inside the container. That bloats your image.

    2. I would recommend to build your JAR separately and just ADD the executable and config files when they are build. That means all build dependencies must be available on your development environment, but your image is as small as it can be.

    You could do this:

    FROM java:7
    COPY . /sourcecode
    WORKDIR /sourcecode
    RUN ./gradlew shadowJar && rm -rf /sourcecode
    WORKDIR /
    CMD ["java", "-jar", "service/build/libs/service.jar", "server", "service/service.yml"]
    

    This uses the Docker official java image (see repo).

    The RUN line should create your service.jar and then remove all the source code you’ve COPYd before the layer gets created, so the source code will not be part of the final image. I’m assuming gradlew will also copy/install it to /service/build/libs, otherwise you should add that step.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.