SensorsIot / IOTstack

Docker stack for getting started on IOT on the Raspberry PI
GNU General Public License v3.0
1.46k stars 307 forks source link

looking to dumb down IOTstack (for traefik) #782

Open NossieUK opened 2 days ago

NossieUK commented 2 days ago

I know traefik is a .... nuanced subject here but I have a problem.

I like the IOTstack interface just for basic commands... but my compose file has ran away with itself and runing 61 containers, my compose file is just over 1000 lines long.

I currently have traefik dashboard running on dashboard.4development.com - that's because I've hard coded it to work

I'm trying to dynamically use a wildcard on the other exposed containers so that when I create dashy, expose it in pihole it's automagically accessible via dashy.4development.com

`# Traefik Dynamic Configuration

http: routers:

Traefik Dashboard (Explicitly defined subdomain)

dashboard:
  entryPoints:
    - websecure
  rule: "Host(`dashboard.4development.com`)"
  service: "api@internal"
  tls:
    certResolver: cloudflare  # Use Cloudflare for TLS

# Redirect HTTP to HTTPS
redirect-to-https:
  entryPoints:
    - web
  middlewares:
    - redirect-to-https
  rule: "HostRegexp(`{any:.+}`)"
  service: noop  # Noop service to handle redirect

# Internal routing (for internal use, such as Traefik's own management)
internal-default:
  entryPoints:
    - internal
  rule: "HostRegexp(`{any:.+}`)"
  middlewares:
    - internal-whitelist
  service: noop  # Noop service for internal routes

services:

Placeholder service for redirects and internal routes

noop:
  loadBalancer:
    servers:
      - url: "http://127.0.0.1"  # Localhost, no actual traffic

# Define your actual services (Example: `web-service`)
web-service:
  loadBalancer:
    servers:
      - url: "http://web-container:8080"  # Replace with your container's URL and port

middlewares:

Middleware to redirect HTTP to HTTPS

redirect-to-https:
  redirectScheme:
    scheme: https

# Middleware to whitelist internal IPs
internal-whitelist:
  ipWhiteList:
    sourceRange:
      - "192.168.0.0/24"  # Replace with your internal subnet
      - "127.0.0.1/32"    # Allow localhost

`

The problem I have - regardless of what I do - with the dynamic / wildcard approach - it works BUT defaults to for example

https://dashy-iotstack.4development.com

It seems to be taking the iotstack part from the docker stack config/program

Is there any option in docker stack to turn this part off?

Paraphraser commented 2 days ago

I wish there was an emoticon for Seriously Dumb Look (😵‍💫+🫥+🤢) because that's what I'm feeling at the moment. I didn't understand a single word of that. One of us deserves a prize, either you for Impenetrable Question of 2024, or me for Universal Dunce of the Decade. Probably me.

you definitely deserve an award for compose file length. Mine weighs in at a mere 275 lines. Gold star for a subtle use of "nuanced" too. I like it!

docker-compose (as distinct from either Docker or IOTstack) defines the all-lower-case representation of the name of the folder containing the compose file as the "project" name. Any time you see iotstack- it's the project name. I've seen it in the context of local image names (eg when a service definition includes a build step), network names like iotstack-default, and some "volume mounts" so this sounds like another situation where the designers of docker compose asked "what happens if there is more than one stack running on a machine - how do we disambiguate?" However, I don't think I've ever seen the project used as a suffix. All the examples that come to mind use it as a prefix. So that's atypical, at least in my experience.

On the other hand, if you're about to raise your hand in objection and tell me that "dashy" isn't in a compose file contained in a folder named "IOTstack" then ... dunno.

One of the things that is not at all clear in your question is how much (if any) of that YAML is in your compose file and how much is in some other config file for traefik. If that's all compose YAML then I think more context could be helpful. Plus, did you mean to include "active" URLs? If those are intended to be public and active so that some part of the question could be understood by visiting a test site you've put up, I can't get anywhere.

Sorry I can't be of any actual help. Hopefully people with traefik experience will chime in.

NossieUK commented 1 day ago

Hi Phil,

Apologies again for the confusion, and thanks for your patience with me.

My Setup and Goal: I use IOTstack primarily for its interface and tools, but I’m starting to scale my setup. Most of my containers are internal-only, but I want certain containers to be accessible via Traefik as subdomains. Specifically, I want them to resolve as:

dashy.4development.com portainer.4development.com paperlessng.4development.com CMXweather.4development.com I have Pi-hole managing the DNS, so if a subdomain for a container doesn’t exist, it shouldn’t be exposed to the outside network.

The Issue: When using Docker Stack (and IOTstack), every container gets a subdomain like:

dashy-iotstack.4development.com portainer-iotstack.4development.com paperlessng-iotstack.4development.com CMXweather-iotstack.4development.com The problem is that the iotstack project name is being appended to the container name, which isn’t what I want.

What I’m Trying to Solve: I need to find a way to prevent Docker Stack from appending the project name (iotstack) to the subdomain.

I’m hoping there’s a way to specify this within the Docker Stack configuration or docker-compose.yml itself (without changing Traefik or the container labels).

What I’ve Tried: I’ve tried setting up Traefik labels and adjusting configurations, but the iotstack suffix still gets appended automatically to the subdomain.

Request: Is there a way within Docker Stack or the docker-compose.yml file to control the subdomain name and prevent the -iotstack suffix from being added?

I’d love to get the containers to show up exactly as portainer.4development.com instead of portainer-iotstack.4development.com.

I appreciate any help you can offer, Phil. Looking forward to your suggestions!

Best,

Paraphraser commented 1 day ago

I'm still struggling to form a mental map. Is traefik running as part of the same stack as the other containers? You say PiHole is configured with non-project names so I presume this is a set of domain names pointing to the same IP address where traefik is running, with the expectation that traefik will take the string before the first dot and figure out which container that is. Yes/no?

So when you then say you're seeing with-project-name forms, where are you seeing those? PiHole? Somewhere else? What I'm getting at is DNS is usually static string to static IP. Nothing dynamic. There are, however, ways (that I've never bothered with) of going from the host name supplied by a client in a DHCP request and turning that into a domain name which is bonded with the allocated IP address (whether that's fixed or dynamic) and handed to the DNS so it can then resolve the name. This question is aimed at supporting or refuting that kind of dynamic DNS as one possible hypothesis.

I have to admit that I may well have a mental block when it comes to traefik. I did muck about with it for a week or so at one point but it drove me nuts. To begin with, the so-called "documentation" seemed very sparse. It kept sending me in circular loops with those zany "bee-like oddity in the middle" diagrams. I don't think I got a single useful tip from the "official" docs - it all came from other searches. Then, getting anything to "react" - as distinct from something actually working - seemed to need the addition of numerous labels with syntactic requirements that made little-to-no sense. In the end I decided that plain old-fashioned bookmarks were (a) one heck of a lot simpler and (b) infinitely more reliable. I junked the lot and moved on.

I've just been back to the docs and that "bee" brought back all the frustration. I didn't fare any better getting useful facts this time either. Bah!

IMG_2876

Study that screen shot for a moment. I've pre-edited Grafana's service definition in the compose file but have not yet done an "up". I then ask the container for its fully-qualified domain name and it returns a randomly-allocated ID. Then the grep on fred shows two lines which have already been added to Grafana's service definition. I up Grafana to activate those lines then repeat the "what is your FQDN" question. You'll see the difference.

Now, if you were to open a shell into another container (eg NodeRed) you could ping Fred and it would find the Grafana container. ping fred.freddy.com doesn't work but that's likely because of the ndots setting in /etc/resolv.conf - and a good way of making a right mess of container DNS is to interfere with that option.

But - either/both of those extra directives in the service deginion might have some impact on what traefik sees...

Paraphraser commented 1 day ago

I could add that the main reason I've never bothered with "dynamic DNS" (in the DHCP sense, rather than the DynDNS, NoIP or DuckDNS sense) is that it's just a very hard way to implement what multicast DNS does already.

Paraphraser commented 1 day ago

IMG_2877

Notice the reverse name in that. The ping has been to fred and the NodeRed container DNS has been able to figure out that that maps to the Grafana container, but the inverse DNS lookup (ie from container IP address to name, aka the DNS PTR record) has taken the container name (not its host name) and tacked on the network name, which is a concatenation of "default" and the project name. Still not at -iotstack.

In other news, I did some nosing around with the JSON output from probing the docker socket to see if I could spot any signs of that suffix. Nada. I'm beginning to think that the lack of evidence on the Docker side of things suggests this is more likely to be something coming from traefik itself.

What I mean is that, as mentioned before, I know of several examples where the project name is used as a prefix. If I was inventing something like a traefik that needed to have knowledge of other containers running in an environment where multiple stacks were a possibility, and I knew Docker already used the project name to avoid name-space collisions (from which I could infer that a project name was sufficient for that purpose), and I knew that Docker typically used the project name as a prefix, then I might well adopt the project name as a suffix to avoid collisions with anything Docker was doing. All pure speculation...