[Support] [Beta] ContainerNursery


Recommended Posts

logo512.png

 

Overview:

Puts Docker Containers to sleep and wakes them back up when they're needed.

 

Written in Node.js, this application acts as a HTTP reverse proxy and stops Docker containers which haven't been accessed recently and starts them again when a new request comes in. ContainerNursery also makes sure there are no more active WebSocket connections before stopping the container.

To improve the user experience a loading page is presented, which automatically reloads when the containers webserver is ready.

 

GitHub: https://github.com/ItsEcholot/ContainerNursery

GitHub Packages: https://github.com/ItsEcholot/ContainerNursery/pkgs/container/containernursery

 

This application is currently in beta! Please report any problems / issues / suggestions in this thread or alternatively using GitHub Issues.

 

Quick Demo:

132314400-817971fd-b364-4c78-9fed-650138

 

Setup Guide:

There are multiple ways to setup and use ContainerNursery depending on your use case and network setup.
In this guide I want to give a quick overview which choices have to be made and to present a non exhaustive list of possible solutions for each choice.

More information can be found in the README.md file on the GitHub Repo.

 

DNS:

Since ContainerNursery is a reverse proxy it will use the host header of the request to decide where the request should be routed to. This means we have to reach CN using a domain name and can't simply use an IP + PORT combination. So you have to find a way to route multiple domain names to the same IP (probably the Unraid IP since CN is running as a Docker Container on that machine).

 

Hosts File:

Edit the local hosts file on your device. Your OS uses this file to resolve domain names to IPs. This file is located at /etc/hosts on Linux and MacOS and at C:\Windows\System32\drivers\etc on Windows.
Add an entry for each application you want to proxy through ContainerNursery.

Example: 

192.168.1.2       my-important-app.unraid
192.168.1.2       handbrake.apps.unraid
192.168.1.2       speedtest.apps.unraid

In this example 192.168.1.2 is your Unraid (and thus ContainerNursery) IP and the names are freely choosable domains.

 

DNS Server:

You can also use your local DNS server to define new domains and point them to your ContainerNursery IP. While more complicated this approach allows all devices which make use of your local DNS server (if you announce it using DHCP, probably all your network devices) to access your apps using the defined domains.

Your DNS server could be a PF/OPNSense box, your modem (if it allows adding manual DNS entries) or a dedicated DNS server application like PiHole for example.

Since all this sub-methods are configured differently, DuckDuckGo (other search engines are available) is probably the best way to figure this one out by yourself.

 

Ports:

By default ContainerNurser is setup, like most reverse proxies, to run on port 80 since this is the default port for HTTP requests. This way you don't have to append a port to the domain name when trying to access your applications. Since port 80 is also used by Unraid to serve it's Webinterface you basically have two options:

 

Change Unraids Webinterface port

This is the preferred method since it allows using all your other applications like you would expect them to, i.e without having to append a port to the domain name. This can be accomplished by navigating to the Settings > Management Access page and changing the HTTP port value to something other than 80. 8080 would be a great candidate, since it's easy to remember.

