Add custom folders during paketo build
goafabric opened this issue · 12 comments
[note: as requested by https://github.com/paketo-buildpacks/base-builder/issues/484]
I am using paketo build packs with Spring Boot for Native Container Images + Maven.
And because of some limitations of flyway, I have the requirement to add an additional directory with content to the image.
JIb has a property "extraDirectories" to achieve this.
But diving into paketos documentation i could not find something similar.
So is there something that can be activated by some <BP_XX> Parameter ?
Otherwise i have to leverage JIB or a Dockerfile afterwards
Thank you in advance
I would try setting BP_MAVEN_BUILT_ARTIFACT
. Something like target/*.jar <pattern for flyway>
.
Configure the built application artifact explicitly. Supersedes $BP_MAVEN_BUILT_MODULE Defaults to
target/*.[ejw]ar
. Can match a single file, multiple files or a directory. Can be one or more space separated patterns.
Normally, the buildpacks will only match the single JAR file that your build produces. That means files outside of that are considered "source code" and not included in your final container. You can adjust this pattern to match multiple files. When it matches multiple or a directory, the buildpack will keep everything. Everything that matches ends up under the /workspace
directory in the final image.
@dmikusa-pivotal
a cool thank you very much ... in theory this would be
BP_MAVEN_BUILT_ARTIFACT=target/*.[ejw]ar target/classes/db/migration
but i am unsure about the first part .. as this is a Native application so workspace just has (in my case)
org.goafabric.personservice.Application
so this would rather be
BP_MAVEN_BUILT_ARTIFACT=target/*.Application target/classes/db/migration
i guess ?
because of native builds arm limitation i cannot build locally and have to leverage github actions
ok i guess for native images build inside docker this is a lil different, because console log tells me
/layers/paketo-buildpacks_native-image/native-image/org.***.personservice.Application (executable)
ok . now i see .. this is again different projekt at paketo
https://github.com/paketo-buildpacks/native-image
before beeing redirect a 3rd time .. i gues the equivalent here is
BP_NATIVE_IMAGE_BUILT_ARTIFACT
.. do you happen to know if the described mechanism is also possible with native images ?
because this just says:
--- cut ---
Configure the built application artifact explicitly. This is required if building a native image from a JAR file
And I am unsure how the configuration would look like than
Sorry, I was looking into this more and I don't think it's going to work presently. We are aggressively pruning files to keep the image size down. After compilation with Maven, we strip out all of the source code and after native-image compilation, we do the same with the bytecode.
For Maven and source code, you can use the argument I mentioned to ensure that stuff is retained in /workspace
. There is not a similar option for native-image though. The buildpack removes all the bytecode and doesn't retain anything besides the image.
ok i guess for native images build inside docker this is a lil different, because console log tells me /layers/paketo-buildpacks_native-image/native-image/org.***.personservice.Application (executable)
The /layers
directory contains the outputs from buildpacks, they are not all carried over into the final image. When you add the option for BP_MAVEN_BUILT_ARTIFACT
it will save the matched files to /layers/paketo-buildpacks_maven/
, but that is only available at build time.
I think what is needed here is a code change to the buildpack. I'd be interested in how you'd see this working. The buildpack can certainly persist files through to your final image. We could add an env variable to the native-image buildpack like BP_NATIVE_IMAGE_ADDITIONAL_FILES
(the BP_NATIVE_IMAGE_BUILT_ARTIFACT
is different, that points native image to a specific JAR file that we should build, in the case where you have multiple JAR files which isn't something that happens with Spring Boot apps). The env would be a space separate list of glob patterns. Anything matched, would be copied to the run image.
The part that is a little confusing here is that buildpacks work in a pipeline fashion and they can each transform the /workspace
directory as they execute. The /workspace
is where your final binary is located and that is what's executed in your final image. By the time native-image runs, the contents of your /workspace
are not the same as your source code. That means you'd have to write glob patterns that match the state of the workspace at that time. That would essentially be the set of files that you preserve through the build phase with BP_MAVEN_BUILT_ARTIFACT
, which is not exactly intuitive.
For example:
.
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ └── java
└── target
If you set BP_MAVEN_BUILT_ARTIFACT='target/*.jar target/classes'
, then you'd end up with target/demo-0.0.1-SNAPSHOT.jar and
target/classes/in the
/workspacewhen native-image runs. You would then need to set
BP_NATIVE_IMAGE_BUILT_ARTIFACT=target/.jar, so it can find your JAR and build the native image binary from it, and then
BP_NATIVE_IMAGE_ADDITIONAL_FILES=target/classes/db/migrationso that it copies those files into the final run image. This could be a little confusing as you might expect to be able to set
src/main/resources/db/migration`.
The output of this example would be:
├── io.paketo.demo.DemoApplication
└── target
│ ├── classes
| │ ├── db
| | │ ├── migration
...
Your app would have to know to look in that location for the files, which may not be where it expects them.
I'm curious to know what you would expect here? Where you'd expect files to exist? Where your app would need them to exist? etc...
This might be something that we need to address differently. There is an issue open regarding the ability to control what files are/aren't deleted, paketo-buildpacks/libbs#103, I think the same concerns apply here. Adding a single env variable like is proposed there would probably be a better option. I still think there's questions about where stuff ends up in the final image though. If we copy src/main/resources/db/migrations
to /workspace/src/main/resources/db/migrations
, is that really helpful? In addition to paketo-buildpacks/libbs#103, we might need some sort of transform option but I'm not sure what that would look like off hand.
Thank you for the very detailed description and taking so much time.
The overall abstract requirement is quiete simple.
That would be any option similar to jibs extradirectiories
https://github.com/GoogleContainerTools/jib/blob/master/jib-maven-plugin/README.md#extradirectories-object
This lets you define a "from path" from your project /workspace
and and into, where to reside inside the container.
Of course both options only make sense, when the build job has acces to the "from" files.
And the application has acces to the "into folder".
** The concrete requirement in this special case **
is basically what you wrote and to copy the migrations.
This would basically be a workaround for spring-attic/spring-native#778
Of course if spring native would/will have proper flyway support that is not needed.
Currently i simulate the behaviour by having a jib or dockerfile process the container again after paketo.
And just adding the directory .. ANd then during bootstrap tell flyway to use the migrations from the filesystem.
You can define a location there .. no problem.
All in all that works, but just chaining one hack after another
Conclusion
For the concrete requirement the best solution would be a solution to the flyway ticket.
But overall having some functionality like extradirectories, would help in general
One additional note of reference for anyone coming upon this thread. In most cases, Spring Boot resources (i.e. files under src/main/resources
should be bundled into the actual binary. The Spring Boot tooling will include resources in the resource-config.json
that is generated, what's listed in there ends up in the binary.
i see no value in this anymore
i think for flyway we should have another solution
Just to follow up, we did end up implementing paketo-buildpacks/libbs#103 and it was released in 7.2.0.
That does not have the transformation capabilities I mentioned, but it would allow you to keep the files through into the final container. You could get around that by having the same directory structure in your source code, that you require in the final image.
For example: if you need /workspace/migrations
, then you would just need to have migrations/
in the root of your JAR file & you could have that folder persisted into the final container.
Not sure if that helps, but thought I'd follow up.
@dmikusa sorry to contact you via this issue .. but i don't know another way without raising a new issue
can you tell me what happened to the issue concerning "arm64" support ?
paketo-buildpacks/stacks#51
this was still open and now just has the "repo has been archived now" status
so do we have support now for arm64 ? because last time i tried it did not work ..
also curious concerning spring boot 3.0
thank u
I suspect that is closed because of project repo changes, not because we have ARM64 support complete. That is still a work in progress.
What we have for ARM64 at the moment is a build-your-own option. See https://github.com/dmikusa/paketo-arm64.
A past colleague at VMware also has a Docker Hub image he's published using these instructions. You can use that, but it's an unofficial image at this point. See this comment.
There are still plans for official ARM64 support, but it's kind of hung up on some upstream issues that we need to build images in a sustainable way. See this and this. Upvotes on those helps.