YuukanOO / seelf

Lightweight self-hosted deployment platform written in Go
https://yuukanoo.github.io/seelf/
GNU General Public License v3.0
212 stars 7 forks source link

Issue with multiple ports #71

Closed sardaukar closed 5 months ago

sardaukar commented 5 months ago

I skipped v2.2 (was waiting on private registries) and my go-to example app to test multiple ports is Forgejo, the Gitea fork I use. It has an HTTP and a TCP port for the built-in SSH server for git cloning.

Here is the compose.yaml I use with my current Docker UI:

services:

  app:
    image: codeberg.org/forgejo/forgejo:7.0.3
    environment:
      - USER_UID=1026
      - USER_GID=100
      - FORGEJO__database__DB_TYPE=postgres
      - FORGEJO__database__HOST=db
      - FORGEJO__database__NAME=forgejo
      - FORGEJO__database__USER=forgejo
      - FORGEJO__database__PASSWD=forgejo
    networks:
      - dockge_default
    volumes:
      - /volume1/docker/compose/data/forgejo/data:/data
    ports:
      - 10022:10022
    depends_on:
      db:
        condition: service_healthy
    labels:
      traefik.enable: "true"
      traefik.http.routers.forgejo.rule: "Host(`forgejo.my.redacted.domain`)"
      traefik.http.routers.forgejo.service: "forgejo"
      traefik.http.routers.forgejo.entrypoints: "https"
      traefik.http.routers.forgejo.tls.certresolver: "gandi"
      traefik.http.routers.forgejo.tls.domains[0].main: "my.redacted.domain"
      traefik.http.routers.forgejo.tls.domains[0].sans: "*.my.redacted.domain"
      traefik.http.services.forgejo.loadbalancer.server.port: "3000"

  db:
    image: postgres:14.5
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=forgejo
      - POSTGRES_DB=forgejo
    networks:
      - dockge_default
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h localhost -U forgejo -d forgejo']
      interval: 5s
      timeout: 5s
      retries: 10
    volumes:
      - /volume1/docker/compose/data/forgejo/postgres:/var/lib/postgresql/data

networks:
  dockge_default:
    external: true

x-dockge:
  urls:
    - https://forgejo.my.redacted.domain

I only specify the SSH port I use (10022, to avoid taking the default 22) and the 3000 port for the app is part of the Traefik labels I add.

I tried the following compose with Seelf:

services:

  app:
    image: codeberg.org/forgejo/forgejo:7.0.3
    environment:
      - FORGEJO__database__DB_TYPE=postgres
      - FORGEJO__database__HOST=db
      - FORGEJO__database__NAME=forgejo
      - FORGEJO__database__USER=forgejo
      - FORGEJO__database__PASSWD=forgejo
    volumes:
      - forgejo-data:/data
    ports:
      - 3000:3000
      - 10022:10022/tcp
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:14.5
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=forgejo
      - POSTGRES_DB=forgejo
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h localhost -U forgejo -d forgejo']
      interval: 5s
      timeout: 5s
      retries: 10
    volumes:
      - forgejo-postgres:/var/lib/postgresql/data

volumes:
  forgejo-data:
  forgejo-postgres:

Then I go to the install, make sure the HTTP port is 3000 and SSH is 10022, and install. Then create a new user (becomes the admin), add my SSH key to the settings and create a repo. Cloning it via HTTP works, but via SSH it just hangs, presumably because the TCP port has a mismatch. And sure enough, the app info on Seelf's UI shows that port 10022 is... wrong?

annotely_image

Not sure why I'm getting port 32773 instead of the requested 10022. The docs don't explain this, I think?

Thanks for any pointers!

YuukanOO commented 5 months ago

The behavior is expected but you're right the documentation is lacking this information (I thought I did it but this information is only in https://github.com/YuukanOO/seelf/pull/65#issue-2304648934) and I will add it.

When you use custom entrypoints (multiple http ports on the same container or tcp / udp ports), seelf does not rely on the actual port defined since it can't assume it will be available on the target. What it does instead is trying to find an available port for the specified protocol by spawning a tiny container with ephemeral ports.

Then, those ports are assigned to your entrypoints and as long as you don't change them in your compose file (same app name, protocol and container port), the same port will be used by your next deployments. So in your example, the port 32773 has been assigned by seelf the first time your entrypoint has been seen but if you redeploy your stack, you will still have the 32773 forwarded to 10022.

sardaukar commented 5 months ago

OK, but 10022 was available on the server - is it absolutely random or does it try the requested one first? For Forgejo it's changeable, but for other projects it might be harder like Logitech Music System that requires port 9000

YuukanOO commented 5 months ago

It's random for now. One thing that I could add is an interface to update ports assigned by seelf on target entrypoints so that you can have full control on it if this is absolutely required.

YuukanOO commented 1 month ago

:tada: This issue has been resolved in version 2.3.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket: