Ping
Ping

Reputation: 635

The server.port property of a Spring Boot web application is ignored by Docker Engine on Windows

TL;DR

The server.port property defined in a Spring Boot application.properties file is not getting honored by the Docker engine when running a web application in Tomcat.


Background :

I have a simple Spring Boot application containing a single rest endpoint. I am able to run this application in Eclipse and access the rest endpoint successfully from the browser.

However, when I try to deploy the same application in a Docker container, I am unable to access the rest endpoint from the browser.

Dockerfile :

FROM tomcat
EXPOSE 8000
RUN rm -rf /user/local/tomcat/webapps/*
COPY ./target/my-web-app.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh","run"]

Spring Boot application.properties :

spring.application.name=my-web-app
server.port=8000
spring.jpa.show-sql=true
spring.h2.console.enabled=true

Docker images output :

CK@Ping MINGW64 /c/Program Files/Docker Toolbox
$ docker images
REPOSITORY           TAG                  IMAGE ID            CREATED             SIZE
myrepo/my-web-app    0.0.1-SNAPSHOT       625e9d889139        4 minutes ago       694MB

Start the container :

Note that I map the server.port of my Spring Boot application.properties file to the external port.

docker run -p 8000:8000 -d myrepo/my-web-app:0.0.1-SNAPSHOT

docker container ls output :

CONTAINER ID        IMAGE                                                COMMAND                  CREATED                  STATUS              PORTS                               NAMES
3eff09347de3      myrep/my-web-app:0.0.1-SNAPSHOT              "catalina.sh run"        Less than a second ago            Up 4 seconds        0.0.0.0:8000->8000/tcp, 8080/tcp    hardcore

Error in the Browser :

This site can’t be reached

I am trying to access the URL using :

http://192.168.99.100:8000/my-web-app/getResults

The same app works just fine when launched from Eclipse instead of a Docker container and I am able to access the rest end point using :

http://localhost:8000/my-web-app/getResults

Update/Edit:

I found the root cause. I need to map port 8000 to 8080 instead of mapping 8000 to 8000 itself :

docker run -p 8000:8080 -d myrepo/my-web-app:0.0.1-SNAPSHOT

This means that the server.port property that I defined in my application.properties is not getting honored when starting up the container.

What is even more strange is that I can set the server.port to 8111 for example and still be able to access the URL if I use -p 8000:8080.

However, tomcat starts up on the port specified by server.port if I run the same application in Eclipse rather than a Docker container.

Bottom line : The server.port property defined in a Spring Boot application.properties file is not getting honored by the Docker engine.

Upvotes: 2

Views: 2468

Answers (1)

Michał Krzywański
Michał Krzywański

Reputation: 16930

Solution for standalone tomcat on docker image

server.port property is used to configure port for the spring boot embedded server. In your case you are trying to deploy a war file with your application to a standalone tomcat server (which is contained in your image) - so the embedded spring boot server is not even used and setting this property has no effect.

To achieve what you want you would have to modify the server.xml file of the tomcat that is installed on your image and modify the connector port. So you could copy the overriden server.xml to your image:

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">
    <!-- change port here-->
    <Connector port="8000" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

and the dockerfile :

FROM tomcat:9.0
EXPOSE 8000

COPY ./target/my-web-app.war /usr/local/tomcat/webapps/ROOT.war

#override server.xml
COPY server.xml /usr/local/tomcat/conf/

CMD ["catalina.sh","run"]

and then run your image:

docker run -p 8000:8000 -d myrepo/my-web-app:0.0.1-SNAPSHOT

Solution for spring boot jar with embedded tomcat running in docker container

If you have your spring boot jar copied to your image, you can set SERVER_PORT environment variable during container launching, to override the property defined in application.properties :

docker container run -e SERVER_PORT=8000 -p 8000:8000 myimage

Upvotes: 5

Related Questions