2

Currently I have a tomcat webserver that is hosting multiple .war microservices (if it matters: spring-boot applications). When upgrading an application, I'm using the tomcat parallel deployment feature by adding a myapp##005.war, myapp##006.war, etc to have zero downtime deployment.

I'd like to dockerize the applications. But what suits best for java applications webservice applications?

Is it better to package a war file directly into the container, so that each redeployment would require a new docker container? Or should the tomcat run as a container without applications, and mount the war files from a shared host system folder (and thus provide redeployment without dockerimage recreation)?

I could think of the following 3 possibilities:

  • run each war file as a jar instead with embedded tomcat, each as own docker container? Then each app is decoupled, but I cannot use the parallel deployment feature anymore as I have to kill the jar before another can take its place. If this would be the best approach, then the question is: how could I get zero downtime deployment though with docker containers?
  • run each war file as standalone tomcat, each as own docker container? Each app then would be decoupled and could also make use of parallel deployment. But I'd have to launch an explicit tomcat webserver for each application in every docker container here, which might have negative impacts on the host system performance?
  • run a standalone tomcat as docker, and place all *.war files in a shared folder for deployment? Here I could still use the parallel deployment feature. But isn't this against the idea of docker? Shouldn't the war application be packed inside the container? Performance and resource requirements would probably best here, as this requires only a single tomcat.

Which approach suits for java miroservices?

2
  • I think you need "blue green deployment" for microservices, it allows to redeploy containers with zero down time. Sharing a war files is not a good idea, because you it need follow to the docker container, all you need must be inside image, except docker-compose file. Commented Nov 20, 2019 at 13:03
  • While this is a question that is really "primarily opinion-based", it is still a good question. Commented Nov 20, 2019 at 21:02

1 Answer 1

5

Deployment using a single Jar for each Docker container is definitely the best approach. As you mentioned, low coupling is something you want from a microservice. Rolling deployments/canary releases etc can easily be done with container orchestration tools like Docker Swarm and Kubernetes.

If you want to play around with these concepts, Docker Swarm is fairly easy:

In your compose file:

version: '3' services: example: build: . image: example-image:1.0 ports: - 8080:8080 networks: - mynet deploy: replicas: 6 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure 

The deploy part in you compose file is all Docker Swarm needs.

  • replicas tells you that 6 instances of your application will be deployed in the swarm
  • parallelism will tell you that 2 instances will be updated at the same time (instead of 6)
  • Between updates there will be a 10 second grace period (delay)

Lot's of other things you can do. Take a look at the documentation.

If you update your service, there will be no downtime, as Docker Swarm will serve all requests through the 4 containers that will still be running.

I don't recommend Docker Swarm in a production environment, but it's a great way to play around with the concepts of container orchestration.

Kubernetes learning curve is quite steep. If you're in the cloud, AWS for example, services like EKS, Fargate etc can take a lot of that complexity away for you.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your example and detailed explanation! It would be sufficient for me having 1 running container, and just hot-switch them without downtime. Is that also possible with docker swarm? Beside that, do you know if there are any cons running an embedded tomcat instead of a dedicated standalone?
You need to temporarily scale up to at least two. While the new instance is starting up, the old version still needs to be up to serve requests. I mean it's not physically possible for a service to serve requests if no instances of it exist at a certain point in time. But you can do this with one extra docker command so it doesn't need to be a permanent thing that you define in your docker-compose file.
As to your second question, I would guess that it's a little less stable. If you're just going to deploy one container, I don't really see the point in containerizing it. You're not leveraging the advantages that containers and container orchestration can give you (load-balancing, availability, auto-rebooting crashed applications,...)
Well my whole target is to decouple the applications. If using single jars, I need docker to provide zero downtime deployment. Anyways I'm fine with a single instance. Of course it would be a pro being able to load-balance and scale things up if required in future. Is it possible to tell docker-swarm to start a 2nd instance for deployment, and then go back to only 1, killing the old version?
"docker service scale exampleservice=2", would do the trick. "docker service update --image newexampleserviceimage" for the update. By default docker swarm will update your service instances one by one -I think- if not you can specify this in your compose-file or when creating the service with --update-parallelism tag

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.