diff --git a/README.md b/README.md index 6c862cc47..1898fe7e7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ This mod gives SWAG the ability to start containers on-demand when accessed thro access_log /config/log/nginx/access.log main; ``` - *Optional* - Additional environment variables - - `SWAG_ONDEMAND_STOP_THRESHOLD` - duration of inactivity in seconds before stopping on-demand containers, defaults to `600` (10 minutes). + - `SWAG_ONDEMAND_STOP_THRESHOLD` - duration of inactivity in seconds before stopping on-demand containers, defaults to `600` (10 minutes). Can be overridden per container with the `swag_ondemand_stop_threshold` label. - `SWAG_ONDEMAND_CONTAINER_QUERY_SLEEP` - sleep time in seconds between querying containers, defaults to `5.0`. - `SWAG_ONDEMAND_LOG_READER_SLEEP` - sleep time in seconds between log reads, defaults to `1.0`. - `SWAG_ONDEMAND_DOCKER_API_TIMEOUT` - the timeout for docker's API. Defaults to `5`. @@ -81,12 +81,14 @@ Or set the following label if using `swag-auto-proxy`: - `swag_ondemand=enable` - required for on-demand. - `swag_ondemand_urls=https://wake.domain.com,https://app.domain.com/up` - *optional* - overrides the monitored URLs for starting the container on-demand. Defaults to using the value of the `swag_url` label, if you've already set it for `swag-auto-proxy`, or `https://somecontainer.,http://somecontainer.` otherwise. - `swag_ondemand_websocket=1` - required for apps that communicate over a websocket, such as selkies based apps. +- `swag_ondemand_stop_threshold=300` - *optional* - overrides `SWAG_ONDEMAND_STOP_THRESHOLD` for this container. Must be a positive whole number of seconds, otherwise `SWAG_ONDEMAND_STOP_THRESHOLD` is used. ### URLs: - Accessed URLs need to start with one of `swag_ondemand_urls` to be matched, for example, setting `swag_ondemand_urls=https://plex.` will apply to `https://plex.domain.com` and `https://plex.domain.com/something`. - `swag_ondemand_urls` default to `https://somecontainer.,http://somecontainer.`, for example `https://plex.,http://plex.`. - `swag_ondemand_urls` don't need to be valid, it will work as long as it reaches swag and gets logged by nginx under `/config/log/nginx/access.log`. - The same URL can be set on multiple containers and all of them will be started when accessing that URL. +- Containers sharing a URL are stopped independently, each according to its own stop threshold. ### Logging: The log file can be found under `/config/log/ondemand/ondemand.log`. diff --git a/root/app/ondemand/container_thread.py b/root/app/ondemand/container_thread.py index 0348b2f8a..e2c1a81c2 100644 --- a/root/app/ondemand/container_thread.py +++ b/root/app/ondemand/container_thread.py @@ -62,6 +62,12 @@ def process_containers(self): default_url = container.labels.get("swag_url", f"{container.name}.").rstrip("*") container_urls = container.labels.get("swag_ondemand_urls", f"https://{default_url},http://{default_url}") websocket = container.labels.get("swag_ondemand_websocket", "0").lower() in ("true", "1") + try: + stop_threshold = int(container.labels.get("swag_ondemand_stop_threshold", STOP_THRESHOLD)) + except ValueError: + stop_threshold = STOP_THRESHOLD + if stop_threshold <= 0: + stop_threshold = STOP_THRESHOLD if container.name in docker_host.ondemand_containers: docker_host.ondemand_containers[container.name].status = container.status @@ -69,14 +75,18 @@ def process_containers(self): if container_urls != docker_host.ondemand_containers[container.name].urls: docker_host.ondemand_containers[container.name].urls = container_urls logging.info(f"Updated urls for {container.name} on {docker_host.url} to: {container_urls}") + if stop_threshold != docker_host.ondemand_containers[container.name].stop_threshold: + docker_host.ondemand_containers[container.name].stop_threshold = stop_threshold + logging.info(f"Updated stop threshold for {container.name} on {docker_host.url} to: {stop_threshold}s") else: docker_host.ondemand_containers[container.name] = OnDemandContainer( status=container.status, urls=container_urls, last_accessed=datetime.now(), - websocket=websocket + websocket=websocket, + stop_threshold=stop_threshold ) - logging.info(f"Started monitoring {container.name} on {docker_host.url} for urls: {container_urls}") + logging.info(f"Started monitoring {container.name} on {docker_host.url} for urls: {container_urls}, stop threshold: {stop_threshold}s") def stop_containers(self, websocket_terminated_urls_combined: str): @@ -97,7 +107,7 @@ def stop_containers(self, websocket_terminated_urls_combined: str): continue inactive_seconds = (datetime.now() - ondemand_container.last_accessed).total_seconds() - if inactive_seconds < STOP_THRESHOLD: + if inactive_seconds < ondemand_container.stop_threshold: continue container = docker_host.get_container(container_name) @@ -106,7 +116,7 @@ def stop_containers(self, websocket_terminated_urls_combined: str): container.stop() ondemand_container.status = "exited" - logging.info(f"Stopped {container_name} on {docker_host.url} after {STOP_THRESHOLD}s of inactivity") + logging.info(f"Stopped {container_name} on {docker_host.url} after {ondemand_container.stop_threshold}s of inactivity") def start_containers(self, last_accessed_urls_combined: str): if not last_accessed_urls_combined: diff --git a/root/app/ondemand/data_classes.py b/root/app/ondemand/data_classes.py index 5a9af2255..73abdf403 100644 --- a/root/app/ondemand/data_classes.py +++ b/root/app/ondemand/data_classes.py @@ -11,6 +11,7 @@ class OnDemandContainer: urls: str last_accessed: datetime websocket: bool + stop_threshold: int terminated: bool = False @dataclass