javaspringdockerdocker-composewiremock

Wiremock Docker reporting Unhealthy Health status when using a port not 8080


I am setting up a wiremock docker for running my (Spring) app locally and running tests locally and in a pipeline. I am using port 8081 rather than port 8080 as 8080 is used by the application to accept requests, and wiremock is mocking outgoing requests from the app to a 3rd party.

I have found that I need to add a custom healthcheck to point to the correct port (8081) otherwise the default healthcheck seems to be looking at port 8080 and then then Health check fails and my app wont start up.

My question is, is there a setting I should be using rather than adding a custom health check as I have done below.

This is my working docker-compose.yaml

  wiremock:
    image: registry.myworkplace.com/contributions/wiremock:3x
    environment:
      WIREMOCK_OPTIONS: "--port 8081 --global-response-templating"
    ports:
        - "8081:8081"
    volumes:
      - ./src/test/resources/__files:/home/wiremock/__files
      - ./src/test/resources/mappings:/home/wiremock/mappings
    restart: unless-stopped
    healthcheck:
      test: [ "CMD-SHELL", "curl -f http://localhost:8081/__admin/health || exit 1" ]

When I didn't have the custom Healthcheck app start up would get stuck on

Waiting for wiremock-1 to become healthy (it's starting)

then eventually Waiting for wiremock-1 to become healthy (it's unhealthy)

and when I looked hard in docker on the Inspect Tab for the container I found:

    "Healthcheck": {
        "Test": [
            "CMD-SHELL",
            "curl -f http://localhost:8080/__admin/health || exit 1"
        ],
        "StartPeriod": 5000000000,
        "StartInterval": 100000000
    },

which was what gave me the idea to set a custom healthcheck. I would have expected this to have been updated by the setting of the ports on the compose.


Solution

  • The two ports: numbers don't need to match. It's usually fine if the service is using port 8080 inside the container, and is accessible on port 8081 on the host.

    In most cases it's fine to leave the service's listening port unchanged. If the image is built to listen on port 8080 then keep using that port.

    services:
      wiremock:
        image: registry.myworkplace.com/contributions/wiremock:3x
        environment:
          WIREMOCK_OPTIONS: "--global-response-templating" # but no --port
        ports:
            - "8081:8080"  # second port number matches container-internal port
        volumes: [...]
        restart: unless-stopped
        # do not need to override healthcheck:
    

    If you're calling this from another container, you need to make sure to use the default service port and not the changed port. Calls between containers don't use ports: at all, and if the only thing this is being used for is supporting the other service, you might be able to just remove wiremock: { ports: } entirely.

    services:
      spring-app:
        environment:
          EXTERNAL_SERVICE_URL: http://wiremock:8000/external/api/
    

    Docker doesn't have much automatic wiring between the various service-internal port settings. The port number the process itself is using, the second ports: number, a health-check port, cross-service calls, and a Dockerfile EXPOSE directive (if present) all need to match up, but nothing actually checks any of these, and if you do try to change any of them, you need to change all of the others manually. In your case the image has the original port number 8080 embedded in a command string, and there's no actual Docker-visible connection between that and, say, the exposed port number (if any).