skip to Main Content

I am new to Docker-compose and I am struggling to run my Tomcat+Postgres stack.

I have “successfully” launched the stack, in the sense that my Java Web Application successfully connects to Postgresql and deploys into Tomcat.

But no port is mapped and the hosts are not reachable. But the hosts can reach themselves.

The following is my project layout (I use Palantir’s Gradle Docker plugin)

  • edcom3-docker/
    • edcom3-tomcat/
    • build.gradle
    • src/main/
      • docker/Dockerfile
      • resources
      • webapps/edcom3.war
      • (Other stuff I am too lazy to list)
    • edcom3-postgres/
    • build.gradle
    • src/main/
      • docker/Dockerfile
    • src/main/docker/
    • docker-compose.yml
    • .env

Thanks to Gradle Docker plugin, the context is built into $baseDir/build/docker

The following is my current docker-compose.yml. I needed to expand the directory structure to justify links

version: '3'
services:
  edcom3-postgres:
    build: ../../../edcom3-postgres/build/docker
    image: edcom3-postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: postgres
#    networks:
#      - edcom3-net
    expose:
      - "5432/tcp"
    ports:
    - "${EDCOM3_SQL_PORT}:5432"
    volumes:
      - "edcom3-postgres-data:/var/lib/postgresql/data"
  edcom3-tomcat:
    depends_on:
      - edcom3-postgres
    build: ../../../edcom3-tomcat/build/docker
    image: edcom3-tomcat
    expose:
      - "8009/tcp"
      - "8080/tcp"
    ports:
    - "${EDCOM3_AJP_PORT}:8009"
    volumes:
      - "edcom3-config-location:/home/tomcat"
      - "edcom3-file-repository:/mnt/fileRepository"
      - "edcom3-logs:/mnt/phoenix-logs"
      - "edcom3-tomcat-logs:/usr/local/tomcat/logs"
    restart: always
#    networks:
#      - edcom3-net
    links:
      - edcom3-postgres

#networks:
#  edcom3-net:
#    driver: bridge
#    internal: true

volumes:
  edcom3-config-location:
  edcom3-file-repository:
  edcom3-logs:
  edcom3-tomcat-logs:
  edcom3-postgres-data:

What I have tried

I run first gradle :edcom3-tomcat:docker and :edcom3-postgres:gradle to build the contexts.

Then I cd into src/main/docker of the main project, where the above docker-compose is located, and launch the stack.

edcom3-tomcat_1    | 06-Feb-2020 15:51:12.943 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/usr/local/tomcat/webapps/edcom3.war] has finished in [66,278] ms

The stack starts and the application is deployed. As you can see, I have instructed docker-compose to expose AJP port (variables are bound to port 50000 and 50001) so that Apache can reverse-proxy into Tomcat. Apache is a stand-alone container.

But I can’t find the port bindings in docker ps

[docker@DOCKER01 ~]$ docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS                      PORTS                                                      NAMES
78acb0e5ff5d        edcom3-tomcat                    "catalina.sh run"        11 minutes ago      Up 11 minutes (unhealthy)                                                              edcom3_edcom3-tomcat_1
60bbed143adf        edcom3-postgres                  "docker-entrypoint.s…"   16 minutes ago      Up 16 minutes (unhealthy)                                                              edcom3_edcom3-postgres_1
23265ae20793        postgres:11.6-alpine             "docker-entrypoint.s…"   7 weeks ago         Up 2 days                   192.168.0.72:5432->5432/tcp                                postgres11
9c8b0eda42e9        portainer/portainer:1.23.0       "/portainer --ssl --…"   7 weeks ago         Up 2 days                   192.168.0.72:8000->8000/tcp, 192.168.0.72:9000->9000/tcp   keen_grothendieck
63985a2c656f        initech/sqlserver2017:20191204   "/opt/mssql/bin/nonr…"   2 months ago        Up 2 days (healthy)         192.168.0.72:1433->1433/tcp                                sqlserver2017
09589b076513        oracle/database:12.2.0.1-SE2     "/bin/sh -c 'exec $O…"   2 months ago        Up 2 days (healthy)         192.168.0.72:1521->1521/tcp, 192.168.0.72:5500->5500/tcp   oracle12c

