Closed saturnism closed 6 years ago
I noticed that your application requires Google Application-default Credentials (ADC). So, one possible workaround is
$ ./mvnw clean compile jib:exportDockerContext
$ cd target/jib-docker-context
$ cp <your service account.json> . # give a service account with all the roles that your application requires
Dockerfile
to add something along the line of
COPY <your service account.json> /app/cred.json
ENV GOOGLE_APPLICATION_CREDENTIALS /app/cred.json
$ docker build . -t my-tag
$ docker run -t my-tag
output:
2018-07-17 19:26:49.700 INFO [-,,,] 1 --- [ main] o.s.i.endpoint.EventDrivenConsumer : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2018-07-17 19:26:49.700 INFO [-,,,] 1 --- [ main] o.s.i.channel.PublishSubscribeChannel : Channel 'application-1.errorChannel' has 1 subscriber(s).
2018-07-17 19:26:49.700 INFO [-,,,] 1 --- [ main] o.s.i.endpoint.EventDrivenConsumer : started _org.springframework.integration.errorLogger
2018-07-17 19:26:49.715 INFO [-,,,] 1 --- [ main] c.example.frontend.FrontendApplication : Started FrontendApplication in 4.056 seconds (JVM running for 4.558)
So, this use case is currently not supported in Jib. An application requires Google ADC, and the container which must be self-contained to run the application should be able to get the ADC from somewhere somehow. But I think this can be solved once we have the features to add arbitrary files and define environment variables.
Oh, BTW, I first had to add the spring-milesontes
Maven artifact repository to my ~/.m2/settings.xml
for the org.springframework.cloud:spring-cloud-gcp-dependencies
<profiles>
<profile>
<id>spring-milestones</id>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>spring-milestones</activeProfile>
</activeProfiles>
and also had to downgrade the version of org.springframework.cloud:spring-cloud-gcp-dependencies
:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
- <version>1.1.0.BUILD-SNAPSHOT</version>
+ <version>1.0.0.M4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
So, this use case is currently not supported in Jib.
@chanseokoh So we do have the src/main/jib
extra files feature which could probably be used for this.
@saturnism I'll look more into this as well.
Oh, is src/main/jib
already usable? But I guess we don't have the feature to define arbitrary env variables yet (but will soon)?
@chanseokoh Yes it is usable, but in an incubating state (hence why there is no documentation).
oops, is that default credential causing your start up issue?
the root issue is unrelated to adc. i.e., even w/ credential in place, the tomcat server didn't start.
Easier to test w/ 1-bootstrap/guestbook-frontend and add Jib to it.
./mvnw spring-boot:run
<-- server starts and listens to port 8080./mvnw jib:build
then, run the container <-- tomcat server does not start, container exitsthe root issue is unrelated to adc. i.e., even w/ credential in place, the tomcat server didn't start.
Oops... ADC was causing a problem, but yeah, you're right, the tomcat does not start with Jib, and I think I know why. If I look at the UPDATE: what I said is true, but directly running the main META-INF/MANIFEST.MF
, the main class of this Spring-Boot-crafted excutable WAR (and probably JAR too?) that does some kind of black magic is supposed to be org.springframework.boot.loader.WarLauncher
.com.example.frontend.FrontendApplication
should still work.
Main-Class: org.springframework.boot.loader.WarLauncher
Start-Class: com.example.frontend.FrontendApplication
...
What we instead have in Dockerfile
is
ENTRYPOINT ["java","-cp","/app/libs/*:/app/resources/:/app/classes/","com.example.frontend.FrontendApplication"]
So, adding Jib to https://github.com/spring-projects/spring-petclinic and doing ./mvnw compile jib:build
generates a container that starts Tomcat fine. I'm looking at what difference there could be in this case.
FYI, in the case of Spring-Boot-craft executable JAR (i.e., <packaing>jar</packaing>
instead of <packaing>war</packaing>
), the main class is set to the JAR launcher:
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.frontend.FrontendApplication
Explicitly setting org.springframework.boot.loader.WarLauncher
(or JarLauncher
) as the main class in Jib's configuration won't work, because these launchers require additional classes and library that Spring Boot injects at the time of packaging a WAR or a JAR.
I have been able to create a Jar archive w/ custom manifest w/ the app as the main class. See https://github.com/saturnism/spring-petclinic-gcp/blob/master/pom.xml#L146
So, adding Jib to https://github.com/spring-projects/spring-petclinic and doing ./mvnw compile jib:build generates a container that starts Tomcat fine. I'm looking at what difference there could be in this case.
The difference I think is that, spring-petclinic is a pure Java application (an usual Java application with main()
), whereas @saturnism's application basically retains the WAR structure from which Spring Boot has the ability to create either an (executable) WAR or a JAR with some black magic. This WAR-structure application has this ServletInitializer.
whereas @saturnism's application basically retains the WAR structure from which Spring Boot has the ability to create either an (executable) WAR or a JAR with some black magic.
I might be wrong with the "WAR structure" terminology... but I am still thinking it is this ServletInitializer
that makes the different, which enables Spring Boot to create a magical executable WAR.
I have been able to create a Jar archive w/ custom manifest w/ the app as the main class. See https://github.com/saturnism/spring-petclinic-gcp/blob/master/pom.xml#L146
@saturnism FYI, Jib does not take a JAR from somewhere or even attempt to package a JAR. It doesn't use a JAR at all, but puts individual class files into the container; there is no JAR packaging at all. That could explain why we have problems with Spring Boot here.
Removing servlet initializer doesn't nor should change anything. The ServletInitializer is for initialization inside of an application server, like Jetty.
Spring Petclinic also packages the Manfiest w/ JarLauncher.
So I've found that the tomcat-embed-core
JARs (like tomcat-embed-core-8.5.31.jar
) are not being added to the guestbook image, which I believe are necessary for the embedded tomcat startup. They do appear in the petclinic image, which is why that starts.
Adding
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
Made it work for me.
Not sure why it wasn't being added since spring-boot-starter-web
includes spring-boot-starter-tomcat
, which includes tomcat-embed-core
.
Ah I found it: @saturnism
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
The scope is set to provided
, but should be none/compile
.
Ah I found it: @saturnism
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>
The scope is set to
provided
, but should be none/compile
.
Thank you very much for this clarification
Description of the issue:
pom.xml
.Expected behavior: Created image should behave like the JAR.
Steps to reproduce:
Environment: MacOS, Maven
jib-maven-plugin
Configuration:Log output: Normal Startup w/o Jib
Failed startup w/ Jib
Additional Information: