Help With Published/Exposed Ports

I have a docker compose setup for local development with several containers on a network. In the network I am running a redis, mongo, mysql image all of which I can access from localhost without issue.

However I have a few containers that are based off the official node docker image that cannot be accessed from localhost.

This is an example of the Dockerfile one of the containers are being built from:

FROM node:16.15.1 as build
WORKDIR /app
COPY package*.json ./
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > /app/.npmrc \
    && npm ci
COPY . .
RUN npm run build

FROM node:16.15.1
WORKDIR /app
COPY --from=build /app/dist /app/dist
COPY --from=build /app/package*.json /app/
COPY --from=build /app/config /app/config
COPY --from=build /app/assets /app/assets
COPY --from=build /app/.npmrc /app/.npmrc
RUN npm ci
EXPOSE 8080
ARG BUILD=undetermined
ENV BUILD=$BUILD
CMD ["npm", "run", "start"]

If I inspect the container with docker inspect account I can clearly see that the ports are all mapped correctly.

"PortBindings": {"8080/tcp": [{ "HostIp": "", "HostPort": "8084". }]}

"ExposedPorts": {"8080/tcp": {}}

"NetworkSettings": {"Ports": {"8080/tcp": [{"HostIp": "0.0.0.0", "HostPort": "8084"}, {"HostIp": "::", "HostPort": "8084"}]}}

If I access the docker container directly with docker exec -it account bash and curl port 8080 from inside the container with curl 0.0.0.0:8080 I get the expect response from the node application {"service":"account-api","env":"development","version":"1.0.13","build":"undetermined","uptime":"8m"}.

However if i try and curl from outside the container with curl localhost:8084 I receive curl: (56) Recv failure: Connection reset by peer.

I can’t seem to figure out why these specific containers are giving me this issue as I am able to access the redis, db, mysql and myiflip containers on localhost on their respective ports without issue.

I also have a web based application running on port 80 that I can access without issue on localhost.

Here is my docker-compose.yml

version: '3.5'

services:

  account:
    hostname: 'account'
    container_name: 'account'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/account-api.git#${ACCOUNT_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      LOGGING_LEVEL: 'debug'
      COOKIE_KEY: 'secret'
      INFUSION_APP: '${INFUSION_APP}'
      INFUSION_KEY: '${INFUSION_KEY}'
      AUTH_API_URL: 'http://auth:8080'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8084:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

  api:
    hostname: 'api'
    container_name: 'api'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/motivated-api.git#${API_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      MAILGUN_KEY: '${MAILGUN_KEY}'
      COOKIE_KEY: 'secret'
      DATA_API_URL: 'http://datafeed:8080/v2'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8085:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

  auth:
    hostname: 'auth'
    container_name: 'auth'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/auth-api.git#${AUTH_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      LOGGING_LEVEL: 'debug'
      JWT_EXPIRATION: '15m'
      COOKIE_KEY: 'secret'
      ACCOUNT_API_URL: 'http://account:8080/v1'
      DEV_HOST: 'http://localhost'
      APP_DOMAIN: 'http://localhost'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8082:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

  datafeed:
    hostname: 'datafeed'
    container_name: 'datafeed'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/data-feed-api.git#${DATAFEED_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      MONGO_HOST: 'db'
      REDIS_HOST: 'redis'
      COOKIE_KEY: 'secret'
      DB_HOST: '${ELASTICSEARCH_HOST}'
      DB_USERNAME: '${ELASTICSEARCH_USERNAME}'
      DB_PASSWORD: '${ELASTICSEARCH_PASSWORD}'
      ZILLOW_KEY: '${ZILLOW_KEY}'
      ACCOUNT_API_URL: 'http://account:8080/v1'
      EMAIL_API_URL: '${EMAIL_API_URL}'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8086:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

  db:
    hostname: 'db'
    container_name: 'db'
    env_file: '.env'
    image: 'mongo:jessie'
    logging:
      driver: 'none'
    ports:
      - '27017:27017'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

  es:
    hostname: 'es'
    container_name: 'es'
    env_file: '.env'
    image: 'docker.elastic.co/elasticsearch/elasticsearch:6.2.4'
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - '9200:9200'
      - '9300:9300'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

  email:
    hostname: 'email'
    container_name: 'email'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/email-api.git#${EMAIL_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      REDIS_HOST: 'redis'
      LOGGING_LEVEL: 'debug'
      COOKIE_KEY: 'secret'
      MAILGUN_APP_KEY: '${MAILGUN_APP_KEY}'
      MAILGUN_APP_TOKEN: '${MAILGUN_APP_TOKEN}'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8099:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'redis'

  geo:
    hostname: 'geo'
    container_name: 'geo'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/geo-api.git#${GEO_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      REDIS_HOST: 'redis'
      COOKIE_KEY: 'secret'
      DB_HOST: '${ELASTICSEARCH_HOST}'
      DB_USERNAME: '${ELASTICSEARCH_USERNAME}'
      DB_PASSWORD: '${ELASTICSEARCH_PASSWORD}'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8088:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

  images:
    hostname: 'images'
    container_name: 'images'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/images.git#${IMAGES_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
    ports:
      - '8083:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

  mm:
    hostname: 'mm'
    container_name: 'mm'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/mail-manager-api.git#${MM_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      COOKIE_KEY: 'secret'
      MAILGUN_KEY: '${MAILGUN_KEY}'
      ACCOUNT_API_URL: 'http://account:8080/v1'
      DATA_API_URL: 'http://datafeed:8080/v2'
      MOTIVATED_API_URL: 'http://api:8080/v1'
      SCI_NET_URL: 'http://scinet:8080/v1'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8087:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

  myiflip:
    hostname: 'myiflip'
    container_name: 'myiflip'
    env_file: '.env'
    build:
      context: '/home/shenry/Code/AWS-DOCKER/myiflip/.'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
        CIRCLE_BRANCH: 'local'
        SITE_DOMAIN: 'localhost'
        AWS_ACCESS_KEY_ID: '${AWS_ACCESS_KEY_ID}'
        AWS_SECRET_ACCESS_KEY: '${AWS_SECRET_ACCESS_KEY}'
        AWS_REGION: '${AWS_REGION}'
        AWS_ACCOUNT_ID: '${AWS_ACCOUNT_ID}'
        AWS_RESOURCE_NAME_PREFIX: 'myiflip'
        DOCKER_DOMAIN_AUTH: 'http://host.docker.internal:8082'
        DOCKER_DOMAIN_ACCOUNT: 'http://host.docker.internal:8084'
    ports:
      - '80:80'
      - '9000:9000'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'mysql'
      - 'db'
      - 'redis'
      - 'account'
      - 'auth'
      - 'es'
    volumes:
      - '/home/shenry/Code/AWS-DOCKER/myiflip/web:/web:rw'

  mysql:
    hostname: 'mysql'
    container_name: 'mysql'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/sci-net.git#${SCINET_BRANCH:-develop}'
      dockerfile: 'Dockerfile.db'
    ports:
      - '3306:3306'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    logging:
      driver: 'none'

  phone:
    hostname: 'phone'
    container_name: 'phone'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/phone-api.git#${PHONE_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      LOGGING_LEVEL: 'debug'
      COOKIE_KEY: 'secret'
      ES_HOST: 'http://es:9200'
      SCINET_URL: 'http://scinet:8080/v1'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8092:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

  redis:
    hostname: 'redis'
    container_name: 'redis'
    env_file: '.env'
    image: 'redis:alpine'
    logging:
      driver: 'none'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    ports:
      - '6379:6379'

  scinet:
    hostname: 'scinet'
    container_name: 'scinet'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/sci-net.git#${SCINET_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      DB_HOST: 'db'
      REDIS_HOST: 'redis'
      SEEDING: 'auto'
      MYSQL_HOST: 'mysql'
      COOKIE_KEY: 'secret'
      MAILGUN_KEY: '${MAILGUN_KEY}'
      ACCOUNT_API_URL: 'http://account:8080/v1'
      AUTH_API_URL: 'http://auth:8080'
      DATA_API_URL: 'http://datafeed:8080/v2'
      MOTIVATED_API_URL: 'http://api:8080/v1'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8089:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'
      - 'mysql'

  sms:
    hostname: 'sms'
    container_name: 'sms'
    env_file: '.env'
    build:
      context: 'https://${GITHUB_ACCESS}${GITHUB_PATH}/sms-api.git#${SMS_BRANCH:-develop}'
      args:
        NPM_TOKEN: '${NPM_TOKEN}'
    environment:
      NPM_TOKEN: '${NPM_TOKEN}'
      NODE_ENV: 'development'
      REDIS_HOST: 'redis'
      LOGGING_LEVEL: 'debug'
      COOKIE_KEY: 'secret'
      TWILIO_APP_KEY: '${TWILIO_APP_KEY}'
      TWILIO_APP_TOKEN: '${TWILIO_APP_TOKEN}'
      TWILIO_APP_PHONE: '${TWILIO_APP_PHONE}'
      JWKS_ENDPOINT: '${OIDC_JWKS_URL}'
    ports:
      - '8098:8080'
    networks:
      - 'docker'
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    depends_on:
      - 'db'
      - 'redis'

networks:

    docker:
      driver: 'bridge'
      driver_opts:
        com.docker.network.driver.mtu: '1500'
        com.docker.network.bridge.enable_icc: 'true'

Here is my docker network inspect when running docker compose up myiflip which launches es, db, redis, account, auth and myiflip per the docker-compose.yml config.

