Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincent15000's avatar

How is it possible to have 2 different services on the same port ?

Hello,

The application runs with docker, there are several services and I need to run http and soketi on the same port.

According to me, one port should be associated only with one service.

But I'm quite sure that it's possible (my boss wants it and he has great knowledge in networking), but perhaps I don't understand clearly enough what he asked me for.

So is it possible to run 2 different services on the same port and how is this possible ?

I have tried without success.

soketi:
    image: 'quay.io/soketi/soketi:1.6.1-16-alpine'
    container_name: dev-soketi
    environment:
        SOKETI_DEBUG: '0'
        SOKETI_DEFAULT_APP_ID: '${PUSHER_APP_ID}'
        SOKETI_DEFAULT_APP_KEY: '${PUSHER_APP_KEY}'
        SOKETI_DEFAULT_APP_SECRET: '${PUSHER_APP_SECRET}'
        SOKETI_PORT: '${PUSHER_PORT}'
    ports:
        - 6001:6001
    networks:
        - sail

If I change the default port to another value (8081:8081 for example), it works.

But if I expose the port 8081 to the port 80 8081:80, given that another service is already exposed to port 80, I can't connect to the websocket anymore (handshake error).

If I set 80:80, I have an error saying that the port is already in use.

Can you help me please ?

Thanks a lot.

V

0 likes
8 replies
LaryAI's avatar
Level 58

Running two different services on the same port is generally not possible because a port can only be bound to one service at a time. However, there are a few strategies you can use to achieve similar functionality:

  1. Reverse Proxy: Use a reverse proxy like Nginx or Traefik to route traffic to different services based on the request path or subdomain. This way, you can have both services listening on different ports internally, but externally they appear to be on the same port.

  2. Multiplexing: Use a multiplexer that can inspect the incoming traffic and route it to the appropriate service based on the protocol or other criteria. This is more complex and less common.

Here's an example of how you can use Nginx as a reverse proxy to achieve this:

Step 1: Configure Docker Compose

Update your docker-compose.yml to include Nginx as a reverse proxy:

version: '3.8'

services:
  soketi:
    image: 'quay.io/soketi/soketi:1.6.1-16-alpine'
    container_name: dev-soketi
    environment:
      SOKETI_DEBUG: '0'
      SOKETI_DEFAULT_APP_ID: '${PUSHER_APP_ID}'
      SOKETI_DEFAULT_APP_KEY: '${PUSHER_APP_KEY}'
      SOKETI_DEFAULT_APP_SECRET: '${PUSHER_APP_SECRET}'
      SOKETI_PORT: '6001'
    ports:
      - 6001:6001
    networks:
      - sail

  web:
    image: 'your-web-service-image'
    container_name: dev-web
    ports:
      - 8080:80
    networks:
      - sail

  nginx:
    image: nginx:latest
    container_name: dev-nginx
    ports:
      - 80:80
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - sail

networks:
  sail:
    driver: bridge

Step 2: Configure Nginx

Create an nginx.conf file in the same directory as your docker-compose.yml:

events {}

http {
    upstream soketi {
        server dev-soketi:6001;
    }

    upstream web {
        server dev-web:80;
    }

    server {
        listen 80;

        location /soketi/ {
            proxy_pass http://soketi;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
        }

        location / {
            proxy_pass http://web;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

Explanation

  • Nginx Configuration: The Nginx configuration defines two upstream services: soketi and web. It listens on port 80 and routes requests based on the path.

    • Requests to /soketi/ are proxied to the Soketi service.
    • All other requests are proxied to the web service.
  • Docker Compose: The nginx service is added to the Docker Compose file, and it shares the same network (sail) with the other services. This allows Nginx to communicate with the other containers using their service names.

Running the Setup

  1. Ensure your nginx.conf file is in the same directory as your docker-compose.yml.
  2. Run docker-compose up -d to start the services.

With this setup, you can access your web service at http://localhost and your Soketi service at http://localhost/soketi/.

This way, you effectively have two services running on the same external port (80), but they are differentiated by the request path.

vincent15000's avatar

@martinbean I have more precisions about the demand : I have to use a reverse proxy on nginx to redirect some request to the websocket. This way all request (http and ws) are on port 80, but if the url is for example http://localhost/websocket, this will redirect to ws on port 6001.

Have you already done something like this ?

I don't understand how to do that ...

https://nginx.org/en/docs/http/websocket.html

geraintp's avatar
geraintp
Best Answer
Level 18

Martin is correct, docker can only bind one service to a given port, and nothing else can be bound to that port outside of docker eg.. valet, or herd cant be using port 80 either..

What you want do do can be done but the Nginx proxy has to be bound on that port. Which is exactly what the AI bot has suggested above..

nginx is on port 80, and receive all the traffic to that port and then forwards it to the other services acting as a router, technically the other services don't have to have any ports bound to them nginx will be able talk to them over the sail docker network.

They only need port binding if you want to access them directly from the host computer without going through the nginx proxy..

2 likes
vincent15000's avatar

@geraintp

I need to access to the websocket with ws://192.168.10.254:80.

I don't want any subpath like ws://192.168.10.254:80/websocket.

I have tried this configuration suggested by chatgpt (quite the same as the one suggestion by the AI here.

server {
    location / {
        root /var/www/html;
        index index.html index.htm;

        if ($http_upgrade = "websocket") {
            proxy_pass http://localhost:6001;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            break;
        }
    }
}

But I get an error message : proxy_http_version is not allowed here, and the same error message for proxy_set_header. Because with nginx these directives are not allowed inside a condition.

vincent15000's avatar

@geraintp And I have also tried this.

But I get another error message : 502 Bad Gateway.

upstream web {
    server proxy-nginx:80;
}

upstream websocket {
    server proxy-soketi:6001;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://web;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /websocket/ {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

But in this case I get an error message 400 (request or cookie too large) and I have a subpath (websocket) that I don't want.

vincent15000's avatar

@geraintp And here is my docker-compose.yml file.

services:
  nginx:
    build:
      context: .
      dockerfile: nginx.dockerfile
    container_name: proxy-nginx
    ports:
      - 80:80
    volumes:
      - ./src/dist:/var/www/html
      - ./data:/var/www/data
  soketi:
    image: 'quay.io/soketi/soketi:1.6.1-16-alpine'
    container_name: proxy-soketi
    environment:
      SOKETI_DEBUG: '1'
    ports:
      - 6001:6001
  npm:
    image: node:20-alpine
    container_name: proxy-npm
    volumes:
      - ./src:/var/www/src
    entrypoint: ["npm"]
    working_dir: /var/www/src
vincent15000's avatar

@geraintp @martinbean Given that pusher-js adds automatically /app/{app-key} in the URL, I just had to configure nginx accordingly.

location /app/ {
    proxy_pass http://websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

And be sure that I don't use app in any other route.

Please or to participate in this conversation.