mirror of
https://github.com/kodxana/madiator-docker-runpod.git
synced 2024-11-22 02:40:12 +01:00
Merge pull request #7 from lutzapps/app-configs-and-gradio
app_configs bugfix online Url, app_utils gradio link support, port changes
This commit is contained in:
commit
0af6151735
9 changed files with 147 additions and 40 deletions
|
@ -74,10 +74,6 @@
|
|||
"containerPort": 6006, // Tensorboard (needed by kohya_ss)
|
||||
"hostPort": 6006
|
||||
},
|
||||
{
|
||||
"containerPort": 7860, // Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
"hostPort": 7860
|
||||
},
|
||||
{
|
||||
"containerPort": 7862, // Forge (aka Stable-Diffiusion-WebUI-Forge)
|
||||
"hostPort": 7862
|
||||
|
@ -85,6 +81,10 @@
|
|||
{
|
||||
"containerPort": 7863, // A1111 (aka Stable-Diffiusion-WebUI)
|
||||
"hostPort": 7863
|
||||
},
|
||||
{
|
||||
"containerPort": 7864, // Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
"hostPort": 7864
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -62,9 +62,9 @@ BASE_IMAGE=madiator2011/better-base:cuda12.4
|
|||
|
||||
- 3000/http (ComfyUI)
|
||||
- 6006/http (Tensorboard [needed by kohya_ss])
|
||||
- 7860/http (Kohya-ss) with FLUX.1 support
|
||||
- 7862/http (Forge) aka Stable-Diffiusion-WebUI-Forge
|
||||
- 7863/http (A1111) aka Stable-Diffiusion-WebUI
|
||||
- 7864/http (Kohya-ss) with FLUX.1 support
|
||||
|
||||
## ENV Vars (System)
|
||||
|
||||
|
|
|
@ -17,8 +17,10 @@ from utils.filebrowser_utils import configure_filebrowser, start_filebrowser, st
|
|||
from utils.app_utils import (
|
||||
run_app, update_process_status, check_app_directories, get_app_status,
|
||||
force_kill_process_by_name, update_webui_user_sh, save_install_status,
|
||||
get_install_status, download_and_unpack_venv, fix_custom_nodes, is_process_running, install_app #, update_model_symlinks
|
||||
get_install_status, download_and_unpack_venv, fix_custom_nodes, is_process_running, install_app, # update_model_symlinks
|
||||
get_bkohya_launch_url # lutzapps - support dynamic generated gradio url
|
||||
)
|
||||
|
||||
# lutzapps - CHANGE #1
|
||||
LOCAL_DEBUG = os.environ.get('LOCAL_DEBUG', 'False') # support local browsing for development/debugging
|
||||
|
||||
|
@ -67,7 +69,7 @@ running_processes = {}
|
|||
|
||||
app_configs = get_app_configs()
|
||||
|
||||
S3_BASE_URL = "https://better.s3.madiator.com/"
|
||||
#S3_BASE_URL = "https://better.s3.madiator.com/" # unused now
|
||||
|
||||
SETTINGS_FILE = '/workspace/.app_settings.json'
|
||||
|
||||
|
@ -187,6 +189,19 @@ def get_logs(app_name):
|
|||
return jsonify({'logs': running_processes[app_name]['log'][-100:]})
|
||||
return jsonify({'logs': []})
|
||||
|
||||
# lutzapps - support bkohya gradio url
|
||||
@app.route('/get_bkohya_launch_url', methods=['GET'])
|
||||
def get_bkohya_launch_url_route():
|
||||
command = app_configs['bkohya']['command']
|
||||
is_gradio = ("--share" in command.lower()) # gradio share mode
|
||||
if is_gradio:
|
||||
mode = 'gradio'
|
||||
else:
|
||||
mode = 'local'
|
||||
|
||||
launch_url = get_bkohya_launch_url() # get this from the app_utils global BKOHYA_GRADIO_URL, which is polled from the kohya log
|
||||
return jsonify({ 'mode': mode, 'url': launch_url }) # used from the index.html:OpenApp() button click function
|
||||
|
||||
@app.route('/kill_all', methods=['POST'])
|
||||
def kill_all():
|
||||
try:
|
||||
|
|
|
@ -2768,16 +2768,47 @@
|
|||
await updateStatus();
|
||||
}
|
||||
|
||||
function openApp(appKey, port) {
|
||||
// *** lutzapps - Change #3 - support to run locally
|
||||
async function openApp(appKey, port) {
|
||||
// *** lutzapps - support to run locally and new support for bkohya gradio url
|
||||
// NOTE: ` (back-ticks) are used here for template literals
|
||||
var url = `https://${podId}-${port}.proxy.runpod.net/`; // need to be declared as var
|
||||
if (`${enable_unsecure_localhost}` === 'True') {
|
||||
url = `http://localhost:${port}/`; // remove runpod.net proxy
|
||||
//alert(`openApp URL=${url}`);
|
||||
}
|
||||
|
||||
window.open(url, '_blank');
|
||||
// new: support gradio url for kohya_ss, e.g. https://b6365c256c395e755b.gradio.live
|
||||
//if (`${appKey}` === 'bkohya' && `${app_status[appKey]['status']}` === 'running') { // get the latest data from the server
|
||||
if (appKey == 'bkohya') { // get the latest data from the server
|
||||
var response = await fetch('/get_bkohya_launch_url');
|
||||
var result = await response.json();
|
||||
|
||||
var launch_mode = result['mode']; // 'gradio' or 'local'
|
||||
//alert('launch_mode=' + launch_mode);
|
||||
|
||||
var launch_url = result['url'];
|
||||
//alert('launch_url=' + launch_url);
|
||||
|
||||
if (launch_url !== '') { // when a launch url is defined, the app is initialized and ready to be opened
|
||||
if (launch_mode === 'gradio') { // if it is a gradio url
|
||||
url = launch_url; // then use it, instead of the above defined CF proxy url
|
||||
//alert('using gradio for bkohya: ' + launch_url);
|
||||
}
|
||||
// else use the CF proxy url defined above for localhost, instead of the localhost url from the log
|
||||
}
|
||||
else { // empty launch_url, waiting for launch url from log
|
||||
if (launch_mode === 'gradio') {
|
||||
alert('Waiting for Gradio URL to be generated ...');
|
||||
}
|
||||
else {
|
||||
alert('Waiting for lokal Launch URL to be generated ...');
|
||||
}
|
||||
return; // no lauch Url yet
|
||||
}
|
||||
}
|
||||
|
||||
//alert(`openApp URL=${url}`);
|
||||
|
||||
window.open(url, '_blank'); // open app window as popup window
|
||||
}
|
||||
|
||||
async function updateStatus() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
import requests
|
||||
import urllib.request
|
||||
import json
|
||||
|
||||
# this is the replacement for the XML manifest, and defines all app_configs in full detail
|
||||
|
@ -141,7 +142,13 @@ app_configs = {
|
|||
'bkohya': {
|
||||
'id': 'bkohya', # app_name
|
||||
'name': 'Better Kohya',
|
||||
'command': 'cd /workspace/bkohya && . ./bin/activate && cd /workspace/kohya_ss && python ./kohya_gui.py --headless --share --server_port 7860', # TODO!! check ./kohya_gui.py
|
||||
'command': 'cd /workspace/bkohya && . ./bin/activate && cd /workspace/kohya_ss && python ./kohya_gui.py --headless --share --server_port 7864', # TODO!! check other ""./kohya_gui.py" cmdlines options
|
||||
# need to check:
|
||||
# python ./kohya_gui.py --inbrowser --server_port 7864
|
||||
# works for now:
|
||||
# python ./kohya_gui.py --headless --share --server_port 7864
|
||||
# creates a gradio link for 72h like e.g. https://b6365c256c395e755b.gradio.live
|
||||
#
|
||||
### for Gradio supported reverse proxy:
|
||||
# --share -> Share the gradio UI
|
||||
# --root_path ROOT_PATH -> root_path` for Gradio to enable reverse proxy support. e.g. /kohya_ss
|
||||
|
@ -182,8 +189,8 @@ app_configs = {
|
|||
|
||||
'venv_path': '/workspace/bkohya',
|
||||
'app_path': '/workspace/kohya_ss',
|
||||
'port': 7860,
|
||||
'download_url': 'https://better.s3.madiator.com/kohya.tar.gz', # (2024-11-08 13:13:00Z) - lutzapps
|
||||
'port': 7864,
|
||||
'download_url': 'https://better.s3.madiator.com/bkohya/kohya.tar.gz', # (2024-11-08 13:13:00Z) - lutzapps
|
||||
'venv_uncompressed_size': 12128345264, # uncompressed size of the tar-file (in bytes)
|
||||
'archive_size': 6314758227, # tar filesize (in bytes)
|
||||
'sha256_hash': '9a0c0ed5925109e82973d55e28f4914fff6728cfb7f7f028a62e2ec1a9e4f60a',
|
||||
|
@ -276,12 +283,12 @@ def write_dict_to_jsonfile(dict:dict, json_filepath:str, overwrite:bool=False) -
|
|||
|
||||
return False, error_msg # failure
|
||||
|
||||
# Write the JSON data to a file
|
||||
# Write the JSON data to a file BUGBUG
|
||||
with open(json_filepath, 'w', encoding='utf-8') as output_file:
|
||||
json.dump(dict, output_file, ensure_ascii=False, indent=4, separators=(',', ': '))
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"ERROR in shared_models:write_dict_to_jsonfile() - loading JSON Map File '{json_filepath}'\nException: {str(e)}"
|
||||
error_msg = f"ERROR in write_dict_to_jsonfile() - loading JSON Map File '{json_filepath}'\nException: {str(e)}"
|
||||
print(error_msg)
|
||||
|
||||
return False, error_msg # failure
|
||||
|
@ -293,17 +300,20 @@ def read_dict_from_jsonfile(json_filepath:str) -> tuple [dict, str]:
|
|||
# Read JSON file from 'json_filepath' and return it as 'dict'
|
||||
|
||||
try:
|
||||
if os.path.exists(json_filepath):
|
||||
if ":" in json_filepath: # filepath is online Url containing ":" like http:/https:/ftp:
|
||||
with urllib.request.urlopen(json_filepath) as url:
|
||||
dict = json.load(url)
|
||||
elif os.path.exists(json_filepath): # local file path, e.g. "/workspace/...""
|
||||
with open(json_filepath, 'r') as input_file:
|
||||
dict = json.load(input_file)
|
||||
else:
|
||||
error_msg = f"dictionary file '{json_filepath}' does not exist"
|
||||
#print(error_msg)
|
||||
error_msg = f"local dictionary file '{json_filepath}' does not exist"
|
||||
print(error_msg)
|
||||
|
||||
return {}, error_msg # failure
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"ERROR in shared_models:read_dict_from_jsonfile() - loading JSON Map File '{json_filepath}'\nException: {str(e)}"
|
||||
error_msg = f"ERROR in read_dict_from_jsonfile() - loading JSON Map File '{json_filepath}'\nException: {str(e)}"
|
||||
print(error_msg)
|
||||
|
||||
return {}, error_msg # failure
|
||||
|
@ -317,30 +327,39 @@ def pretty_dict(dict:dict) -> str:
|
|||
return dict_string
|
||||
|
||||
# helper function for "init_app_install_dirs(), "init_shared_model_app_map()", "init_shared_models_folders()" and "inir_DEBUG_SETTINGS()"
|
||||
def load_global_dict_from_file(dict:dict, dict_filepath:str, dict_description:str, SHARED_MODELS_DIR:str="", write_file:bool=True) -> tuple[bool, dict]:
|
||||
def load_global_dict_from_file(default_dict:dict, dict_filepath:str, dict_description:str, SHARED_MODELS_DIR:str="", write_file:bool=True) -> tuple[bool, dict]:
|
||||
# returns the 'dict' for 'dict_description' from 'dict_filepath'
|
||||
|
||||
success = False
|
||||
return_dict = {}
|
||||
|
||||
try:
|
||||
if not SHARED_MODELS_DIR == "" and not os.path.exists(SHARED_MODELS_DIR):
|
||||
print(f"\nThe SHARED_MODELS_DIR '{SHARED_MODELS_DIR}' is not found!\nCreate it by clicking the 'Create Shared Folders' button from the WebUI 'Settings' Tab\n")
|
||||
|
||||
return
|
||||
return False, return_dict
|
||||
|
||||
if os.path.isfile(dict_filepath) and os.path.exists(dict_filepath):
|
||||
# read from file, if filepath is online url (http:/https:/ftp:) or local filepath exists
|
||||
if ":" in dict_filepath or \
|
||||
os.path.isfile(dict_filepath) and os.path.exists(dict_filepath):
|
||||
dict_filepath_found = True
|
||||
# read the dict_description from JSON file
|
||||
print(f"\nExisting '{dict_description}' found and read from file '{dict_filepath}'\nThe file overwrites the code defaults!")
|
||||
print(f"\nExisting '{dict_description}' found online and read from file '{dict_filepath}'\nThe file overwrites the code defaults!")
|
||||
|
||||
dict, error_msg = read_dict_from_jsonfile(dict_filepath)
|
||||
if not error_msg == "":
|
||||
print(error_msg)
|
||||
return_dict, error_msg = read_dict_from_jsonfile(dict_filepath)
|
||||
|
||||
success = (not return_dict == {} and error_msg == "") # translate to success state
|
||||
|
||||
if not success: # return_dict == {}
|
||||
dict_filepath_found = False # handle 404 errors from online urls
|
||||
return_dict = default_dict # use the code-defaults dict passed in
|
||||
|
||||
else: # init the dict_description from app code
|
||||
dict_filepath_found = False
|
||||
print(f"No {dict_description}_FILE found, initializing default '{dict_description}' from code ...")
|
||||
# use already defined dict from app code
|
||||
# write the dict to JSON file
|
||||
success, ErrorMsg = write_dict_to_jsonfile(dict, dict_filepath)
|
||||
success, ErrorMsg = write_dict_to_jsonfile(default_dict, dict_filepath)
|
||||
|
||||
if success:
|
||||
print(f"'{dict_description}' is initialized and written to file '{dict_filepath}'")
|
||||
|
@ -348,14 +367,15 @@ def load_global_dict_from_file(dict:dict, dict_filepath:str, dict_description:st
|
|||
print(ErrorMsg)
|
||||
|
||||
# Convert 'dict_description' dictionary to formatted JSON
|
||||
print(f"\nUsing {'external' if dict_filepath_found else 'default'} '{dict_description}':\n{pretty_dict(dict)}")
|
||||
print(f"\nUsing {'external' if dict_filepath_found else 'default'} '{dict_description}':\n{pretty_dict(return_dict)}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR in shared_models:load_global_dict_from_file() - initializing dict Map File '{dict_filepath}'\nException: {str(e)}")
|
||||
print(f"ERROR in load_global_dict_from_file() - initializing dict file '{dict_filepath}'\nException: {str(e)}")
|
||||
|
||||
return False, {}
|
||||
|
||||
return True, dict # success
|
||||
return success, return_dict
|
||||
|
||||
|
||||
DEBUG_SETTINGS_FILE = "/workspace/_debug_settings.json"
|
||||
DEBUG_SETTINGS = {
|
||||
|
@ -380,9 +400,9 @@ def init_debug_settings():
|
|||
|
||||
local_debug = os.environ.get('LOCAL_DEBUG', 'False') # support local browsing for development/debugging
|
||||
generate_debug_settings_file = os.environ.get('DEBUG_SETTINGS_FILE', 'False') # generate the DEBUG_SETTINGS_FILE, if not exist already
|
||||
write_file_if_not_exist = local_debug == 'True' or generate_debug_settings_file == 'True'
|
||||
write_file_if_not_exists = (local_debug == 'True' or local_debug == 'true' or generate_debug_settings_file == 'True' or generate_debug_settings_file == 'true')
|
||||
|
||||
success, dict = load_global_dict_from_file(DEBUG_SETTINGS, DEBUG_SETTINGS_FILE, "DEBUG_SETTINGS", write_file=write_file_if_not_exist)
|
||||
success, dict = load_global_dict_from_file(DEBUG_SETTINGS, DEBUG_SETTINGS_FILE, "DEBUG_SETTINGS", write_file=write_file_if_not_exists)
|
||||
if success:
|
||||
DEBUG_SETTINGS = dict
|
||||
|
||||
|
@ -426,21 +446,28 @@ APP_CONFIGS_FILE = APP_CONFIGS_MANIFEST_URL # default is the online manifest url
|
|||
# when the IMAGE is used normally.
|
||||
|
||||
def init_app_configs():
|
||||
global APP_CONFIGS_MANIFEST_URL
|
||||
global APP_CONFIGS_FILE
|
||||
global app_configs
|
||||
|
||||
# check for overwrite of APP_CONFIGS_MANIFEST_URL
|
||||
if not DEBUG_SETTINGS['APP_CONFIGS_MANIFEST_URL'] == "":
|
||||
APP_CONFIGS_FILE = DEBUG_SETTINGS['APP_CONFIGS_MANIFEST_URL']
|
||||
debug_app_configs_manifest_url = DEBUG_SETTINGS['APP_CONFIGS_MANIFEST_URL']
|
||||
if not debug_app_configs_manifest_url == "":
|
||||
print(f"using APP_CONFIGS_MANIFEST_URL from DEBUG_SETTINGS: {debug_app_configs_manifest_url}")
|
||||
APP_CONFIGS_MANIFEST_URL = debug_app_configs_manifest_url
|
||||
APP_CONFIGS_FILE = APP_CONFIGS_MANIFEST_URL
|
||||
|
||||
|
||||
print(f"\nUsing APP_CONFIGS_MANIFEST_URL={APP_CONFIGS_MANIFEST_URL}")
|
||||
|
||||
local_debug = os.environ.get('LOCAL_DEBUG', 'False') # support local browsing for development/debugging
|
||||
generate_app_configs_file = os.environ.get('APP_CONFIGS_FILE', 'False') # generate the APP_CONFIGS_FILE, if not exist already
|
||||
write_file_if_not_exists = local_debug == 'True' or generate_app_configs_file == 'True'
|
||||
write_file_if_not_exists = (local_debug == 'True' or local_debug == 'true' or generate_app_configs_file == 'True' or generate_app_configs_file == 'true')
|
||||
|
||||
success, dict = load_global_dict_from_file(app_configs, APP_CONFIGS_FILE, "APP_CONFIGS", write_file=write_file_if_not_exists)
|
||||
|
||||
if success:
|
||||
app_configs = dict # overwrite code-defaults (from local or external settings)
|
||||
app_configs = dict # overwrite code-defaults (from local or external/online JSON settings file)
|
||||
#else app_configs = <code defaults already initialized>
|
||||
|
||||
return
|
||||
|
|
|
@ -13,11 +13,19 @@ import xml.etree.ElementTree as ET
|
|||
import time
|
||||
import datetime
|
||||
import shutil
|
||||
from utils.app_configs import (DEBUG_SETTINGS, pretty_dict, init_app_configs, init_debug_settings, write_debug_setting, ensure_kohya_local_venv_is_symlinked)
|
||||
from utils.app_configs import (app_configs, DEBUG_SETTINGS, pretty_dict, init_app_configs, init_debug_settings, write_debug_setting, ensure_kohya_local_venv_is_symlinked)
|
||||
from utils.model_utils import (get_sha256_hash_from_file)
|
||||
|
||||
INSTALL_STATUS_FILE = '/tmp/install_status.json'
|
||||
|
||||
# lutzapps - support for bkohya gradio url
|
||||
BKOHYA_LAUNCH_URL = "" # will be captured during run_app('bkohya', ...) from bkohya log
|
||||
# e.g. https://85f6f17d6d725c6cde.gradio.live
|
||||
|
||||
def get_bkohya_launch_url() -> str:
|
||||
global BKOHYA_LAUNCH_URL
|
||||
return BKOHYA_LAUNCH_URL
|
||||
|
||||
def is_process_running(pid):
|
||||
try:
|
||||
process = psutil.Process(pid)
|
||||
|
@ -34,7 +42,32 @@ def run_app(app_name, command, running_processes):
|
|||
'status': 'running'
|
||||
}
|
||||
|
||||
# lutzapps - capture the gradio-url for bkohya app
|
||||
global BKOHYA_LAUNCH_URL
|
||||
|
||||
BKOHYA_LAUNCH_URL = "" # will be captured during run_app('bkohya', ...) from bkohya log
|
||||
# e.g. https://85f6f17d6d725c6cde.gradio.live
|
||||
|
||||
for line in process.stdout:
|
||||
# wait for gradio-url in bkohya log (the --share option generates a gradio url)
|
||||
if app_name == 'bkohya' and BKOHYA_LAUNCH_URL == "":
|
||||
gradio_mode = ("--share" in command.lower())
|
||||
if gradio_mode and ".gradio.live" in line:
|
||||
# get the gradio url from the log line
|
||||
# line = '* Running on public URL: https://85f6f17d6d725c6cde.gradio.live\n'
|
||||
gradio_url_pattern = r"https://([\w.-]+(?:\.[\w.-]+)+)"
|
||||
|
||||
match = re.search(gradio_url_pattern, line)
|
||||
if match:
|
||||
BKOHYA_LAUNCH_URL = match.group(0) # Full URL, e.g., "https://85f6f17d6d725c6cde.gradio.live"
|
||||
print(f"Public Gradio-URL found in bkohya log: {BKOHYA_LAUNCH_URL}")
|
||||
|
||||
elif not gradio_mode and "127.0.0.1" in line: # only wait for this when gradio_mode = False (=local URL mode)
|
||||
port = app_configs[app_name]['port'] # read the configured port from app_configs
|
||||
# line = '* Running on local URL: http://127.0.0.1:7864
|
||||
BKOHYA_LAUNCH_URL = f"http://127.0.0.1:{port}"
|
||||
print(f"Local-URL found in bkohya log: {BKOHYA_LAUNCH_URL}")
|
||||
|
||||
running_processes[app_name]['log'].append(line.strip())
|
||||
if len(running_processes[app_name]['log']) > 1000:
|
||||
running_processes[app_name]['log'] = running_processes[app_name]['log'][-1000:]
|
||||
|
|
|
@ -18,9 +18,9 @@ services:
|
|||
|
||||
# - 3000:3000 # ComfyUI
|
||||
# - 6006:6006 # Tensorboard (needed by kohya_ss)
|
||||
# - 7860:7860 # Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
# - 7862:7862 # Forge (aka Stable-Diffiusion-WebUI-Forge)
|
||||
# - 7863:7863 # A1111 (aka Stable-Diffiusion-WebUI)
|
||||
# - 7864:7864 # Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
|
||||
env_file:
|
||||
- .env # pass additional env-vars (hf_token, civitai token, ssh public-key) from ".env" file to container
|
||||
|
|
|
@ -19,6 +19,6 @@ services:
|
|||
|
||||
- 3000:3000 # ComfyUI
|
||||
- 6006:6006 # Tensorboard (needed by kohya_ss)
|
||||
- 7860:7860 # Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
- 7862:7862 # Forge (aka Stable-Diffiusion-WebUI-Forge)
|
||||
- 7863:7863 # A1111 (aka Stable-Diffiusion-WebUI)
|
||||
- 7864:7864 # Kohya-ss (lutzapps - added new Kohya app with FLUX support)
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
<li>Better Comfy UI</li>
|
||||
<li>Better Forge</li>
|
||||
<li>Better A1111</li>
|
||||
<li>Better Kohya</li>
|
||||
</ul>
|
||||
|
||||
<h2>Getting Started</h2>
|
||||
|
|
Loading…
Reference in a new issue