I am trying to figure out the ultimate best practices for using Java in Docker containers deployed using Kubernetes on local environments or while developing code. In the ideal state, Java developers should be able to move as fast as python/javascript developers, but I am having a hard time matching the speed (or even coming close).
At the moment, I have a working, manually deployed k8's cluster. My Java Spring project is built by maven after a build command is run manually (mvn clean install
), then I run a script to make an image, after that I run a script to run minkube (if its not already running) and finally I have to apply
a deployments manifest file (which launches the containers into the pods).
What I am missing:
Sadly, Skaffold, the tool that I would be excited to use does not work natively with Java. Is there another tool that Java Devs are using to make their local deployments super fast and competitive with the DUCK languages (py, js)?
Sorry if I'm late, I'll try to give an answer for future readers, or maybe still for you!
First of all, docker build and deploy on kubernetes cluster are two totally different phases of your software supply chain, let's keep them as separate discourses
a) create a config repository with all the k8s manifests and run kubectl apply from you CI server at every push
b) put config along with the interested microservice, tag the fresh built image with the commit hash and at the end of the pipeline kubectl apply env.yaml && kubectl set image myregistry.com/myimage:${commitHash} (just be sure to tag also as "latest" and include the latest tag in you deployment spec, it helps to reconstruct the current situation after a remove-and-apply configuration)
c) deploy with helm charts. It's similar to the previous but you can leverage all the advantages of the dependency management and deployment templateization
Hot reloads are nice when you do your tdd development but useless when the code is about to be delivered, neither with node/python microservices you will use it because once your code is containerized, you should shoot with an AK47 every developer that tries to touch it. The real big thing here is to automate your integration/delivery/deployment. In my team we just need to open and accept a PR, and the magic happens
You need to do some debugging/integration between microservices on your laptop. I would not discourage this practice, but is something that has to be done at a frequency for which speed is not so important for productivity. But if you want to do it, you can do it building a "laptop" or "dev" environment with docker compose, pulling your dependencies from the registry (to reproduce the current "online" situation) and then build your microservice with its own configuration. Another way is to use port forwarding a k8s capability to pretend that a pod is connected with your local machine exposing a well-known port, but is an headache if there are many dependencies. A third way is to use tools like https://www.telepresence.io/ that promises to run a pod locally and connect to the cluster with a pair of proxies in both directions
You can build a docker image directly from maven with docker-maven-plugin. Add to your pom.xml
:
<build>
<plugins>
...
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<configuration>
<imageName>example</imageName>
<dockerDirectory>docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
...
</plugins>
</build>
I don't know precisely your use case, but deploying a k8's cluster in your dev machine is maybe overkill. You can test your docker images with Docker compose
My take on your development workflow:
docker-maven-plugin
to build direct docker images from your maven build.You mention python/js as being fast, but do note, that for even those languages the basic steps remain the same, build a docker image, push to repository, update k8s deployment.
Also hot deployment has worked with Java, even in things like eclipse say with a spring boot based microservice you can use the spring-dev-tools to do live reloads and auto restarts. However I am not aware of anything that will help you handle live changes to a docker container and I would ask you to shy away from it docker containers are supposed to be immutable.