Replace the .jar file of an application built in Spring Boot 2 without restarting the container every time

I created this project in docker-compose to test applications made in Spring Boot 2.
I would like to replace springbootapp.jar in /ServerDockerJava01/java/target/, or in any subfolder of ServerDockerJava01, without rewriting the container ‘container-java-eb’ of the image ‘image-java-eb: v.1.0’.
I tried to insert a simple volume but it doesn’t work.
I must also be able to interact with the container to make a backup of the photos saved on the disk by springbootapp.jar.
Can you tell me how I can solve it?
/home/gi/Dropbox/SERVER/DOCKER-LINUX/ServerDockerJava01/java/Dockerfile

FROM openjdk:11.0.15-jre-slim
EXPOSE 8080
EXPOSE 8443
WORKDIR /demoapp
COPY target/springbootapp.jar /demoapp/
CMD ["java", "-jar", "/demoapp/springbootapp.jar"]

/home/gi/Dropbox/SERVER/DOCKER-LINUX/ServerDockerJava01/docker-compose.yaml

version: '3.8'

services:
  java:
    build: ./java
    image: image-java-eb:v.1.0
    container_name: container-java-eb
    ports:
      - 6004:8080
      - 7004:8443
#    volumes:
#      - ./volumes/data-java:/demoapp
    restart: on-failure
    networks:
      - eb

networks:
  eb:

Hot Code Swap (which is sometimes also refered to as Code Hot Swap) is not possible like that. There is no way arround restarting the container, regardess wether you map a volume bind mount or not. The classloader already processed the classes from the jar it used during start, replacing the jar file will not make the classloader de-register the existing classes from memory and register the classes from the new jar instead.

You might want to map hosts ports to your vm (for VMware NAT Interfaces see: VMware Workstation Port Forward to a VM in a NAT Network) and map a host folder to the vm (make sure your install open-vm-tools if you still use vmware workstation). Within your IDE you should be able to leverage Hot Code Swap.

1 Like

Thanks for your intervention. I don’t understand why you show me that page. I don’t want to change the vmware configuration.
If I cannot replace the .jar file without restarting the container I am content to create a volume next to the docker-compose.yaml file.
I tried to do it like this:

    volumes:
      - data-java:/demoapp

but the volume is created in an awkward place to reach.
Can I move the default volume position?
From:
admin:///var/lib/docker/volumes/serverdockerjava01_data-java/_data/springbootapp.jar
to:
/home/gi/Dropbox/SERVER/DOCKER-LINUX/ServerDockerJava01/volumes/data-java/springbootapp.jar

I believe @meyay said it is not enough to replace the jar file since it is loaded into memory and you need to reload it, which basically means restart. So it is not about Docker, it is about Java and memory handling. Note that my Java knowledge is not so deep so I can’t help you with that. However a container is a running process. If springboot is part of the main process loaded when the container starts, you need to restart that process which means restart the container.

If you just want to avoid going through the whole starting process, like a longrunning entrypoint, you can send a signal directly to the java process to reload/restart. I don’t know if that could reload the jar files though.

That is what a volume is. It is not for using it from the host. You can use bind mounts or change the path of of the volume. The latter is useful when you need the proper permissions (from the app’s point of view) set on the host folder, but it means you might not be able to edit or even read those the files. I think a simple bind mount would be enough for you, but it will not reload the jar files.

1 Like

Thanks a lot guys, as usual you are fantastic! It’s easier done than said. Bind mounts work perfectly with my application. Is there a way to not indicate the app name in the Dockerfile? If I use the asterisk I get “Error: Unable to access jarfile /appfolder/*.jar”.

  java:
    build: ./java
    image: image-java-eb:v.1.0
    container_name: container-java-eb
    ports:
      - 6004:8080
      - 7004:8443
    volumes:
      - type: bind
        source: ./volumes/data-java
        target: /appfolder
    depends_on:
      - postgresql-postgis
      - pgadmin
    restart: on-failure
    networks:
      - eb

volumes:
  data-postgresql:

networks:
  eb:
FROM openjdk:11.0.15-jre-slim
EXPOSE 8080
EXPOSE 8443
WORKDIR /appfolder
CMD ["java", "-jar", "/appfolder/*.jar"]