Set up a simple project following the documentation at https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/#getting-started
Run ./gradlew bootBuildImage
and observe this failure:
$ ./gradlew bootBuildImage
> Task :generateAot
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.security.config.annotation.web.configuration.AutowiredWebSecurityConfigurersIgnoreParents it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.messaging.handler.annotation.MessageMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.transaction.annotation.Transactional it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: javax.transaction.Transactional it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.transaction.annotation.Propagation it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.ExceptionHandler it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestMethod[] it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.ModelAttribute it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.InitBinder it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestMethod it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.ResponseBody it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestBody it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestHeader it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RestController it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestParam it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.PathVariable it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.Mapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.RequestMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.GetMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.PostMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.PutMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.DeleteMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.PatchMapping it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.bind.annotation.ResponseStatus it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.http.HttpStatus it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.reactive.socket.server.upgrade.UndertowRequestUpgradeStrategy it will be skipped
Failed verification check: this type was requested to be added to configuration but is not resolvable: org.springframework.web.reactive.socket.server.upgrade.JettyRequestUpgradeStrategy it will be skipped
> Task :compileAotJava
Note: /home/candrews/projects/demo/build/generated/sources/aot/org/springframework/aot/StaticSpringFactories.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
> Task :bootBuildImage
Building image 'docker.io/library/demo:0.0.1-SNAPSHOT'
> Pulling builder image 'docker.io/paketobuildpacks/builder:base' ..................................................
> Pulled builder image 'paketobuildpacks/builder@sha256:1ac94f392f25db5d2d52a6c0f1ede01cb63f1bd92908e78afb720c1e2cd32baa'
> Pulling run image 'docker.io/paketobuildpacks/run:base-cnb' ..................................................
> Pulled run image 'paketobuildpacks/run@sha256:0bf521429c5fac06616ef542da735f9e34c4997cc5d5987242eb7199b04ac923'
> Executing lifecycle version v0.10.2
> Using build cache volume 'pack-cache-96f12fa81ff5.build'
> Running creator
[creator] ERROR: failed to initialize docker client: failed to connect to docker socket: dial unix /var/run/docker.sock: connect: permission denied
> Task :bootBuildImage FAILED
FAILURE: Build failed with an exception.
Comment From: candrews
I believe that the problem occurs only when SELinux is enabled (as it on Fedora and Red Hat). It seems that the docker socket is being mounted in a docker container, which isn't allowed by the SELinux policy, as explained at https://bugzilla.redhat.com/show_bug.cgi?id=1495053#c2
The solution would be to run in privileged mode... and I think that makes sense.
How can one specify privileged mode? I was thinking there would be something along these lines for gradle:
bootBuildImage {
docker {
privileged = true
}
}
but there isn't a privileged
method in DockerSpec
Even if there was... should privileged be enabled by default?
Comment From: scottfrederick
How can one specify privileged mode? there isn't a privileged method in DockerSpec
You are correct, it is not currently possible to configure the container that runs the CNB builder to run in privileged mode. We can add a configuration option to the Maven and Gradle plugins similar to what you suggested.
A privileged parameter would belong under bootBuildImage { }
for the Gradle plugin and in the <image></image>
tag for the Maven plugin since it determines how the builder container is configured. The docker { }
spec in the Gradle plugin and the <docker></docker>
tag in the Maven plugin configure the connection between the plugin and Docker Engine, which is a separate concern.
should privileged be enabled by default?
No, the configuration should be secure by default. Running a container in privileged mode makes the container much less secure, and a user should explicitly opt into running in privileged mode only after they've determined they trust the builder and all buildpacks that are being run in the container.
Comment From: scottfrederick
The pack
CLI appears to accommodate this use case without running the container in privileged mode. pack build
supports a --docker-host
option that can be used to provide the build container with an alternate Docker host to override the default /var/run/docker.sock
. Setting something like --docker-host=tcp://127.0.0.1:2375
to point to the host Docker daemon along with --network=host
to connect the build container to the host network makes the builder work on SELinux without compromising security.
Flagging this for team attention to discuss the options. This may also require some design work and experimentation to determine the best approach.
Comment From: wilkinsona
@scottfrederick Am I right in thinking that pack
doesn't support running the builder's container in privileged mode, or have I just failed to find it?
Comment From: scottfrederick
pack
doesn't support running the builder's container in privileged mode
That's my conclusion after searching the code. I don't see any issues suggesting this is something that's under consideration for pack
either. I did see the secure Linux use case mentioned a few times as one of several problems that can be solved with the combination of --docker-host
and --network
. It's more work for Spring Boot to implement two options similar to pack's --docker-host
and --network
, but I'm inclined to think it's the better path.
Comment From: scottfrederick
After a team discussion, we've decided to maintain parity with the pack
CLI. Issues #25876 and #25877 have been created to add support for options similar to pack's --docker-host
and --network
, which should be sufficient to address this secure Linux use case as well as other use cases.
Comment From: izeye
Looking at the last comment from @scottfrederick and the label, this seems to be meant to be closed.
Comment From: snicoll
Good catch, once again, @izeye. Thanks!
Comment From: wsams
fwiw I'm getting ERROR: failed to initialize docker client: failed to connect to docker socket: dial unix /var/run/docker.sock: connect: permission denied
as well when running builds inside a Kubernetes pod. I have access to the docker unix socket. I can run docker commands just fine. (Java 11, Spring Boot 2.5.1, k8s 1.19, maven 3.6, docker 20.10.3) I'm also running as root in a privileged container and still no luck.
Comment From: scottfrederick
@wsams Please do not post the same question on several issues. Doing this creates noise and could result in multiple people trying to help and wasting time. This is a question that would be better suited to Stack Overflow.