K. Siva Prasad Reddy
K. Siva Prasad Reddy

Reputation: 12385

SpringBoot Docker image built with gradle bootBuildImage failing to start on any port < 1024

I have created a simple SpringBoot application using 2.3.3.RELEASE and I am able to create docker image using ./gradlew bootBuildImage.

Code to reproduce this issue: https://github.com/sivaprasadreddy/spring-boot-aws-cdk-demo

build.gradle

springBoot {
    buildInfo()
}

bootJar {
}

bootBuildImage {
    imageName = "sivaprasadreddy/spring-boot-aws-cdk-demo"
}

I can start the container successfully as follows:

docker run -p 18080:8080 sivaprasadreddy/spring-boot-aws-cdk-demo

But if I try to run the app on any different port like 80 using the following command the application is failing to start.

docker run -e SERVER_PORT=80 -p 80:80 sivaprasadreddy/spring-boot-aws-cdk-demo

2020-08-16 12:34:22.707  WARN 1 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
2020-08-16 12:34:22.715  INFO 1 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-08-16 12:34:22.726  INFO 1 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2020-08-16 12:34:22.727  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
2020-08-16 12:34:22.731  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-08-16 12:34:22.747  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2020-08-16 12:34:22.754  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2020-08-16 12:34:22.779  INFO 1 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-08-16 12:34:22.788 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:895) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at com.sivalabs.todolist.TodoListApplication.main(TodoListApplication.java:19) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[workspace/:na]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:109) ~[workspace/:na]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[workspace/:na]
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) ~[workspace/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ... 22 common frames omitted
Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed
    at org.apache.catalina.core.StandardService.addConnector(StandardService.java:231) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    ... 24 common frames omitted
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1067) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    ... 26 common frames omitted
Caused by: java.net.SocketException: Permission denied
    at java.base/sun.nio.ch.Net.bind0(Native Method) ~[na:na]
    at java.base/sun.nio.ch.Net.bind(Unknown Source) ~[na:na]
    at java.base/sun.nio.ch.Net.bind(Unknown Source) ~[na:na]
    at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(Unknown Source) ~[na:na]
    at java.base/sun.nio.ch.ServerSocketAdaptor.bind(Unknown Source) ~[na:na]
    at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:228) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:211) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1141) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:592) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.connector.Connector.startInternal(Connector.java:1064) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    ... 28 common frames omitted

I am able to build the docker image using docker build -t sivaprasadreddy/spring-boot-aws-cdk-demo . and I can successfully run the container using docker run -e SERVER_PORT=80 -p 90:80 sivaprasadreddy/spring-boot-aws-cdk-demo

Dockerfile:

FROM openjdk:11-jdk-slim
VOLUME /tmp
ADD build/libs/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8787"
ENV SPRING_PROFILES_ACTIVE "default"
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -jar /app.jar" ]

PS: The issue is clearly using the ports < 1024. So, now the questions becomes is there any possibility to customize SpringBoot Gradle Plugin to generate docker image that allows to use ports < 1024 ?

Upvotes: 2

Views: 5888

Answers (3)

Daniel Jacob
Daniel Jacob

Reputation: 1536

It would be handy if you posted the dockerfile, but my guess would be that you are trying to run the container as non-root. By default non-root users don't have permissions to access portnumbers under 1024.

In order to achieve this you need to add the following line in your dockerfile

RUN groupadd --gid 5000 docker && useradd --home-dir /home/default --create-home --uid 5000 --gid 5000 --shell /bin/sh --skel /dev/null default

Upvotes: 1

akop
akop

Reputation: 7845

I think, that the docker-image is rootless. This means that all ports below 1024 are not useable (they need root-permission).

But why do you need to change the port? With docker you can map the port. Like this:

docker run -p 80:8080 sivaprasadreddy/spring-boot-aws-cdk-demo

Upvotes: 3

Karthik R
Karthik R

Reputation: 5786

Its just 'access' issue as you run as non-root for port 80 which requires it. It falls under privileged ports:

Reference: https://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html

From logs:

Caused by: java.net.SocketException: Permission denied
    at java.base/sun.nio.ch.Net.bind0(Native Method) ~[na:na]

Run as sudo user or follow steps here: https://serverfault.com/questions/112795/how-to-run-a-server-on-port-80-as-a-normal-user-on-linux

or use a proxy like nginx to reroute.

Upvotes: 1

Related Questions