Open balopat opened 5 years ago
cc @GoogleContainerTools/java-tools
@loosebazooka #1312 is something to consider when designing this.
@tejal29 is the suggestion that the rebuild happens on the remote machine? instead of building locally and pushing intermediate artifacts over?
I guess we could provide multiple hooking points and see what happens, I'm curious how remote execution would be handled though.
interesting suggestion - #1312 would push compilation on the container side - that requires the container to have all the build toolchain. It is similar to what @ahmetb is experimenting with on https://github.com/ahmetb/rundev in a sense that compilation would happen inside the container.
I was primarily thinking that this feature would leverage the developer's machine for compilation, hence compile -> sync compiled files to container -> container server reloads itself
instead of sync -> compile inside container -> container server reloads itself
I managed to get Spring Boot devtools to work. You have to be careful to build the image with the devtools dependency included (probably do that in a profile, so the production image is different). If the image is built using the buildpack support in Spring Boot 2.3 it ends up with the app code in /workspace
. So this works:
apiVersion: skaffold/v2alpha4
kind: Config
build:
artifacts:
- image: localhost:5000/apps/demo
custom:
buildCommand: ./mvnw spring-boot:build-image -D docker.image=$IMAGE && docker push $IMAGE
dependencies:
paths:
- pom.xml
- src/main/resources
- target/classes
sync:
manual:
- src: "src/main/resources/**/*"
dest: /workspace/BOOT-INF/classes
strip: src/main/resources/
- src: "target/classes/**/*"
dest: /workspace/BOOT-INF/classes
strip: target/classes/
deploy:
kustomize:
paths:
- "src/main/k8s/demo/"
With this builder you have to explicitly ask for devtools to be in the container image, and at the moment we also need to declare that docker.image
property explicitly. E.g:
<properties>
<docker.image>localhost:5000/apps/${project.artifactId}</docker.image>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
<image>
<name>${docker.image}</name>
</image>
</configuration>
</plugin>
</plugins>
</build>
@dsyer this is interesting, I just merged jib support for spring-boot-devtools https://github.com/GoogleContainerTools/skaffold/pull/3382. Are you running package
on your own to trigger the rebuild?
Sort of. I’m just making changes the the IDE and they get copied to the target dir, where skaffold notices them.
Oh right makes sense. So is skaffold watching anything for you?
Yes, I think so. Isn’t that what the sync:
config does?
Yeah, sorry I'm stuck in the jib specific implementation. You're right.
@balopat I'm trying Dave's example with Skaffold 1.12 on Windows. But the $ IMAGE variable is not replaced. Does anything have to be configured for this? Thx.
On Windows, the cmd syntax must be used, i.e.% IMAGE%. Exchanging values via the environment is simple, but as can be seen, incompatible between operating systems. I would prefer to work on Linux, but unfortunately there are situations that do not allow this. :-(
@dsyer buildpacks "starts" a spring boot application via the JarLauncher. Isn't it that devtools doesn't work in this case? The example doesn't work for me.
If you don't have any special requirements like this, try the springboot devtools example which uses auto sync: https://github.com/GoogleContainerTools/skaffold/tree/master/examples/jib-sync
Thanks, I know jib. Your example is not clear. If you change HelloController.java, the entire build will be run.
Addendum because I am not allowed to edit my old post: Devtools does not work with webflux, at least as far as the remote update is concerned. issue
I don't think you need remote updates for skaffold though (that's kind of the point of skaffold sync - it handles all of that), so the issue you linked to isn't really relevant. There is another issue that is relevant: https://github.com/spring-projects/spring-boot/issues/21424 (more to do with the buildpack than Spring Boot as such).
If you change HelloController.java, the entire build will be run.
If you are using maven, this is a problem with maven unfortunately. They don't do incremental builds very well. Gradle, while it may have its own issues, does the incremental compile much much better.
@dsyer's solution is nice for maven users since the IDE will do the right thing incrementally compiling. Maybe we can improve auto sync to use the outputs from the IDE too.
@torsten-liermann as @dsyer pointed out, I don't think the remote update feature of Devtools makes sense with Skaffold. You should let Skaffold sync and update files and have Devtools reload them, instead of manually updating server-side files through the remote update of Devtools.
@loosebazooka
If you change HelloController.java, the entire build will be run.
If you are using maven, this is a problem with maven unfortunately.
I referred to the configuration of skaffold in the example with maven. It is not necessary for skaffold to start a build if the java code is changed.
Indeed. That's why I used target/classes
in the sync configuration. Skaffold will copy the compiled code over if the IDE or command line dumps it in target/classes
.
@chanseokoh
I don't think the remote update feature of Devtools makes sense with Skaffold. You should let Skaffold sync and update files and have Devtools reload them, instead of manually updating server-side files through the remote update of Devtools.
I just wanted to mention remote update of Devtools that it doesn't work with webflux apps. I didn't know before. Maybe a bit helpful at the moment: it offers a way to restart the app remotely. I would like to use buildpacks with skaffold, but as noted by Dave, it doesn't work at the moment.
@balopat i saw the skaffold sample for Spring dev tools , which was quite useful , just small question is it working the same in case of multi module spring boot application ? as i suspect Spring boot dev tools class loader separation (restart and app class loader) will not work in that case as skaffold will sync the modules other than main application as jars in app libs folder not a plain classes as the main module inside the container.
Do we have any example about spring boot multi module app auto sync with skaffold ?
That's a good question. I haven't really tested the mutlimodule stuff. But as far as general mutlimodule building goes, modules are not included at the class level (*.class) but at a package level (.jar).
Can you confirm it works locally for bootrun ?
Reducing priority since its been an year since last comment.
That's disappointing, since there is still a problem and an opportunity. Time passing does not really change the priority and almost everything needed is in the thread above (I say "almost" because there is a new feature in Boot that makes it necessary to also add spring.devtools.restart.enabled=true
to the system properties). There's a full example here: https://github.com/dsyer/inner-loop-boot-k8s.
@dsyer so it seems like there are several approaches for configuring for a Spring Boot app, and those approaches may need to be periodically updated as Spring Boot changes. Using a custom builder is insufficient as the builders aren't able to configure sync rules or provide dependencies to be monitored.
A user could probably get by with some judicious use of YAML anchors, but that doesn't enable re-use between projects.
Not sure what the several approaches are, or what the differences are between builders and sync rules. A sensible first step would be simply to support Spring Boot where it is now (2.5) by adding a system property. Could it be enabled with a flag in the skaffold.yaml
, with a sensible default? I don't know how it works really.
@dsyer your example above uses a custom builder, whereas your inner-loop-boot-k8s
example uses buildpacks. I'm surprised that --auto-sync
does anything in the buildpacks case as there will be no sync-rules provided in the paketo-built images.
Does this spring.devtools.restart.enabled=true
property mean that there is no separate devtools dependency to be included?
Does this
spring.devtools.restart.enabled=true
property mean that there is no separate devtools dependency to be included?
No, that's in addition, otherwise the launcher detects that it is running a jar file and doesn't include restart.
I'm surprised that --auto-sync does anything in the buildpacks case as there will be no sync-rules provided in the paketo-built images.
I don't think it does (do anything). You have to add sync rules manually in skaffold.yaml
. I see that as inconvenient, but not too bad since it doesn't affect the k8s resources that go to production.
As for the custom builder - I only used that in the example above because the buildpacks weren't working at the time. IMO the buildpack is better, but I'm also open to giving people the choice.
The main thing that would help (a lot) in practice is just the system property. If that isn't added by skaffold dev
then the user has to add it to the PodSpec
, leading to different manifests for dev and prod, and all the awkwardness that entails. There is probably more than one way to solve that problem, but I'm not familiar enough with the internals of skaffold
to say what would be best.
Spring Boot DevTools came up a couple of times as a feature to support for Skaffold's filesync. This requires some more advanced workflows because of syncing compiled files to the container that we could invest into if there is enough demand.
I'm opening this issue to see if there is any interest in this from the user community. If you are a user of both Spring Boot Developer Tools and Skaffold, let us know if you are interested in this feature by commenting or putting a thumbs up on this issue!