From 256969c30691476dd240d4ffd23478694d61eece Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Thu, 6 Aug 2026 23:19:00 -0600 Subject: [PATCH] fix: bring remaining blueprints in line with the port conventions (audit green) Co-Authored-By: Claude Fable 5 --- blueprints/adguardhome/docker-compose.yml | 4 ++- blueprints/anytype/docker-compose.yml | 1 + blueprints/chibisafe/docker-compose.yml | 11 ------- blueprints/datalens/docker-compose.yml | 6 ++-- blueprints/dragonfly-db/docker-compose.yml | 4 +-- blueprints/drizzle-gateway/docker-compose.yml | 6 ---- blueprints/elastic-search/docker-compose.yml | 2 -- blueprints/emqx/docker-compose.yml | 8 ----- blueprints/enshrouded/docker-compose.yml | 2 +- blueprints/erpnext/docker-compose.yml | 31 ------------------- blueprints/fivem/docker-compose.yml | 3 +- blueprints/fonoster/docker-compose.yml | 1 + blueprints/frappe-hr/docker-compose.yml | 31 ------------------- blueprints/lodestone/docker-compose.yml | 1 + blueprints/mailpit/docker-compose.yml | 4 +-- blueprints/mailu/docker-compose.yml | 1 + blueprints/oryx/docker-compose.yml | 1 + blueprints/poste.io/docker-compose.yml | 1 + .../pre0.22.5-supabase/docker-compose.yml | 1 + blueprints/pterodactyl/docker-compose.yml | 6 ---- blueprints/qbittorrent/docker-compose.yml | 3 +- blueprints/seafile/docker-compose.yml | 10 ------ blueprints/triggerdotdev/docker-compose.yml | 15 --------- blueprints/unifi/docker-compose.yml | 1 + blueprints/wg-easy/docker-compose.yml | 5 +-- build-scripts/validate-docker-compose.ts | 18 +++++++++-- 26 files changed, 40 insertions(+), 137 deletions(-) diff --git a/blueprints/adguardhome/docker-compose.yml b/blueprints/adguardhome/docker-compose.yml index c0b01d3dc..bfda4d317 100644 --- a/blueprints/adguardhome/docker-compose.yml +++ b/blueprints/adguardhome/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — DNS (53/tcp+udp), DHCP (67/68) and DNS-over-TLS/QUIC (853) are not HTTP protocols; clients must reach them directly on the host, Traefik cannot route them. version: "3.8" services: adguardhome: @@ -10,7 +11,8 @@ services: - "68:68/tcp" # DHCP Client - "853:853/tcp" # DNS over TLS, DNS-over-QUIC - "853:853/udp" # DNS over TLS, DNS-over-QUIC - - "6060:6060/tcp" # HTTP (pprof) + expose: + - 6060 # HTTP (pprof) — debug endpoint, no need to publish it on the host volumes: - adguardhome-work:/opt/adguardhome/work - adguardhome-conf:/opt/adguardhome/conf diff --git a/blueprints/anytype/docker-compose.yml b/blueprints/anytype/docker-compose.yml index 5f3f70cee..36fc86329 100644 --- a/blueprints/anytype/docker-compose.yml +++ b/blueprints/anytype/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — Anytype clients speak the any-sync protocol (TCP 33010, UDP/QUIC 33020) directly against the server; it is not HTTP, so Traefik cannot route it. # Example: Any-Sync-Bundle with embedded MongoDB and Redis (all-in-one image) # # Usage: diff --git a/blueprints/chibisafe/docker-compose.yml b/blueprints/chibisafe/docker-compose.yml index 573cb16a7..db4462567 100644 --- a/blueprints/chibisafe/docker-compose.yml +++ b/blueprints/chibisafe/docker-compose.yml @@ -6,8 +6,6 @@ services: chibisafe: image: chibisafe/chibisafe:latest - networks: - - chibinet environment: - BASE_API_URL=http://chibisafe_server:8000 restart: unless-stopped @@ -20,8 +18,6 @@ services: chibisafe_server: image: chibisafe/chibisafe-server:latest - networks: - - chibinet volumes: - database:/app/database:rw - uploads:/app/uploads:rw @@ -43,8 +39,6 @@ services: caddy: image: caddy:2-alpine - networks: - - chibinet volumes: - ../files/Caddyfile:/etc/caddy/Caddyfile:ro - uploads:/app/uploads:ro @@ -62,8 +56,3 @@ volumes: database: uploads: logs: - -networks: - chibinet: - driver: bridge - internal: true diff --git a/blueprints/datalens/docker-compose.yml b/blueprints/datalens/docker-compose.yml index 94839e04b..c0dd8216a 100644 --- a/blueprints/datalens/docker-compose.yml +++ b/blueprints/datalens/docker-compose.yml @@ -23,7 +23,6 @@ services: - us data-api: - container_name: datalens-data-api image: ghcr.io/datalens-tech/datalens-data-api:0.2192.0 restart: always environment: @@ -43,7 +42,6 @@ services: - pg-compeng pg-us: - container_name: datalens-pg-us image: postgres:16-alpine restart: always environment: @@ -75,8 +73,8 @@ services: datalens: image: ghcr.io/datalens-tech/datalens-ui:0.2601.0 restart: always - ports: - - ${UI_PORT:-8080}:8080 + expose: + - 8080 # web UI — routed through Traefik via the template domain depends_on: - us - control-api diff --git a/blueprints/dragonfly-db/docker-compose.yml b/blueprints/dragonfly-db/docker-compose.yml index 44920f546..908f140b7 100644 --- a/blueprints/dragonfly-db/docker-compose.yml +++ b/blueprints/dragonfly-db/docker-compose.yml @@ -4,8 +4,8 @@ services: image: 'docker.dragonflydb.io/dragonflydb/dragonfly' ulimits: memlock: -1 - ports: - - "6379:6379" + expose: + - 6379 volumes: - dragonflydata:/data environment: diff --git a/blueprints/drizzle-gateway/docker-compose.yml b/blueprints/drizzle-gateway/docker-compose.yml index 460165764..e8c09ac1b 100644 --- a/blueprints/drizzle-gateway/docker-compose.yml +++ b/blueprints/drizzle-gateway/docker-compose.yml @@ -8,12 +8,6 @@ services: MASTERPASS: ${MASTERPASS} volumes: - drizzle-gateway:/app - networks: - - dokploy-network volumes: drizzle-gateway: - -networks: - dokploy-network: - external: true diff --git a/blueprints/elastic-search/docker-compose.yml b/blueprints/elastic-search/docker-compose.yml index 35110aabc..4ae349e4b 100644 --- a/blueprints/elastic-search/docker-compose.yml +++ b/blueprints/elastic-search/docker-compose.yml @@ -3,7 +3,6 @@ version: '3.8' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2 - container_name: elasticsearch environment: - discovery.type=single-node - xpack.security.enabled=false @@ -20,7 +19,6 @@ services: kibana: image: docker.elastic.co/kibana/kibana:8.10.2 - container_name: kibana environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 expose: diff --git a/blueprints/emqx/docker-compose.yml b/blueprints/emqx/docker-compose.yml index 4b11f0109..bde86aa7b 100644 --- a/blueprints/emqx/docker-compose.yml +++ b/blueprints/emqx/docker-compose.yml @@ -21,10 +21,6 @@ services: volumes: - emqx_data:/opt/emqx/data - emqx_log:/opt/emqx/log - networks: - dokploy-network: - aliases: - - emqx-service restart: unless-stopped healthcheck: test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"] @@ -52,7 +48,3 @@ services: volumes: emqx_data: emqx_log: - -networks: - dokploy-network: - external: true diff --git a/blueprints/enshrouded/docker-compose.yml b/blueprints/enshrouded/docker-compose.yml index 9a023c499..45cdf23d0 100644 --- a/blueprints/enshrouded/docker-compose.yml +++ b/blueprints/enshrouded/docker-compose.yml @@ -1,7 +1,7 @@ +# dokploy: allow-host-ports — Enshrouded game clients connect over raw UDP (15637 game, 27015 Steam query); Traefik cannot route UDP game traffic. services: enshrouded: image: mornedhels/enshrouded-server:latest - container_name: enshrouded hostname: enshrouded restart: unless-stopped stop_grace_period: 90s diff --git a/blueprints/erpnext/docker-compose.yml b/blueprints/erpnext/docker-compose.yml index 44561de62..fc56c8a00 100644 --- a/blueprints/erpnext/docker-compose.yml +++ b/blueprints/erpnext/docker-compose.yml @@ -10,8 +10,6 @@ services: <<: *custom_image volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -42,8 +40,6 @@ services: volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: @@ -63,8 +59,6 @@ services: - default volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -87,8 +81,6 @@ services: - long volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -111,8 +103,6 @@ services: - short volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -145,8 +135,6 @@ services: required: true volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network websocket: <<: *custom_image @@ -167,8 +155,6 @@ services: required: true volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network configurator: <<: *custom_image @@ -197,8 +183,6 @@ services: REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}" volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network create-site: <<: *custom_image @@ -237,8 +221,6 @@ services: DB_PORT: "${DB_PORT:-3306}" DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} INSTALL_APP_ARGS: ${INSTALL_APP_ARGS} - networks: - - bench-network migration: <<: *custom_image @@ -258,8 +240,6 @@ services: bench --site all set-config -p pause_scheduler 0; volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network db: image: mariadb:10.6 @@ -282,8 +262,6 @@ services: - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} volumes: - db-data:/var/lib/mysql - networks: - - bench-network redis-cache: deploy: @@ -292,8 +270,6 @@ services: image: redis:6.2-alpine volumes: - redis-cache-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -310,8 +286,6 @@ services: image: redis:6.2-alpine volumes: - redis-queue-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -328,8 +302,6 @@ services: image: redis:6.2-alpine volumes: - redis-socketio-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -349,6 +321,3 @@ volumes: type: "${SITE_VOLUME_TYPE}" o: "${SITE_VOLUME_OPTS}" device: "${SITE_VOLUME_DEV}" - -networks: - bench-network: diff --git a/blueprints/fivem/docker-compose.yml b/blueprints/fivem/docker-compose.yml index 7ea36bd54..61d676f8c 100644 --- a/blueprints/fivem/docker-compose.yml +++ b/blueprints/fivem/docker-compose.yml @@ -1,5 +1,6 @@ +# dokploy: allow-host-ports — FiveM game clients connect over raw TCP/UDP on 30120; Traefik cannot route game traffic. # docker-compose.yml -# +# # IMPORTANT: FiveM Template - Two Deployment Modes # # MODE 1: Standard FiveM Server diff --git a/blueprints/fonoster/docker-compose.yml b/blueprints/fonoster/docker-compose.yml index d1c23bba9..7ea86c529 100644 --- a/blueprints/fonoster/docker-compose.yml +++ b/blueprints/fonoster/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — VoIP stack: SIP signaling (5060-5063 TCP/UDP), RTP media (10000-10100/udp) and the gRPC API endpoints (envoy 8449, rtpengine control 8080) are reached directly by phones/SDKs; these protocols cannot be routed by Traefik. services: dashboard: image: fonoster/dashboard:0.15.15 diff --git a/blueprints/frappe-hr/docker-compose.yml b/blueprints/frappe-hr/docker-compose.yml index 7eec52c4b..20d86585d 100644 --- a/blueprints/frappe-hr/docker-compose.yml +++ b/blueprints/frappe-hr/docker-compose.yml @@ -10,8 +10,6 @@ services: <<: *custom_image volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -42,8 +40,6 @@ services: volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: @@ -63,8 +59,6 @@ services: - default volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -87,8 +81,6 @@ services: - long volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -111,8 +103,6 @@ services: - short volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network healthcheck: test: - CMD @@ -145,8 +135,6 @@ services: required: true volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network websocket: <<: *custom_image @@ -167,8 +155,6 @@ services: required: true volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network configurator: <<: *custom_image @@ -197,8 +183,6 @@ services: REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}" volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network create-site: <<: *custom_image @@ -237,8 +221,6 @@ services: DB_PORT: "${DB_PORT:-3306}" DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} INSTALL_APP_ARGS: ${INSTALL_APP_ARGS} - networks: - - bench-network migration: <<: *custom_image @@ -258,8 +240,6 @@ services: bench --site all set-config -p pause_scheduler 0; volumes: - sites:/home/frappe/frappe-bench/sites - networks: - - bench-network db: image: mariadb:10.6 @@ -282,8 +262,6 @@ services: - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} volumes: - db-data:/var/lib/mysql - networks: - - bench-network redis-cache: deploy: @@ -292,8 +270,6 @@ services: image: redis:6.2-alpine volumes: - redis-cache-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -310,8 +286,6 @@ services: image: redis:6.2-alpine volumes: - redis-queue-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -328,8 +302,6 @@ services: image: redis:6.2-alpine volumes: - redis-socketio-data:/data - networks: - - bench-network healthcheck: test: - CMD @@ -349,6 +321,3 @@ volumes: type: "${SITE_VOLUME_TYPE}" o: "${SITE_VOLUME_OPTS}" device: "${SITE_VOLUME_DEV}" - -networks: - bench-network: diff --git a/blueprints/lodestone/docker-compose.yml b/blueprints/lodestone/docker-compose.yml index 42f5d8dc9..00cfc1133 100644 --- a/blueprints/lodestone/docker-compose.yml +++ b/blueprints/lodestone/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — Lodestone hosts game servers (Minecraft et al.) on 25565-25590 (raw TCP) and the dashboard talks to the core agent on 16662 directly by server address; neither is routable through Traefik. version: '3.8' services: diff --git a/blueprints/mailpit/docker-compose.yml b/blueprints/mailpit/docker-compose.yml index d83b62d81..ef26770e3 100644 --- a/blueprints/mailpit/docker-compose.yml +++ b/blueprints/mailpit/docker-compose.yml @@ -2,8 +2,8 @@ services: mailpit: image: axllent/mailpit:v1.22.3 restart: unless-stopped - ports: - - '1025:1025' + expose: + - 1025 # SMTP — other services reach it over the internal Docker network (mailpit:1025) volumes: - 'mailpit-data:/data' environment: diff --git a/blueprints/mailu/docker-compose.yml b/blueprints/mailu/docker-compose.yml index 3b644361e..baa1423df 100644 --- a/blueprints/mailu/docker-compose.yml +++ b/blueprints/mailu/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — mail protocols (SMTP 25, SMTPS 465, Submission 587, IMAPS 993) are not HTTP; mail servers and clients must reach them directly on the host. version: "3.8" # Shared Mailu configuration (equivalent to the upstream mailu.env file) diff --git a/blueprints/oryx/docker-compose.yml b/blueprints/oryx/docker-compose.yml index 98d460ff3..0fed0c3ec 100644 --- a/blueprints/oryx/docker-compose.yml +++ b/blueprints/oryx/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — RTMP (1935/tcp), WebRTC (8000/udp) and SRT (10080/udp) are streaming protocols Traefik cannot route; they must be published on the host. version: "3.8" services: oryx: diff --git a/blueprints/poste.io/docker-compose.yml b/blueprints/poste.io/docker-compose.yml index ad99b8884..9121ea44d 100644 --- a/blueprints/poste.io/docker-compose.yml +++ b/blueprints/poste.io/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — mail protocols (SMTP 25/465/587, POP3 110/995, IMAP 143/993, Sieve 4190) are not HTTP; mail servers and clients must reach them directly on the host. version: "3.8" services: mailserver: diff --git a/blueprints/pre0.22.5-supabase/docker-compose.yml b/blueprints/pre0.22.5-supabase/docker-compose.yml index ee16e34ee..e1934ff89 100644 --- a/blueprints/pre0.22.5-supabase/docker-compose.yml +++ b/blueprints/pre0.22.5-supabase/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-container-names — frozen legacy template (pre-Dokploy 0.22.5). Supabase functionally depends on container names: Kong routes Realtime via its container DNS name and Vector derives log routing from container names. The ${CONTAINER_PREFIX} per-deploy hash prevents name collisions. # Usage # Start: docker compose up # With helpers: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml up diff --git a/blueprints/pterodactyl/docker-compose.yml b/blueprints/pterodactyl/docker-compose.yml index 639988182..c75a88a47 100644 --- a/blueprints/pterodactyl/docker-compose.yml +++ b/blueprints/pterodactyl/docker-compose.yml @@ -38,12 +38,6 @@ services: MYSQL_ROOT_PASSWORD: DB_CONNECTION: "mysql" -networks: - default: - ipam: - config: - - subnet: 172.20.0.0/16 - volumes: pterodb: pterovar: diff --git a/blueprints/qbittorrent/docker-compose.yml b/blueprints/qbittorrent/docker-compose.yml index 38e2fdec4..ca019b55f 100644 --- a/blueprints/qbittorrent/docker-compose.yml +++ b/blueprints/qbittorrent/docker-compose.yml @@ -1,5 +1,6 @@ +# dokploy: allow-host-ports — BitTorrent peer connections (6881 TCP/UDP) must reach the host directly; the peering protocol is not HTTP, so Traefik cannot route it. # docker-compose.yml -# +# # IMPORTANT: First-time setup information # - Default username: admin # - Password: Check container logs for temporary password on first startup diff --git a/blueprints/seafile/docker-compose.yml b/blueprints/seafile/docker-compose.yml index 74636b625..d503f50b9 100644 --- a/blueprints/seafile/docker-compose.yml +++ b/blueprints/seafile/docker-compose.yml @@ -20,8 +20,6 @@ services: - MARIADB_AUTO_UPGRADE=1 volumes: - seafile-mysql-db:/var/lib/mysql" - networks: - - seafile-net healthcheck: test: [ @@ -39,8 +37,6 @@ services: memcached: image: memcached:1.6.29 entrypoint: memcached -m 256 - networks: - - seafile-net healthcheck: test: [ @@ -78,18 +74,12 @@ services: condition: service_healthy memcached: condition: service_started - networks: - - seafile-net healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:80/api2/ping"] interval: 20s timeout: 5s retries: 10 -networks: - seafile-net: - name: seafile-net - volumes: seafile-mysql-db: seafile-data: diff --git a/blueprints/triggerdotdev/docker-compose.yml b/blueprints/triggerdotdev/docker-compose.yml index c8cee8504..4c2709ec7 100644 --- a/blueprints/triggerdotdev/docker-compose.yml +++ b/blueprints/triggerdotdev/docker-compose.yml @@ -14,9 +14,6 @@ volumes: postgres-data: redis-data: -networks: - webapp: - services: webapp: image: ghcr.io/triggerdotdev/trigger.dev:${TRIGGER_IMAGE_TAG:-v3} @@ -30,8 +27,6 @@ services: depends_on: - postgres - redis - networks: - - webapp postgres: image: postgres:${POSTGRES_IMAGE_TAG:-16} @@ -40,8 +35,6 @@ services: - postgres-data:/var/lib/postgresql/data/ env_file: - .env - networks: - - webapp expose: - 5432 command: @@ -53,8 +46,6 @@ services: restart: ${RESTART_POLICY:-unless-stopped} volumes: - redis-data:/data - networks: - - webapp expose: - 6379 docker-provider: @@ -63,8 +54,6 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock user: root - networks: - - webapp depends_on: - webapp expose: @@ -81,8 +70,6 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock user: root - networks: - - webapp depends_on: - webapp expose: @@ -98,8 +85,6 @@ services: restart: ${RESTART_POLICY:-unless-stopped} environment: DATABASE_URL: ${DATABASE_URL}?sslmode=disable - networks: - - webapp depends_on: - postgres expose: diff --git a/blueprints/unifi/docker-compose.yml b/blueprints/unifi/docker-compose.yml index 7a44dff57..1081554c8 100644 --- a/blueprints/unifi/docker-compose.yml +++ b/blueprints/unifi/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — the UniFi controller serves its portal over HTTPS with a self-signed certificate on 8443 and this template defines no Traefik domain; users and UniFi devices reach the controller directly on the host. services: unifi-network-application: image: lscr.io/linuxserver/unifi-network-application:latest diff --git a/blueprints/wg-easy/docker-compose.yml b/blueprints/wg-easy/docker-compose.yml index 0a98f6d93..e5adcc042 100644 --- a/blueprints/wg-easy/docker-compose.yml +++ b/blueprints/wg-easy/docker-compose.yml @@ -1,3 +1,4 @@ +# dokploy: allow-host-ports — WireGuard VPN traffic is raw UDP on 51820; Traefik cannot route it, so the port must be published on the host. volumes: etc_wireguard: @@ -12,13 +13,13 @@ services: - INIT_DNS=1.1.1.1,8.8.8.8 - PORT=51821 image: ghcr.io/wg-easy/wg-easy:15 - container_name: wg-easy volumes: - etc_wireguard:/etc/wireguard - /lib/modules:/lib/modules:ro ports: - "51820:51820/udp" - - "51821:51821/tcp" + expose: + - 51821 # web UI — routed through Traefik via the template domain restart: unless-stopped cap_add: - NET_ADMIN diff --git a/build-scripts/validate-docker-compose.ts b/build-scripts/validate-docker-compose.ts index 2132c7bb8..e3fd2ef37 100644 --- a/build-scripts/validate-docker-compose.ts +++ b/build-scripts/validate-docker-compose.ts @@ -26,6 +26,7 @@ type LogLevel = "info" | "success" | "warning" | "error" | "debug"; class DockerComposeValidator { private allowHostPorts = false; + private allowContainerNames = false; private options: Required; private errors: string[] = []; private warnings: string[] = []; @@ -77,6 +78,11 @@ class DockerComposeValidator { // Opt-out marker for templates whose protocols require host-published ports // (mail/SMTP, game servers, streaming, VPN, remote-desktop relays...). this.allowHostPorts = /^#\s*dokploy:\s*allow-host-ports\b/m.test(content); + // Opt-out marker for templates that functionally depend on container_name + // (e.g. legacy Supabase: Kong routes Realtime via its container DNS name and + // Vector derives log routing from container names). Only use it when the + // names are deployment-unique (e.g. include a per-deploy hash/prefix). + this.allowContainerNames = /^#\s*dokploy:\s*allow-container-names\b/m.test(content); const compose = yaml.parse(content) as ComposeSpecification; if (!compose || typeof compose !== "object") { @@ -107,9 +113,15 @@ class DockerComposeValidator { private validateNoContainerName(services: Record): void { Object.entries(services).forEach(([serviceName, service]) => { if (service.container_name) { - this.error( - `Service '${serviceName}': Found 'container_name' field. According to README, container_name should not be used. Dokploy manages container names automatically.` - ); + if (this.allowContainerNames) { + this.warning( + `Service '${serviceName}': uses 'container_name' (allowed by '# dokploy: allow-container-names' marker)` + ); + } else { + this.error( + `Service '${serviceName}': Found 'container_name' field. According to README, container_name should not be used. Dokploy manages container names automatically.` + ); + } } }); }