Considerations: (un)commenting the network in the compose file has no effect.

I can clearly see that the containers are reported unhealthy. I tried to remove the health check from their Dockerfiles but it had no effect: the container is not determined its health but still no port available

Then I tried to ping the containers within their network (network block in docker-compose commented out). From my Windows workstation

> docker inspect 4ce2be94fbe8 (tomcat)

....

                    "NetworkID": "8196b4a9dab76b899494f427286c0a9250ba4b74f8e4c6dbb8cd4459243509ac",
                    "EndpointID": "17d969ad49fe127870f73e63211e309f23d37a23d2918edb191381ffd7b2aaff",
                    "Gateway": "172.25.0.1",
                    "IPAddress": "172.25.0.3",

....

(Oh, cool, the server is listening on port 8080 on that)

> telnet 172.25.0.1 8009
(connection failed)

> tracert 172.25.0.1
(a number of nodes)

It is interesting to see tracert result (which I have omitted). Basically Windows 10 tries to reach 172.25.x.x, which is notably a class 16 private IP address, through the main gateway, only to be ignored by our external ISP (4 external hosts appear in the trace)

Okay, Windows has not configured routing tables.

Let’s try on our docker server running CentOS

$ docker inspect 60bbed143adf

.....

                    "NetworkID": "10a52bc3f822f756f5b76c300787be5af255afd061453add0c70664f69ee06c8",
                    "EndpointID": "f054747f6a5d0370916caa74b8c01c3e7b30d255e06ebb9d0c450bf1db38efb1",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.2",
                    "IPPrefixLen": 16,
.....

[docker@DOCKER01 ssl]$ telnet 172.19.0.3 8009
Trying 172.19.0.3...
Connected to 172.19.0.3.
Escape character is '^]'.

It’s interesting that I can finally access the network

Conclusion: question

Can somebody help me understand why can’t I map port 8009 (AJP) from the web container to the host machine? If I can achieve that, the web application will be available to Apache load balancer via AJP protocol

2

Answers


  1. Chosen as BEST ANSWER

    I have found that the edcom3-net was the main culprit to blame.

    My issue was caused by a number of unfortunate coincidences, so let me put order on that.

    Ports not exposed with network

    Simply put, I have found that if you connect a Docker container to an internal network, it won't publish ports on the host. It must be connected to the host network to publish ports. If you comment the network part on the docker-compose file, ports will be successfully publishes

    Host up but not reachable when internal network is in use

    I found this to be another aspect, which requires me additional investigation and rather a separate Q&A.

    What I have discovered is that when you attach a container to an internal network, it will obtain its own private IP address and not expose the ports. Still, the container has IP address and ports available. There are two noticeable things here

    1. If you run a load balancer on another Docker container (this time on the host network)

    You will have a hard time reaching the target container. You must configure routing tables to link multiple networks.

    2. If the load balancer runs on the Docker host, instead

    It should be easier to set a reverse proxy. However, I had the unfortunate coincidence to run this scenarion on a Windows host. And Docker Desktop, in my case, did not set the routing tables. Even after docker network inspecting the network edcom3-net several times, the 172.16.x.x address of Tomcat was routed via the main gateway


  2. In the compose file, the container port 8009 is exposed on the host port ${EDCOM3_AJP_PORT}.
    So you should be able to access your tomcat AJP with <IP-OF-DOCKER-SERVER>:${EDCOM3_AJP_PORT}.

    Port publication is done with the ports section, expose only “expose ports without publishing them to the host machine – they’ll only be accessible to linked services”

    But we can see in the docker ps that the PORTS section is empty for the edcom3-tomcat container, so I’ll suggests that EDCOM3_AJP_PORT is not well defined (but then it should fail…)

    On using 172.25.0.1:8009: the container IP is private to the docker host (the CentOS machine), so no problem to access it (on any listening port of the container) from this machine, but it’s not possible from any other machine.

    See Container networking – Published ports:

    By default, when you create a container, it does not publish any of its ports to the outside world.
    To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the –publish or -p flag.
    This creates a firewall rule which maps a container port to a port on the Docker host.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search