From 52f170532479b8ad515f018cfaf9d279c447bc3f Mon Sep 17 00:00:00 2001 From: Nick Yeoman Date: Wed, 26 Nov 2025 20:07:00 -0800 Subject: [PATCH] modifying things for portainer --- _build/portainer_template_build.py | 67 ++-- archivebox/docker-compose.yml | 7 +- archivebox/sample.env | 3 - {directus => directus_dev}/README.md | 0 {directus => directus_dev}/docker-compose.yml | 0 {directus => directus_dev}/sample.env | 0 mariadb/docker-compose.yml | 20 +- mariadb/sample.env | 6 - nocodb/docker-compose.yml | 8 - {nocodb => nocodb_dev}/README.md | 5 + nocodb_dev/docker-compose.yml | 9 + {nocodb => nocodb_dev}/old.yml | 0 {nocodb => nocodb_dev}/sample.env | 0 {stashapp => stashapp_notes}/README.md | 0 .../docker-compose.yml | 0 {stashapp => stashapp_notes}/sample.env | 0 templates.json | 378 +----------------- zammad/sample.env | 4 - 18 files changed, 74 insertions(+), 433 deletions(-) rename {directus => directus_dev}/README.md (100%) rename {directus => directus_dev}/docker-compose.yml (100%) rename {directus => directus_dev}/sample.env (100%) delete mode 100644 nocodb/docker-compose.yml rename {nocodb => nocodb_dev}/README.md (78%) create mode 100644 nocodb_dev/docker-compose.yml rename {nocodb => nocodb_dev}/old.yml (100%) rename {nocodb => nocodb_dev}/sample.env (100%) rename {stashapp => stashapp_notes}/README.md (100%) rename {stashapp => stashapp_notes}/docker-compose.yml (100%) rename {stashapp => stashapp_notes}/sample.env (100%) diff --git a/_build/portainer_template_build.py b/_build/portainer_template_build.py index b21f6c3..a6a5abe 100644 --- a/_build/portainer_template_build.py +++ b/_build/portainer_template_build.py @@ -59,7 +59,6 @@ def find_logo_url(dir_path: Path, nologo: bool = False) -> str: return f"{base_url}default.png" - # --------------------------------------------------------- # Parse image from docker-compose.yml using sample.env defaults # --------------------------------------------------------- @@ -80,9 +79,7 @@ def parse_image(compose_path: Path, env_vars: list) -> str: bash_default = match.group(2) return env_defaults.get(var_name, bash_default if bash_default else "") - # Regex matches ${VAR} or ${VAR:-default} image = re.sub(r"\$\{([^:}]+)(?:[:-]([^}]+))?\}", replace_var, image) - return image return "" @@ -107,37 +104,47 @@ def parse_ports(compose_path: Path): if in_ports: if not stripped or not stripped.startswith("-"): break - # Remove "- " prefix, quotes, and strip comments + port_str = stripped[1:].strip().split("#", 1)[0].strip().strip('"').strip("'") if not port_str: continue - if ":" in port_str: - host_port, container_port = port_str.split(":", 1) + + protocol = "tcp" + if "/" in port_str: + port_part, protocol_part = port_str.split("/", 1) + protocol = protocol_part.strip() else: - container_port = port_str + port_part = port_str + + if ":" in port_part: + host_port, container_port = port_part.split(":", 1) + else: + container_port = port_part host_port = container_port + try: - container_port = int(container_port.split("/")[0].strip()) - host_port = int(host_port.split("/")[0].strip()) + container_port = int(container_port.strip()) + host_port = int(host_port.strip()) except ValueError: continue + ports_list.append({ "container": container_port, "published": host_port, - "protocol": "tcp" + "protocol": protocol }) return ports_list -# --------------------------------------------------------- -# Parse volumes from docker-compose.yml -# Returns a list of dicts: {"name": "volume_name", "container": "/container/path"} -# --------------------------------------------------------- # --------------------------------------------------------- # Parse volumes from docker-compose.yml # Returns a list of dicts: {"name": "unique-name", "container": "/container/path"} # --------------------------------------------------------- def parse_volumes(compose_path: Path, stack_name: str): + """ + Parse volumes from docker-compose.yml and generate Portainer-ready entries. + Host paths and VOL_PATH references are ignored; only container paths are used. + """ if not compose_path.exists(): return [] @@ -153,15 +160,27 @@ def parse_volumes(compose_path: Path, stack_name: str): if in_volumes: if not stripped or not stripped.startswith("-"): break + + # Strip "- ", quotes, inline comments volume_str = stripped[1:].strip().split("#", 1)[0].strip().strip('"').strip("'") if not volume_str: continue - parts = volume_str.rsplit(":", 1) - container_path = parts[-1].strip() + + # Split host:container[:ro|rw] + parts = volume_str.split(":") + if len(parts) == 1: + container_path = parts[0].strip() + else: + container_path = parts[-1].strip() # always take the last part as container path + + # Remove :ro or :rw suffix if present container_path = re.sub(r":(ro|rw)$", "", container_path) + + # Generate unique name for Portainer from stack + container path name = f"{stack_name}-{container_path.strip('/').replace('/', '-')}" if not name: name = f"{stack_name}-volume" + volumes.append({"name": name, "container": container_path}) return volumes @@ -188,7 +207,6 @@ def parse_env_vars(dir_path: Path): if "=" in line: key, value = line.split("=", 1) key = key.strip() - # Remove inline comment after #, then strip quotes and whitespace value = value.split("#", 1)[0].strip().strip('"').strip("'") if key: env_list.append({"name": key, "default": value}) @@ -198,25 +216,23 @@ def parse_env_vars(dir_path: Path): # --------------------------------------------------------- # Build template object for a stack directory # --------------------------------------------------------- -def generate_template_object(dir_path: Path): +def generate_template_object(dir_path: Path, nologo: bool = False): name = dir_path.name compose_file = dir_path / "docker-compose.yml" readme_file = dir_path / "README.md" - # Extract info description = extract_overview(readme_file, name) - logo = find_logo_url(dir_path, nologo=False) # for dev/test + logo = find_logo_url(dir_path, nologo=False) env_vars = parse_env_vars(dir_path) image = parse_image(compose_file, env_vars) ports = parse_ports(compose_file) - volumes = parse_volumes(compose_file, name) # pass stack name for unique volume naming + volumes = parse_volumes(compose_file, name) - # Environment variables entries for Portainer env_entries = [ - {"name": v["name"], "label": v["name"], "default": v["default"]} for v in env_vars + {"name": v["name"], "label": v["name"], "default": v["default"]} + for v in env_vars if v["default"] is not None ] - # Build template object return { "type": 1, "title": name, @@ -252,9 +268,8 @@ def main(): if not (item / "docker-compose.yml").exists(): continue - templates.append(generate_template_object(item)) + templates.append(generate_template_object(item, nologo=True)) - # Wrap in Portainer top-level object output_data = { "version": "3", "templates": templates diff --git a/archivebox/docker-compose.yml b/archivebox/docker-compose.yml index 364407d..cf39667 100644 --- a/archivebox/docker-compose.yml +++ b/archivebox/docker-compose.yml @@ -3,9 +3,12 @@ services: image: ${ARCHIVEBOX_IMAGE:-archivebox/archivebox:stable} restart: unless-stopped volumes: - - ${VOL_PATH:-./data}/archive-data:/data + - "archivebox-data:/data" environment: - ARCHIVEBOX_UID=1000 - ARCHIVEBOX_GID=1000 - - PYTHONUNBUFFERED=1 # Ensures logs are output in real-time + - PYTHONUNBUFFERED=1 command: server --quick-init 0.0.0.0:8000 + +volumes: + archivebox-data: diff --git a/archivebox/sample.env b/archivebox/sample.env index cc785b1..baeeb11 100644 --- a/archivebox/sample.env +++ b/archivebox/sample.env @@ -1,5 +1,2 @@ -COOKBOOK=/git/docker-compose-cookbooks #HELP: cookbooks -VOL_PATH=./data - # ARCHIVEBOX ARCHIVEBOX_IMAGE=archivebox/archivebox:sha-1d49bee diff --git a/directus/README.md b/directus_dev/README.md similarity index 100% rename from directus/README.md rename to directus_dev/README.md diff --git a/directus/docker-compose.yml b/directus_dev/docker-compose.yml similarity index 100% rename from directus/docker-compose.yml rename to directus_dev/docker-compose.yml diff --git a/directus/sample.env b/directus_dev/sample.env similarity index 100% rename from directus/sample.env rename to directus_dev/sample.env diff --git a/mariadb/docker-compose.yml b/mariadb/docker-compose.yml index 107838f..bec2485 100644 --- a/mariadb/docker-compose.yml +++ b/mariadb/docker-compose.yml @@ -1,13 +1,19 @@ services: - mariadb: image: ${MARIADB_IMAGE:-mariadb:latest} restart: unless-stopped - command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed + command: > + --transaction-isolation=READ-COMMITTED + --binlog-format=ROW + --innodb-file-per-table=1 + --skip-innodb-read-only-compressed environment: - - MARIADB_DATABASE=${MARIADB_MARIADB_DATABASE:-mydb} - - MARIADB_ROOT_PASSWORD=${MARIADB_MARIADB_ROOT_PASSWORD:-ChangeThisPassword} - - MARIADB_USER=${MARIADB_MARIADB_USER:-dbuser} - - MARIADB_PASSWORD=${MARIADB_MARIADB_PASSWORD:-AlsoChangeThisPassword} + - MARIADB_DATABASE=${MARIADB_DATABASE:-mydb} + - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD:-ChangeThisPassword} + - MARIADB_USER=${MARIADB_USER:-dbuser} + - MARIADB_PASSWORD=${MARIADB_PASSWORD:-AlsoChangeThisPassword} volumes: - - ${VOL_PATH:-./data/}/mariadb:/var/lib/mysql + - mariadb-data:/var/lib/mysql + +volumes: + mariadb-data: diff --git a/mariadb/sample.env b/mariadb/sample.env index ffd1fd6..1363cab 100644 --- a/mariadb/sample.env +++ b/mariadb/sample.env @@ -1,9 +1,3 @@ -# Global -COMPOSE_PROJECT_NAME=project -TZ=America/Vancouver -VOL_CONFIG_PATH=/data/projectName/config -VOL_PATH=/data/projectName/data - # MariaDB MARIADB_IMAGE=mariadb:latest MARIADB_MARIADB_DATABASE=mydb diff --git a/nocodb/docker-compose.yml b/nocodb/docker-compose.yml deleted file mode 100644 index abe0a4e..0000000 --- a/nocodb/docker-compose.yml +++ /dev/null @@ -1,8 +0,0 @@ -services: - nc: - image: ${NOCODB_IMAGE:-nocodb/nocodb:latest} - restart: unless-stopped - # environment: - # - NC_DB=${NCDB_NC_DB:-mysql2://root_db:3306?u=noco&p=password&d=root_db} - volumes: - - "${VOL_PATH:-./data}/nc_data:/usr/app/data" diff --git a/nocodb/README.md b/nocodb_dev/README.md similarity index 78% rename from nocodb/README.md rename to nocodb_dev/README.md index bf4e1ba..9cfdcab 100644 --- a/nocodb/README.md +++ b/nocodb_dev/README.md @@ -11,3 +11,8 @@ Proxy Port: 8080 ## Description This project is setup to use sql lite. Although it can use mysql with some env vars. + +## Notes + +# environment: + # - NC_DB=${NCDB_NC_DB:-mysql2://root_db:3306?u=noco&p=password&d=root_db} \ No newline at end of file diff --git a/nocodb_dev/docker-compose.yml b/nocodb_dev/docker-compose.yml new file mode 100644 index 0000000..597df17 --- /dev/null +++ b/nocodb_dev/docker-compose.yml @@ -0,0 +1,9 @@ +services: + nc: + image: ${NOCODB_IMAGE:-nocodb/nocodb:latest} + restart: unless-stopped + volumes: + - "nocodb-data:/usr/app/data" + +volumes: + nocodb-data: diff --git a/nocodb/old.yml b/nocodb_dev/old.yml similarity index 100% rename from nocodb/old.yml rename to nocodb_dev/old.yml diff --git a/nocodb/sample.env b/nocodb_dev/sample.env similarity index 100% rename from nocodb/sample.env rename to nocodb_dev/sample.env diff --git a/stashapp/README.md b/stashapp_notes/README.md similarity index 100% rename from stashapp/README.md rename to stashapp_notes/README.md diff --git a/stashapp/docker-compose.yml b/stashapp_notes/docker-compose.yml similarity index 100% rename from stashapp/docker-compose.yml rename to stashapp_notes/docker-compose.yml diff --git a/stashapp/sample.env b/stashapp_notes/sample.env similarity index 100% rename from stashapp/sample.env rename to stashapp_notes/sample.env diff --git a/templates.json b/templates.json index 80087a7..cb5fa6c 100644 --- a/templates.json +++ b/templates.json @@ -1,66 +1,6 @@ { "version": "3", "templates": [ - { - "type": 1, - "title": "phpcontainer", - "description": "phpcontainer description to come", - "note": "Auto-generated template from repository", - "categories": [ - "Auto" - ], - "platform": "linux", - "logo": "https://i.4lt.ca/cookbooks/default.png", - "image": "4lights/phpcontainer:latest", - "repository": { - "url": "https://github.com/nickyeoman/docker-compose-cookbooks", - "stackfile": "phpcontainer/docker-compose.yml", - "stackfile_plain": false - }, - "env": [ - { - "name": "COOKBOOK", - "label": "COOKBOOK", - "default": "/docker-compose-cookbooks" - }, - { - "name": "COMPOSE_PROJECT_NAME", - "label": "COMPOSE_PROJECT_NAME", - "default": "project" - }, - { - "name": "TZ", - "label": "TZ", - "default": "America/Vancouver" - }, - { - "name": "VOL_CONFIG_PATH", - "label": "VOL_CONFIG_PATH", - "default": "/data/projectName/config" - }, - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "/data/projectName/data" - }, - { - "name": "PHPCONTAINER_IMAGE", - "label": "PHPCONTAINER_IMAGE", - "default": "4lights/phpcontainer:latest" - } - ], - "ports": [], - "volumes": [ - { - "name": "phpcontainer-data", - "container": "/data" - }, - { - "name": "phpcontainer-usr-local-etc-php-php.ini", - "container": "/usr/local/etc/php/php.ini" - } - ] - }, { "type": 1, "title": "wallabag", @@ -235,26 +175,6 @@ "stackfile_plain": false }, "env": [ - { - "name": "COMPOSE_PROJECT_NAME", - "label": "COMPOSE_PROJECT_NAME", - "default": "project" - }, - { - "name": "TZ", - "label": "TZ", - "default": "America/Vancouver" - }, - { - "name": "VOL_CONFIG_PATH", - "label": "VOL_CONFIG_PATH", - "default": "/data/projectName/config" - }, - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "/data/projectName/data" - }, { "name": "MARIADB_IMAGE", "label": "MARIADB_IMAGE", @@ -595,7 +515,7 @@ { "container": 53, "published": 53, - "protocol": "tcp" + "protocol": "udp" }, { "container": 80, @@ -751,117 +671,6 @@ } ] }, - { - "type": 1, - "title": "nocodb", - "description": "Docker Hub: https://hub.docker.com/r/nocodb/nocodb Project: https://nocodb.com/ Docker Compose Example: https://github.com/nocodb/nocodb/blob/master/docker-compose/mysql/docker-compose.yml Proxy Port: 8080", - "note": "Auto-generated template from repository", - "categories": [ - "Auto" - ], - "platform": "linux", - "logo": "https://i.4lt.ca/cookbooks/default.png", - "image": "nocodb/nocodb:latest", - "repository": { - "url": "https://github.com/nickyeoman/docker-compose-cookbooks", - "stackfile": "nocodb/docker-compose.yml", - "stackfile_plain": false - }, - "env": [ - { - "name": "COOKBOOK", - "label": "COOKBOOK", - "default": "/git/docker-compose-cookbooks" - }, - { - "name": "NOCODB_IMAGE", - "label": "NOCODB_IMAGE", - "default": "nocodb/nocodb:latest" - } - ], - "ports": [], - "volumes": [ - { - "name": "nocodb-usr-app-data", - "container": "/usr/app/data" - } - ] - }, - { - "type": 1, - "title": "directus", - "description": "directus description to come", - "note": "Auto-generated template from repository", - "categories": [ - "Auto" - ], - "platform": "linux", - "logo": "https://i.4lt.ca/cookbooks/default.png", - "image": "directus/directus:latest", - "repository": { - "url": "https://github.com/nickyeoman/docker-compose-cookbooks", - "stackfile": "directus/docker-compose.yml", - "stackfile_plain": false - }, - "env": [ - { - "name": "COMPOSE_PROJECT_NAME", - "label": "COMPOSE_PROJECT_NAME", - "default": "directus" - }, - { - "name": "TZ", - "label": "TZ", - "default": "America/Vancouver" - }, - { - "name": "VOL_CONFIG_PATH", - "label": "VOL_CONFIG_PATH", - "default": "/docker/directus/config" - }, - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "/docker/directus/data" - }, - { - "name": "DIRECTUS_SECRET", - "label": "DIRECTUS_SECRET", - "default": "01234567890123456789012345678912" - }, - { - "name": "DIRECTUS_ADMIN_EMAIL", - "label": "DIRECTUS_ADMIN_EMAIL", - "default": "noreply@example.com" - }, - { - "name": "DIRECTUS_ADMIN_PASSWORD", - "label": "DIRECTUS_ADMIN_PASSWORD", - "default": "enter_secure_password_here" - } - ], - "ports": [ - { - "container": 8055, - "published": 8000, - "protocol": "tcp" - } - ], - "volumes": [ - { - "name": "directus-directus-uploads", - "container": "/directus/uploads" - }, - { - "name": "directus-directus-extensions", - "container": "/directus/extensions" - }, - { - "name": "directus-directus-templates", - "container": "/directus/templates" - } - ] - }, { "type": 1, "title": "matomo", @@ -1882,90 +1691,6 @@ } ] }, - { - "type": 1, - "title": "semaphore", - "description": "* [Docker Hub](https://hub.docker.com/r/semaphoreui/semaphore) * [Official Website](https://semaphoreui.com/) * [Docker Compose Example](https://docs.semaphoreui.com/administration-guide/installation/#docker)", - "note": "Auto-generated template from repository", - "categories": [ - "Auto" - ], - "platform": "linux", - "logo": "https://i.4lt.ca/cookbooks/default.png", - "image": "semaphoreui/semaphore:latest", - "repository": { - "url": "https://github.com/nickyeoman/docker-compose-cookbooks", - "stackfile": "semaphore/docker-compose.yml", - "stackfile_plain": false - }, - "env": [ - { - "name": "COOKBOOK", - "label": "COOKBOOK", - "default": "/git/docker-compose-cookbooks" - }, - { - "name": "TZ", - "label": "TZ", - "default": "America/Vancouver" - }, - { - "name": "VOL_CONFIG_PATH", - "label": "VOL_CONFIG_PATH", - "default": "./config" - }, - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "./data" - }, - { - "name": "SEMAPHORE_IMAGE", - "label": "SEMAPHORE_IMAGE", - "default": "semaphoreui/semaphore:latest" - }, - { - "name": "SEMAPHORE_ACCESS_KEY_ENCRYPTION", - "label": "SEMAPHORE_ACCESS_KEY_ENCRYPTION", - "default": "1234567890123456789012345678901234567890" - }, - { - "name": "SEMAPHORE_ADMIN_EMAIL", - "label": "SEMAPHORE_ADMIN_EMAIL", - "default": "example@example.com" - }, - { - "name": "SEMAPHORE_ADMIN_NAME", - "label": "SEMAPHORE_ADMIN_NAME", - "default": "admin" - }, - { - "name": "SEMAPHORE_ADMIN_PASSWORD", - "label": "SEMAPHORE_ADMIN_PASSWORD", - "default": "password" - }, - { - "name": "SEMAPHORE_PLAYBOOK_PATH", - "label": "SEMAPHORE_PLAYBOOK_PATH", - "default": "/tmp/semaphore/" - } - ], - "ports": [], - "volumes": [ - { - "name": "semaphore---tmp-semaphore-}", - "container": "-/tmp/semaphore/}" - }, - { - "name": "semaphore-home-semaphore-.ssh", - "container": "/home/semaphore/.ssh/" - }, - { - "name": "semaphore-etc-hosts", - "container": "/etc/hosts" - } - ] - }, { "type": 1, "title": "uptimekuma", @@ -2019,21 +1744,6 @@ "stackfile_plain": false }, "env": [ - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "./data" - }, - { - "name": "TZ", - "label": "TZ", - "default": "America/Vancouver" - }, - { - "name": "COMPOSE_PROJECT_NAME", - "label": "COMPOSE_PROJECT_NAME", - "default": "zammad" - }, { "name": "ZAMMAD_RAILS_IMAGE", "label": "ZAMMAD_RAILS_IMAGE", @@ -3497,82 +3207,6 @@ } ] }, - { - "type": 1, - "title": "stashapp", - "description": "This Docker Compose configuration sets up the Stash application using Docker containers. - Stash App: [Stash on Docker Hub](https://hub.docker.com/r/stashapp/stash) - Compose Example: [Stash GitHub Repository](https://github.com/stashapp/stash/blob/develop/docker/production/docker-compose.yml) - ProxyPort: 9999", - "note": "Auto-generated template from repository", - "categories": [ - "Auto" - ], - "platform": "linux", - "logo": "https://i.4lt.ca/cookbooks/default.png", - "image": "stashapp/stash:latest", - "repository": { - "url": "https://github.com/nickyeoman/docker-compose-cookbooks", - "stackfile": "stashapp/docker-compose.yml", - "stackfile_plain": false - }, - "env": [ - { - "name": "STASHAPP_IMAGE", - "label": "STASHAPP_IMAGE", - "default": "stashapp/stash:latest" - }, - { - "name": "STASHAPP_STASH_CACHE", - "label": "STASHAPP_STASH_CACHE", - "default": "/cache/" - }, - { - "name": "STASHAPP_STASH_DOMAIN_NAME", - "label": "STASHAPP_STASH_DOMAIN_NAME", - "default": "stash.yourdomain.ca" - }, - { - "name": "STASHAPP_STASH_GENERATED", - "label": "STASHAPP_STASH_GENERATED", - "default": "/generated/" - }, - { - "name": "STASHAPP_STASH_METADATA", - "label": "STASHAPP_STASH_METADATA", - "default": "/metadata/" - }, - { - "name": "STASHAPP_STASH_STASH", - "label": "STASHAPP_STASH_STASH", - "default": "/data/" - } - ], - "ports": [], - "volumes": [ - { - "name": "stashapp-cache", - "container": "/cache" - }, - { - "name": "stashapp-generated", - "container": "/generated" - }, - { - "name": "stashapp-metadata", - "container": "/metadata" - }, - { - "name": "stashapp-root", - "container": "/root" - }, - { - "name": "stashapp-data", - "container": "/data" - }, - { - "name": "stashapp-ro", - "container": "ro" - } - ] - }, { "type": 1, "title": "archivebox", @@ -3590,16 +3224,6 @@ "stackfile_plain": false }, "env": [ - { - "name": "COOKBOOK", - "label": "COOKBOOK", - "default": "/git/docker-compose-cookbooks" - }, - { - "name": "VOL_PATH", - "label": "VOL_PATH", - "default": "./data" - }, { "name": "ARCHIVEBOX_IMAGE", "label": "ARCHIVEBOX_IMAGE", diff --git a/zammad/sample.env b/zammad/sample.env index a249be2..f322743 100644 --- a/zammad/sample.env +++ b/zammad/sample.env @@ -3,10 +3,6 @@ # https://docs.zammad.org/en/latest/install/docker-compose/environment.html ############################################# -VOL_PATH=./data -TZ=America/Vancouver -COMPOSE_PROJECT_NAME=zammad - ZAMMAD_RAILS_IMAGE=ghcr.io/zammad/zammad:latest ZAMMAD_RESTART=always scheme=http