This means that from now on you would have to access your Unraid WebUI (only if you don't use https) using the following URL: http://<yourunraidip>:8080

This method also means you could deploy CN using host networking instead of bridge, however I don't recommend this, since the useful isolation layer between host and container is then not used.

 

Change ContainerNurserys port

This can be easily done by editing the CN container and making sure you're using bridge networking and maping the port from 80 to 8080 for example.

If you use this way the Unraid WebUI will still be available like usual, but all your services have to be accessed with this port appended, for example: http://hanbrake.apps.unraid:8080

 

Networking:

Since you want to use ContainerNursery to proxy your requests to your applications, CN will have to be able to access your other containers. The approach here depends on how your other apps and CNs network is configured.

 

Custom bridge network

This is the most elegant solution in my eyes. Custom docker bridge networks allow you to specify which containers should be able to access this network and communicate with each other (without having to map any ports) and most importantly allow you to use the name of the container as a hostname. Docker will then automatically resolve the correct container IP address for you. Using this approach dramatically reduces the attack surface, since less ports are open on the Unraid Host itself.

To use this approach open up the Unraid Console using SSH or the WebUI and run the following command, creating a custom bridge network with the name proxy:

docker network create proxy

Now edit all your applications, which you want to access through ContainerNursery and change the following option:

Network Type --> Custom: proxy

You can (and should) now remove all port mappings (hint: make a note of what port the app uses inside the container, since they're not always the same), since you will only be accessing the app through the domain (and CN as a reverse proxy) instead of the raw IP + port combination.

Make sure ContainerNursery itself is also switched to using your newly created docker bridge network but keep the port mapping (change it to your desired value if needed, see the part about ports above) since we need to be able to access ContainerNursery from other machines so that it can route our requests to the desired containers.

Now you can configure ContainerNursery like in this example:

proxyHosts:
  - domain: handbrake.apps.unraid
    containerName: handbrake
    proxyHost: handbrake
    proxyPort: 5800
    timeoutSeconds: 14400

Since we use a custom bridge network which translates the container name to the correct IP address we can use handbrake as our proxyHost value. The proxyPort value is the internal port (the port the actual application inside of the container listens on) of the target container since containers of the same bridge network can communicate freely with each other without any port mapping taking place.

 

Default bridge network

If you want to use the default bridge network docker provides you will have to map ports on both ContainerNursery and the container you want to access and then use a configuration like in this example:

proxyHosts:
  - domain: handbrake.apps.unraid
    containerName: handbrake
    proxyHost: 192.168.1.2
    proxyPort: 6800
    timeoutSeconds: 14400

192.168.1.2 is the IP of the Unraid machine and the port 6800 is the mapped port of the handbrake container.

 

Host network

The same rules as for the default bridge network hold true but now localhost can be used inside the config, since localhost now refers to the Unraid machine and not the CN docker container.

proxyHosts:
  - domain: handbrake.apps.unraid
    containerName: handbrake
    proxyHost: 127.0.0.1
    proxyPort: 6800
    timeoutSeconds: 14400

 

Edited by Echolot
Added setup guide
  • Like 1
Link to comment

Changelog

12.10.2021 - v1.5.1 Fixed a bug where the loading page wouldn't be displayed when a path other than `/` is requested. Thanks to @JamesDAdams on GitHub for the Bug report.

 

29.09.2021 - v1.5.0 Added the ability to stop (and start) multiple containers per proxy host. This is useful if the application supports multiple containers. The first container in the list is the main container, which is used to check if the container is ready and reload the loading page. For usage information check the README.md file on GitHub.

 

24.09.2021 - v1.4.2 Handle SIGTERM. The ContainerNursery container should now stop (and thus also restart) much quicker.

 

23.09.2021 - v1.4.1 Fixed an issue where certain editors broke the live config reload functionality by introducing a small delay before reading the config file.

 

23.09.2021 - v1.4.0 Added stopOnTimeoutIfCpuUsageBelow setting to proxyHosts which prevents ContainerNursery from stoping containers if they're still busy (using more CPU than the limit). For usage information check the README.md file on GitHub.

Edited by Echolot
Update v1.5.1
Link to comment
  • 2 weeks later...

Would love to see a guide to config this. Seems to need a reverse proxy also?

I'm not used to local domain names and not sure how to create them to work with my docker containers. I'm not sure if I need to install something different or use my pfSense system.

And does not the container 80 port interfere with the Unraid server 80 port?

But seems a great add to the repository, so thanks for your work!

Edited by guillelopez
Link to comment
11 hours ago, guillelopez said:

Would love to see a guide to config this. Seems to need a reverse proxy also?

I'm not used to local domain names and not sure how to create them to work with my docker containers. I'm not sure if I need to install something different or use my pfSense system.

And does not the container 80 port interfere with the Unraid server 80 port?

But seems a great add to the repository, so thanks for your work!

 

A guide is definitely something I thought about doing but haven't found the time yet to do, I will try to do it in the course of the next week. A pretty technical "guide" can already be found on the GitHub Project page in the Readme file.

 

If you're using Docker Bridge Network you can map the port 80 easily to something other you prefer. Either way we're working on making the listening port configurable.

  • Like 1
Link to comment

Good news then :)

I managed to configure it so ContainerNursery log said it can detect the other containers, and using the Bridge Network I maped the port to 86 and with the host-ip:86 but still didn't got it working properly, just was able to after 1800s the app turning off the other containers. I think I should try to learn today something about DNS resolvers and this kind of stuff. I access my containers with the ip:port, i'm a simple man 😅

 

I was following the GitHub Project guide, but get confused with the Domains and NginxProxyManager part, as I not used to it. But as I said, something new to learn.

 

Thanks!

Link to comment

Well I managed to get it nearly working. I created some host names on my desktop /etc/hosts file. "192.168.1.4 filebrowser.rack" and "192.168.1.4 krusader.rack"

I changed the network on your container to custom and used the 192.168.1.4 ip for it. (as I don't want to change Unraid 80 port and can't use ports on /etc/host file, this seemed for me the best solution)

and my config.yml is this:

 

proxyHosts:
  - domain: filebrowser.rack
    containerName: FileBrowser
    proxyHost: localhost
    proxyPort: 87
    timeoutSeconds: 1800
  - domain: krusader.rack
    containerName: Krusader
    proxyHost: localhost
    proxyPort: 6080
    timeoutSeconds: 1800

 

But I only get an infinite waking up FileBrowser or waking up Krusader.

On ContainerNursery logs I get Host not reachable.

Tried to change localhost for the unraid ip, and still no luck. Also tried internal containers ips (172.17.0.3 or 172.17.0.8) with their normal ports and also no luck.

Link to comment

@guillelopez So just to clarify, the ContainerNursery loading page gets displayed correctly when you visit filebrowser.rack but it just never displays the target application itself?

 

This would mean that either the proxyHost and/or proxyPort configuration is wrong for this proxy host, or that no connection can be established between these two applications (ContainerNursery and FileBrowser for example).

Using localhost as proxyHost is only correct if ContainerNursery is run in host networking mode, since otherwise localhost refers to the container and not the Unraid machine.

It could be that because of your special network situation the two containers can’t connect to each other, maybe try to investigate more into that direction?

 

You could try (not a permanent solution) to use the default bridge network for both Application and ContainerNursery and simply append the port when you open the url in the browser like so: http://filebrowser.rack:8080

Use the docker container settings to map the ContainerNursery port 80 to port 8080 for example. Then use the Unraid machine IP as proxyHost and the application port (which you have configured using the container settings, like for ContainerNursery) as the proxyPort.

Link to comment
18 hours ago, Echolot said:

@guillelopez So just to clarify, the ContainerNursery loading page gets displayed correctly when you visit filebrowser.rack but it just never displays the target application itself?

 

This would mean that either the proxyHost and/or proxyPort configuration is wrong for this proxy host, or that no connection can be established between these two applications (ContainerNursery and FileBrowser for example).

Using localhost as proxyHost is only correct if ContainerNursery is run in host networking mode, since otherwise localhost refers to the container and not the Unraid machine.

It could be that because of your special network situation the two containers can’t connect to each other, maybe try to investigate more into that direction?

 

You could try (not a permanent solution) to use the default bridge network for both Application and ContainerNursery and simply append the port when you open the url in the browser like so: http://filebrowser.rack:8080

Use the docker container settings to map the ContainerNursery port 80 to port 8080 for example. Then use the Unraid machine IP as proxyHost and the application port (which you have configured using the container settings, like for ContainerNursery) as the proxyPort.

 

That did the trick, I used Bridge Network on ContainerNursery and maped 80 to 8080, then used my Unraid ip as proxyHost. But I need to change also the domain on config.yml to use http://filebrowser.rack:8080, with just http://filebrowser.rack there, ContainerNursery told me on browser "Proxy configuration is missing for http://filebrowser.rack:8080"

 

So my config.yml looks like this:

proxyHosts:
  - domain: filebrowser.rack:8080
    containerName: FileBrowser
    proxyHost: 192.168.1.9
    proxyPort: 85
    timeoutSeconds: 1800
  - domain: krusader.rack:8080
    containerName: Krusader
    proxyHost: 192.168.1.9
    proxyPort: 6080
    timeoutSeconds: 1800

 

And ContainerNursery config:

2133962492_Capturadepantalla2021-09-20alas16_12_11.thumb.png.8dcb10b0b20a0234fbce25007ed028cc.png

 

Let me know, if you have time, to do more test with other configurations so we can find a perfect use to Unraid.

Thanks for your help and your really nice app.

Edited by guillelopez
  • Like 1
Link to comment
10 hours ago, guillelopez said:

 

That did the trick, I used Bridge Network on ContainerNursery and maped 80 to 8080, then used my Unraid ip as proxyHost. But I need to change also the domain on config.yml to use http://filebrowser.rack:8080, with just http://filebrowser.rack there, ContainerNursery told me on browser "Proxy configuration is missing for http://filebrowser.rack:8080"

 

So my config.yml looks like this:

proxyHosts:
  - domain: filebrowser.rack:8080
    containerName: FileBrowser
    proxyHost: 192.168.1.9
    proxyPort: 85
    timeoutSeconds: 1800
  - domain: krusader.rack:8080
    containerName: Krusader
    proxyHost: 192.168.1.9
    proxyPort: 6080
    timeoutSeconds: 1800

 

And ContainerNursery config:

2133962492_Capturadepantalla2021-09-20alas16_12_11.thumb.png.8dcb10b0b20a0234fbce25007ed028cc.png

 

Let me know, if you have time, to do more test with other configurations so we can find a perfect use to Unraid.

Thanks for your help and your really nice app.

thanks a lot for your tips. i use pihole, so i just add the host names under local dns.

  • Thanks 1
Link to comment

@guillelopez

Quote

That did the trick, I used Bridge Network on ContainerNursery and maped 80 to 8080, then used my Unraid ip as proxyHost. But I need to change also the domain on config.yml to use http://filebrowser.rack:8080, with just http://filebrowser.rack there, ContainerNursery told me on browser "Proxy configuration is missing for http://filebrowser.rack:8080"

This is actually a bug! Thanks for reporting this, will look into getting this fixed in the next few days. The port shouldn't be taken into consideration when examining the domain.

  • Thanks 1
Link to comment
  • Echolot changed the title to [Support] [Beta] ContainerNursery

@Echolot At least to add the port on the domain part in config.yml was an easy temporary walkaround.

 

@kjames2001 I'm glad I was helpful. I also use Pi-hole on a raspberry pi, and my router is a pfSense, but couldn't get working it with the Pi-hole local DNS or with the pfSense DNS Resolver. Probably something messy on my config, or I'm forgetting to do some steps.

But, for me, the most elegant solution seems to be the provided on the GitHub Project with NginxProxyManager, that let you specify the forward port. Need to learn how to properly implement it on my system.

Link to comment
21 minutes ago, Echolot said:

@guillelopez The fix to the bug you discovered, as well as the configurable listening port update was just released two hours ago.

 

I also added the guide I mentioned to the first post. Let me know if somethings missing.

 

I removed the domain port on the config file and updated, working perfect. Will make some test with the configurable port at night when I come back home.

Thanks a lot for your work.

 

EDIT: Forgot to say that the guide on first post is great even for noobs like me 😄

Edited by guillelopez
  • Thanks 1
Link to comment
17 hours ago, Echolot said:

@guillelopez The fix to the bug you discovered, as well as the configurable listening port update was just released two hours ago.

 

I also added the guide I mentioned to the first post. Let me know if somethings missing.

just checked out the update, fixed config file. everything works properly, except now the container wont auto update when there's a config change. it used to auto update config when any changes are made.

Edited by kjames2001
Link to comment
48 minutes ago, kjames2001 said:

just checked out the update, fixed config file. everything works properly, except now the container wont auto update when there's a config change. it used to auto update config when any changes are made.

I sadly can't recreate your issue, config reloading works just fine on my machines... Is there anymore detail you can provide?

Link to comment
5 hours ago, Echolot said:

I sadly can't recreate your issue, config reloading works just fine on my machines... Is there anymore detail you can provide?

This what @Kjames should be refering. This happens when I modify the config.yml on Sublime on my desktop Mac, and save it with the container running.

Need to restart the container to be able get the change working.

This also happened on Unraid with the previus package. If it helps in anyway I run 6.10.0-rc1 Unraid version.

693516256_Capturadepantalla2021-09-22alas15_41_58.thumb.png.f1210e2eb707f5bcfa6607cf5aefd7b8.png

 

I also run ContainerNursery on a Proxmox server where I have some containers, and there I don't have the same issue. But there I modify the config.yml on cli with nano.

 

PD: the configurable port works perfect, I changed to 90 on Unraid and use the default 80 on proxmox. Maybe I going to migrate all the config to proxmox as then I don't have to add the port on the local domains. But still I would be happy to still runing on Unraid to perfom test for you.

Edited by guillelopez
Link to comment

I just tried this using VSCode as the editor on Mac with the container running, can't reproduce this. Do you maybe use a different encoding than UTF-8? Does the same config file that produces this error work after a restart of the container?

Link to comment
1 hour ago, Echolot said:

I just tried this using VSCode as the editor on Mac with the container running, can't reproduce this. Do you maybe use a different encoding than UTF-8? Does the same config file that produces this error work after a restart of the container?

 

On Sublime I was using UTF-8, but yes after restart ContainerNursery, same config file works. It's just when saving it with the container running.

Tried to edit and save it from cli with nano on the Unraid system, and instead it works fine at how it should be, no need to restart the container.

So definetly something related with the text editor. Would like know what text editor does @kjames2001 use.

 

But for me this is not a big deal. Just restart the container or use nano on cli.

Link to comment
10 minutes ago, guillelopez said:

 

On Sublime I was using UTF-8, but yes after restart ContainerNursery, same config file works. It's just when saving it with the container running.

Tried to edit and save it from cli with nano on the Unraid system, and instead it works fine at how it should be, no need to restart the container.

So definetly something related with the text editor. Would like know what text editor does @kjames2001 use.

 

But for me this is not a big deal. Just restart the container or use nano on cli.

 

1 hour ago, Echolot said:

I just tried this using VSCode as the editor on Mac with the container running, can't reproduce this. Do you maybe use a different encoding than UTF-8? Does the same config file that produces this error work after a restart of the container?

 

7 hours ago, Echolot said:

I sadly can't recreate your issue, config reloading works just fine on my machines... Is there anymore detail you can provide?

I'm a noob, so i still use notepad. lol

 

Yeah, not a big deal, but it was super convenient. Because as long as the file is saved after any change, the container updates its config.

Link to comment

A small Update v1.4.0 was released, check the second post for the changelog.

 

@guillelopez & @kjames2001 Could you try the config reload issue again with the dev-config tag? ghcr.io/itsecholot/containernursery:dev-config

I added a small delay (500ms) after receiving a file change event before trying to read the config file. Maybe this fixes your issue? I sadly still couldn't reproduce this so it's impossible for me to test this on my own.

Link to comment
1 hour ago, Echolot said:

A small Update v1.4.0 was released, check the second post for the changelog.

 

@guillelopez & @kjames2001 Could you try the config reload issue again with the dev-config tag? ghcr.io/itsecholot/containernursery:dev-config

I added a small delay (500ms) after receiving a file change event before trying to read the config file. Maybe this fixes your issue? I sadly still couldn't reproduce this so it's impossible for me to test this on my own.

 

With dev-config tag I don't have the reload issue. Seems to work that 500ms delay.

Unfortunely for the new "stopOnTimeoutIfCpuUsageBelow" parameter, I don't have a use case yet to test it.

Link to comment
31 minutes ago, guillelopez said:

 

With dev-config tag I don't have the reload issue. Seems to work that 500ms delay.

Unfortunely for the new "stopOnTimeoutIfCpuUsageBelow" parameter, I don't have a use case yet to test it.

That is both good and disappointing to hear lol. Means we found a fix but also means that these editors first save an empty file and then save the correct edited file. The file changed event only gets emitted on the first save since there's an internal debounce logic in the library I use. I will push a small bug fix release in the next few minutes with this change.

Link to comment

@Echolot I didn't even thought about something like that hahaha. I thought that may be It were some kind of latency on my local lan that produced that kind of error, as modifying it on nano from ssh console, changes should be made locally.

 

I updated to 1.4.1 with latest tag and now can modify config without restart. 🤘

Edited by guillelopez
  • Like 1
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.