Skip to content

Commit

Permalink
through to merge (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
the-dusky authored Dec 17, 2024
2 parents 07a023f + ba04dd4 commit c7d9c12
Show file tree
Hide file tree
Showing 43 changed files with 3,181 additions and 445 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ yarn-error.log*
# Sentry Config File
.sentryclirc

package-lock.json
package-lock.json
1 change: 0 additions & 1 deletion docker/.env_openai

This file was deleted.

84 changes: 46 additions & 38 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,56 +1,64 @@
# Setup a server ready to accept component requests
# Use ubuntu user, not root
# Use a venv for ComfyUI
# Builder stage for SSH key
FROM pytorch/pytorch:latest as start

FROM pytorch/pytorch:latest AS start
RUN apt update && apt-get install -y \
git git-lfs rsync nginx wget curl nano ffmpeg libsm6 libxext6 \
cron sudo ssh zstd jq build-essential cmake ninja-build \
gcc g++ openssh-client aria2 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# ARG DEBIAN_FRONTEND=noninteractive PIP_PREFER_BINARY=1

RUN apt update && apt-get install -y git rsync nginx wget nano ffmpeg libsm6 libxext6 cron sudo ssh && apt-get clean

ARG GITACCESSKEY
FROM start AS middle

RUN useradd -m -d /home/ubuntu -s /bin/bash ubuntu
RUN usermod -aG sudo ubuntu
RUN mkdir -p /home/ubuntu/.ssh && touch /home/ubuntu/.ssh/authorized_keys
RUN echo ${GITACCESSKEY} >> /home/ubuntu/.ssh/authorized_keys
RUN chown -R ubuntu:ubuntu /home/ubuntu/.ssh
ENV ROOT=/workspace
ENV PATH="${ROOT}/.local/bin:${PATH}"
ENV CONFIG_DIR=${ROOT}/config
ENV COMFY_DIR=${ROOT}/ComfyUI

RUN mkdir -p /etc/ssh/sshd_config.d
RUN touch /etc/ssh/sshd_config.d/ubuntu.conf
RUN echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config.d/ubuntu.conf
RUN echo "PasswordAuthentication no" >> /etc/ssh/sshd_config.d/ubuntu.conf
WORKDIR ${ROOT}

RUN service ssh restart
RUN sudo cp /etc/sudoers /etc/sudoers.bak
RUN echo 'ubuntu ALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers
RUN git clone https://github.com/comfyanonymous/ComfyUI.git ${COMFY_DIR} && \
cd ${COMFY_DIR} && \
pip install --upgrade pip && \
pip install -r requirements.txt && \
pip install huggingface_hub[hf_transfer] && \
pip install tqdm

FROM start AS middle
FROM middle AS end

RUN su - ubuntu
COPY config/ ${CONFIG_DIR}/

RUN mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo ${GITACCESSKEY} >> ~/.ssh/id_ed25519 && chmod 600 ~/.ssh/id_ed25519
# Debug: List config files
RUN find ${CONFIG_DIR} -name "config.json"

ENV ROOT=/comfyui-launcher
# Set default config type
ARG CONFIG_TYPE

RUN eval "$(ssh-agent -s)" && ssh-add /root/.ssh/id_ed25519 && ssh-keyscan github.com > ~/.ssh/githubKey && ssh-keygen -lf ~/.ssh/githubKey && cat ~/.ssh/githubKey >> ~/.ssh/known_hosts
# Copy type-specific config files
COPY config/${CONFIG_TYPE} ${CONFIG_DIR}/

WORKDIR ${ROOT}
# Copy init.d script
COPY scripts/comfyui /etc/init.d/comfyui
RUN chmod +x /etc/init.d/comfyui && \
update-rc.d comfyui defaults

# COPY ./build.sh /scripts/build.sh
# Copy startup script
COPY scripts/start.sh /start.sh
RUN chmod +x /start.sh

# RUN /scripts/build.sh
COPY scripts ${ROOT}/scripts

COPY ./nodes.sh /nodes.sh
RUN /nodes.sh
RUN rm -rf ${ROOT}/scripts/start.sh && rm -rf ${ROOT}/scripts/comfyui

FROM middle AS end

COPY --from=scripts . /scripts/
RUN chmod +x /scripts/*.sh
# RUN usermod -aG crontab ubuntu
# Create cron pid directory with correct permissions
RUN mkdir -p /var/run/cron \
&& touch /var/run/cron/crond.pid \
&& chmod 644 /var/run/cron/crond.pid
RUN sed -i 's/touch $PIDFILE/# touch $PIDFILE/g' /etc/init.d/cron

RUN mv /nodes.sh /scripts/nodes.sh
RUN cd ${ROOT} && git-lfs install

COPY ./models.sh /scripts/models.sh

CMD ["/scripts/start.sh"]
# Start services and application
CMD ["/start.sh"]
229 changes: 229 additions & 0 deletions docker/_oldstuff/_scripts/generate_dockerfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
import json
import os
import hashlib
import shutil
from typing import Dict, List

def read_json_config(config_path: str) -> Dict:
with open(config_path, 'r') as f:
return json.load(f)

def generate_download_stage(model: Dict, index: int) -> str:
stage_name = f"download_{index}"
path = model['path']
name = model.get('name', f'model_{index}')

# If path ends with /, append the name to create full path
if path.endswith('/'):
path_dir = path.rstrip('/')
full_path = os.path.join(path_dir, name)
else:
full_path = path
path_dir = os.path.dirname(path)

# Prepend ComfyUI to the path
comfy_path = os.path.join("ComfyUI", full_path)
comfy_dir = os.path.dirname(comfy_path)

return f"""RUN echo "Downloading {name}..."
RUN mkdir -p ${{ROOT}}/{comfy_dir}
RUN wget -O "${{ROOT}}/{comfy_path}" "{model['url']}"
""", comfy_path

def generate_node_stage(node: Dict, index: int) -> str:
"""Generate a Dockerfile stage for installing a node."""
name = node.get('name', f'node_{index}')
url = node.get('url', '')
commit = node.get('commit', None)

# Extract repo name from URL
repo_name = url.split('/')[-1].replace('.git', '')

# Build the clone commands only
commands = [f"""FROM middle-comfy-install AS node_{index}
RUN echo "Installing node: {name}..."
RUN mkdir -p ${{ROOT}}/ComfyUI/custom_nodes && \\
cd ${{ROOT}}/ComfyUI/custom_nodes && \\
git clone {url}"""]

if commit:
commands.append(f'RUN cd ${{ROOT}}/ComfyUI/custom_nodes/{repo_name} && git checkout {commit}')

return "\n".join(commands), repo_name

def generate_dockerfile_content(models_config: str, nodes_config: str = None) -> str:
# First, generate the startup script
script_content = ["#!/bin/bash", ""]

# Add model download function
script_content.extend([
"check_and_download_models() {",
' echo "Checking and downloading models if needed..."',
""
])

# Add model download commands
if models_config:
models = read_json_config(models_config).get('models', [])
for model in models:
url = model.get('url', '')
path = model.get('path', '')
name = model.get('name', '')

full_path = os.path.join("${ROOT}/ComfyUI", path)
script_content.extend([
f' if [ ! -f "{full_path}/{name}" ]; then',
f' echo "Downloading {name}..."',
f' mkdir -p "{full_path}"',
f' wget -q --header="Authorization: Bearer $HF_TOKEN" "{url}" -O "{full_path}/{name}"',
' fi',
''
])

# Add node installation function
script_content.extend([
"}",
"",
"install_nodes() {",
' cd ${ROOT}/ComfyUI/custom_nodes',
""
])

# Add node installation commands
if nodes_config:
nodes = read_json_config(nodes_config).get('nodes', [])
for node in nodes:
url = node.get('url', '')
name = node.get('name', '')
commit = node.get('commit', None)
repo_name = url.split('/')[-1].replace('.git', '')

script_content.extend([
f' if [ ! -d "{repo_name}" ]; then',
f' echo "Installing node: {name}"',
f' git clone {url}',
])

if commit:
script_content.append(f' cd {repo_name} && git checkout {commit} && cd ..')

script_content.extend([
f' if [ -f "{repo_name}/requirements.txt" ]; then',
f' pip install -r "{repo_name}/requirements.txt"',
' fi',
' fi',
''
])

# Add script execution
script_content.extend([
"}",
"",
"# Run setup functions",
"check_and_download_models",
"install_nodes",
"",
"# Start ComfyUI",
"cd ${ROOT}/ComfyUI",
"python main.py"
])

# Write the startup script to a file
script_path = os.path.join(os.path.dirname(os.path.dirname(models_config)), "scripts")
os.makedirs(script_path, exist_ok=True)
with open(os.path.join(script_path, "start.sh"), "w") as f:
f.write("\n".join(script_content))

# Generate the Dockerfile content
content = []
content.append("# [GENERATED_CONTENT]\n")

# Setup environment variables
content.append("# Setup environment variables")
content.append('ARG HF_TOKEN')
content.append('ARG OPENAI_API_KEY')
content.append('ENV HF_TOKEN=$HF_TOKEN')
content.append('ENV OPENAI_API_KEY=$OPENAI_API_KEY')
content.append('ENV ROOT=/home/ubuntu')
content.append('ENV PATH="${ROOT}/.local/bin:${PATH}"\n')

# Create directories for volumes
content.append("# Create directories for volumes")
content.append("""RUN mkdir -p ${ROOT}/ComfyUI/models && \\
mkdir -p ${ROOT}/ComfyUI/custom_nodes && \\
chown -R ubuntu:ubuntu ${ROOT}/ComfyUI""")

# Copy and setup the startup script
content.extend([
"",
"# Copy startup script",
"COPY scripts/start.sh /start.sh",
"RUN chmod +x /start.sh",
"",
"# Set working directory",
"WORKDIR ${ROOT}/ComfyUI",
"",
"# Start the application",
'CMD ["/start.sh"]',
"",
"# [END_GENERATED_CONTENT]"
])

return "\n".join(content)

def merge_with_dockerfile(dockerfile_path: str, generated_content: str, marker: str = "# [GENERATED_CONTENT]") -> None:
# Create a new Dockerfile in the current directory
current_dir = os.getcwd()
new_dockerfile = os.path.join(current_dir, "Dockerfile")

# Copy the original Dockerfile
shutil.copy2(dockerfile_path, new_dockerfile)

# Read the contents of the new Dockerfile
with open(new_dockerfile, 'r') as f:
content = f.read()

# Split content at marker and reconstruct
if marker in content:
parts = content.split(marker)
if len(parts) >= 2:
# Construct new content with marker, generated content, and final stages
new_content = parts[0] + marker + "\n" + generated_content.split(marker)[1].split("# [END_GENERATED_CONTENT]")[0] + "\n\n" + "# [END_GENERATED_CONTENT]" + "\n\n" + parts[1].split("# [END_GENERATED_CONTENT]")[1]

# Write back to the new Dockerfile
with open(new_dockerfile, 'w') as f:
f.write(new_content)

print(f"Generated new Dockerfile at: {new_dockerfile}")
else:
print(f"Error: Marker found but content format unexpected")
else:
print(f"Error: Marker '{marker}' not found in Dockerfile")

if __name__ == "__main__":
import sys
import os

if len(sys.argv) < 3:
print("Usage: generate_dockerfile.py <dockerfile_path> <models_config_path> [nodes_config_path]")
sys.exit(1)

dockerfile_path = sys.argv[1]
models_config_path = sys.argv[2]
nodes_config_path = sys.argv[3] if len(sys.argv) > 3 else None

if not os.path.exists(dockerfile_path):
print(f"Dockerfile not found: {dockerfile_path}")
sys.exit(1)

if not os.path.exists(models_config_path):
print(f"Models config not found: {models_config_path}")
sys.exit(1)

if nodes_config_path and not os.path.exists(nodes_config_path):
print(f"Nodes config not found: {nodes_config_path}")
sys.exit(1)

content = generate_dockerfile_content(models_config_path, nodes_config_path)
merge_with_dockerfile(dockerfile_path, content)
Loading

0 comments on commit c7d9c12

Please sign in to comment.