[
    {
        "Name": "code_docker",
        "Id": "f4626a53ecf2c9fb063bd803ab09387f02705e13dbf616f81038783fc9040d3a",
        "Created": "2023-08-10T21:04:17.639694576Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5f1a1570794a5e8a2ab13698d30700bb2055637ce92239bf2aef812d9d300771": {
                "Name": "account",
                "EndpointID": "f29ff167fc9a6dbe7a0becc32730cb4661243eeab0ec782c9767e12701954373",
                "MacAddress": "02:42:ac:13:00:06",
                "IPv4Address": "172.19.0.6/16",
                "IPv6Address": ""
            },
            "6430e31369e1bc2652c8c5ccc821a73b62ae58484048afd4dc5e5955d08ff3e2": {
                "Name": "myiflip",
                "EndpointID": "fafbf3fa07332b9442c380f3e2c2d609b88ba648c8bcd8b309c9bc29fc4223ae",
                "MacAddress": "02:42:ac:13:00:08",
                "IPv4Address": "172.19.0.8/16",
                "IPv6Address": ""
            },
            "91a5195390ff542482bf05af91442cf2848e59b864e7833fac6e3054a1f81004": {
                "Name": "mysql",
                "EndpointID": "ed257ba8663aea1b839aed6217273f0bec54054b27d7def23658a53c9a054a19",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "987f741429a5dae7fc9743308c37029a4cc8823dc26f77ff6d6b1cf8efa19bd9": {
                "Name": "es",
                "EndpointID": "0c4b739a2f89395fd729a229e211a6ce6e8dffed40e0126924b281d66eaae239",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "bb407770e6a007e1d25a0ea776707bfc747f8958c88d2237ba0d64195f599f83": {
                "Name": "db",
                "EndpointID": "67d53f3ae5c2858030dd7a82c81930006a3c5a24788d3caf43978b1039554795",
                "MacAddress": "02:42:ac:13:00:04",
                "IPv4Address": "172.19.0.4/16",
                "IPv6Address": ""
            },
            "cffb75a05d7bd824dab686a5f8d3a0cbb21385bb73411f24b72563e8a4b20cbd": {
                "Name": "auth",
                "EndpointID": "2c79de6cdff66072ea49a91a095ad609c273e29c894f480e5db93bc7c95d6545",
                "MacAddress": "02:42:ac:13:00:07",
                "IPv4Address": "172.19.0.7/16",
                "IPv6Address": ""
            },
            "f1a703c5b8f1058f9340e50d06df203c9da883ead4299ea9cfd309d6e7f485d5": {
                "Name": "redis",
                "EndpointID": "d9ae2aaa29e7adfdc631a1328be357778ba11cb93b090e3b0b781889e3a94fb0",
                "MacAddress": "02:42:ac:13:00:05",
                "IPv4Address": "172.19.0.5/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {
            "com.docker.compose.network": "docker",
            "com.docker.compose.project": "code",
            "com.docker.compose.version": "2.20.2"
        }
    }
]

Any help with accessing these containers would be greatly appreciated. The containers in having this issue are account, auth, datafeed, email, geo, images, mm, phone, scinet, sms. Again these are all based off the official node image per their Dockerfile.

NOTE: From within the account docker container I can curl myiflip:80, however I am not able to curl auth:8082 or curl auth:8080. It’s almost as if the published port is not binding to the internal exposed port of the container for some reason.

Your previous, now already deleted topic (as you requested) was in Docker Destkop for Mac category. Are you still using Mac or Linux?

I am running this in ubuntu server in a UTM virtual machine now to avoid the issues with MacOS networking.

Than there must be something in your node container that prevents you from connecting to localhost from outside the container. For example your nodejs application might listen on localhost only instead of 0.0.0.0.

I recently found out that sometimes docker is actually able to route traffic to the localhost of a container, but I don’t remember the exact case so this is my quick guess.

Here is a tutorial I found as first result without reading it, but scrolled down and it mentiones listening on 0.0.0.0

I can understand that. However, as I had mentioned I can connect to the container, curl 0.0.0.0:8080, and the results come back as expected.

Well I just figured it out… and it makes absolutely no sense to.

I removed the env_file: “.env” from each container and magically it started working.

It makes absolutely no sense to me considering that docker compose looks for .env in the same directory as the config file by default.

How would this setting be any different, I’m not sure, but that was my issue.

You can compare the effective compose configuration, if you compare the output of docker compose config of your old and new configuration.

The command above will render the effective compose configuration, including all default configuration items, substituted variables, injected envs from .env rendered into your created config.

I might have missed something but I thought you referred to “from inside the container”

If it is the case, that means nothing, since 0.0.0.0 is not a real ip address it just means the service should listen on all available ipv4 addresses. When you use curl 0.0.0.0:8080 you can access a service listening only on localhost because curl will try it on all available ipv4 addresses. From outsdie the container you need a container with a service that listens on a port to which the host can forward requests.

Docker Compsoe reads .env files so you can use those variables in the compose file. env_file however (If I remember correctly) for the containers. So whatever you define in the env file, will be available in the container directly without passing the environment variables to the services in the compose file.