Search code examples
javaspring-bootdockerport

Spring Boot Application doesn't expose the port in Docker


I have built a Spring Boot app and am trying to run it in Docker.

The problem is that when I run it, the output seems to be normal:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.3)

2024-03-03T17:00:09.520Z  INFO 1 --- [           main] com.example.javaapp.Application          : Starting Application v1.0-SNAPSHOT using Java 21 with PID 1 (/javaapp.jar started by root in /)
2024-03-03T17:00:09.532Z  INFO 1 --- [           main] com.example.javaapp.Application          : No active profile set, falling back to 1 default profile: "default"
2024-03-03T17:00:13.840Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8090 (http)
2024-03-03T17:00:13.894Z  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-03-03T17:00:13.894Z  INFO 1 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.19]
2024-03-03T17:00:14.054Z  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-03-03T17:00:14.059Z  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3571 ms
2024-03-03T17:00:14.409Z  INFO 1 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2024-03-03T17:00:15.260Z  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8090 (http) with context path ''
2024-03-03T17:00:15.296Z  INFO 1 --- [           main] com.example.javaapp.Application          : Started Application in 7.211 seconds (process running for 8.78)

but when I curl it, I get:

user@user-laptop:~$ curl http://127.0.0.1:8090
curl: (7) Failed to connect to 127.0.0.1 port 8090 after 0 ms: Connection refused

I run the container via docker run -it javaproj. Here's the application.properties:

server.port=8090
spring.mvc.static-path-pattern=/static/**

And the Dockerfile:

FROM maven AS build
COPY . .
RUN mvn clean package -DskipTests

FROM openjdk:21
COPY --from=build /target/javaapp.jar javaapp.jar
EXPOSE 8090
ENTRYPOINT ["java","--enable-preview","-jar","javaapp.jar"]

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://maven.apache.org/POM/4.0.0"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>javaProject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.3</version>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>21.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-web</artifactId>
            <version>21.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>javaapp</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>21</release>
                    <compilerArgs>--enable-preview</compilerArgs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

My project structure (didn't post directly as an image, because it is quite big)

P.S. I saw this question, but there isn't any clear answer there.


Solution

  • You need to publish ports to access the image from outside it.

    docker run -d -p 8090:8090 javaproj
    

    -d runs the container in the background
    -p 8090:8090 maps port 8090 from the host to port 8090 inside the container

    This way you can check whether the container is listening for traffic on the specified ports:

    docker ps
    

    Then to connect to the container from your machine use the following command:

    curl http://127.0.0.1:8090
    

    An alternative to -p 8090:8090 could be -P, which means publish all exposed ports. Here you can find more information about the difference between expose and publish