{"id":10280,"date":"2026-08-15T01:13:32","date_gmt":"2026-08-14T23:13:32","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/toolbox\/traefik-label-compose-generator\/"},"modified":"2026-08-15T01:13:32","modified_gmt":"2026-08-14T23:13:32","slug":"traefik-label-compose-generator","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/","title":{"rendered":"Traefik Label &#038; Compose Generator"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">Traefik is configured through labels, and a single wrong one is enough for the container to stay invisible or the password prompt to accept anything. This generator writes the whole block and points at the places where it usually goes wrong.<\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap;\">\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"tr-dienst\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Service name<\/label><br \/>\n            <input type=\"text\" id=\"tr-dienst\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"grafana\">\n        <\/div>\n<div style=\"flex: 2; min-width: 220px;\">\n            <label for=\"tr-host\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Domain<\/label><br \/>\n            <input type=\"text\" id=\"tr-host\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"grafana.example.com\">\n        <\/div>\n<div style=\"flex: 1; min-width: 130px;\">\n            <label for=\"tr-port\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Port inside the container<\/label><br \/>\n            <input type=\"text\" id=\"tr-port\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"3000\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"tr-netz\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Shared network<\/label><br \/>\n            <input type=\"text\" id=\"tr-netz\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"proxy\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;\">\n<div style=\"flex: 1; min-width: 180px;\">\n            <label for=\"tr-resolver\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Certificate resolver<\/label><br \/>\n            <input type=\"text\" id=\"tr-resolver\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"letsencrypt\">\n        <\/div>\n<div style=\"flex: 1; min-width: 180px;\">\n            <label for=\"tr-pfad\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Path prefix (optional)<\/label><br \/>\n            <input type=\"text\" id=\"tr-pfad\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" placeholder=\"\/metrics\">\n        <\/div>\n<div style=\"flex: 2; min-width: 240px;\">\n            <label for=\"tr-auth\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Basic auth, user:hash (optional)<\/label><br \/>\n            <input type=\"text\" id=\"tr-auth\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" placeholder=\"admin:$apr1$xyz$abc...\">\n        <\/div>\n<\/p><\/div>\n<div id=\"tr-optionen\" style=\"display: flex; flex-wrap: wrap; gap: 6px 24px; margin-top: 15px;\"><\/div>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 0;\">\n        <button id=\"tr-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Generate labels<\/button>\n    <\/div>\n<div id=\"tr-ergebnis\" style=\"margin-top: 22px;\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Traefik is configured through labels, and a single wrong one is enough for the container to stay invisible or the password prompt to accept anything. This generator writes the whole block and points at the places where it usually goes wrong.\",\"label_dienst\":\"Service name\",\"label_host\":\"Domain\",\"label_port\":\"Port inside the container\",\"label_netz\":\"Shared network\",\"label_resolver\":\"Certificate resolver\",\"label_pfad\":\"Path prefix (optional)\",\"label_auth\":\"Basic auth, user:hash (optional)\",\"o_weiterleitung\":\"Redirect http to https\",\"o_kompression\":\"Compression\",\"o_kopfzeilen\":\"Security headers\",\"o_ratenbremse\":\"Rate limit\",\"knopf\":\"Generate labels\",\"fehler_dienst\":\"The service name is missing.\",\"fehler_dienst_zeichen\":\"The service name may only hold lowercase letters, digits, dash and underscore.\",\"fehler_host\":\"The domain is missing.\",\"fehler_host_form\":\"That is not a valid domain.\",\"fehler_port\":\"The port has to be a number between 1 and 65535.\",\"fehler_pfad\":\"The path prefix has to start with a slash.\",\"h_compose\":\"Service in docker-compose.yml\",\"h_befunde\":\"What to watch out for\",\"b_dollar\":\"Every dollar sign in the hash is doubled above. Compose reads a single one as a variable and replaces it with nothing, which breaks the hash without a word - the prompt then accepts nothing at all.\",\"b_kein_hash\":\"The entry carries no dollar sign, so it is probably a plaintext password rather than a hash from htpasswd.\",\"b_ohne_doppelpunkt\":\"The entry has no colon. The form is user:hash.\",\"b_ohne_tls\":\"No certificate resolver: the router listens on the secure entry point without a certificate, and nothing gets through.\",\"b_resolver\":\"The resolver %s has to exist in the static configuration of Traefik. The labels only reference it, they do not create it.\",\"b_ohne_weiterleitung\":\"Without the redirect the service answers only on https. A call over http runs into nothing, which looks like an outage.\",\"b_ohne_kopfzeilen\":\"Without the header middleware the service answers without HSTS and without frame protection.\",\"b_netz\":\"The container and Traefik have to sit on the network %s. Traefik reads the labels of every container, but it can only reach the ones it shares a network with.\",\"b_port\":\"The port label refers to the port inside the container, not to a published one. Publishing it as well opens the service past the proxy.\",\"b_enable\":\"traefik.enable=true is only needed when Traefik runs with exposedByDefault=false, which is the setting worth having.\"};<\/p>\n<p>    \/\/ --- reine Rechenlogik ---<\/p>\n<p>    const OPTIONEN = ['weiterleitung', 'kompression', 'kopfzeilen', 'ratenbremse'];<\/p>\n<p>    function text(wert) { return String(wert === undefined || wert === null ? '' : wert).trim(); }<\/p>\n<p>    function bauen(e) {\n        const ergebnis = { ok: false, fehler: '', etiketten: [], compose: '', befunde: [] };\n        const eingabe = e || {};<\/p>\n<p>        const dienst = text(eingabe.dienst);\n        const host = text(eingabe.host);\n        const port = text(eingabe.port);\n        const netz = text(eingabe.netz) || 'proxy';\n        const resolver = text(eingabe.resolver);\n        const pfad = text(eingabe.pfad);\n        const auth = text(eingabe.auth);<\/p>\n<p>        if (dienst === '') { ergebnis.fehler = T.fehler_dienst; return ergebnis; }\n        if (!\/^[a-z0-9][a-z0-9_-]*$\/.test(dienst)) { ergebnis.fehler = T.fehler_dienst_zeichen; return ergebnis; }\n        if (host === '') { ergebnis.fehler = T.fehler_host; return ergebnis; }\n        if (!\/^[a-z0-9.-]+\\.[a-z]{2,}$\/i.test(host)) { ergebnis.fehler = T.fehler_host_form; return ergebnis; }\n        if (!\/^[0-9]+$\/.test(port) || parseInt(port, 10) < 1 || parseInt(port, 10) > 65535) { ergebnis.fehler = T.fehler_port; return ergebnis; }\n        if (pfad !== '' && pfad.charAt(0) !== '\/') { ergebnis.fehler = T.fehler_pfad; return ergebnis; }<\/p>\n<p>        const regel = 'Host(`' + host + '`)' + (pfad !== '' ? ' && PathPrefix(`' + pfad + '`)' : '');\n        const mittel = [];\n        const etiketten = [];<\/p>\n<p>        etiketten.push('traefik.enable=true');\n        etiketten.push('traefik.docker.network=' + netz);\n        etiketten.push('traefik.http.routers.' + dienst + '.rule=' + regel);\n        etiketten.push('traefik.http.routers.' + dienst + '.entrypoints=websecure');\n        etiketten.push('traefik.http.services.' + dienst + '.loadbalancer.server.port=' + port);<\/p>\n<p>        if (resolver !== '') {\n            etiketten.push('traefik.http.routers.' + dienst + '.tls=true');\n            etiketten.push('traefik.http.routers.' + dienst + '.tls.certresolver=' + resolver);\n        }<\/p>\n<p>        if (eingabe.weiterleitung) {\n            etiketten.push('traefik.http.routers.' + dienst + '-web.rule=' + regel);\n            etiketten.push('traefik.http.routers.' + dienst + '-web.entrypoints=web');\n            etiketten.push('traefik.http.routers.' + dienst + '-web.middlewares=' + dienst + '-nach-https');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-nach-https.redirectscheme.scheme=https');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-nach-https.redirectscheme.permanent=true');\n        }\n        if (eingabe.kompression) {\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kompression.compress=true');\n            mittel.push(dienst + '-kompression');\n        }\n        if (eingabe.kopfzeilen) {\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kopfzeilen.headers.stsSeconds=31536000');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kopfzeilen.headers.stsIncludeSubdomains=true');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kopfzeilen.headers.contentTypeNosniff=true');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kopfzeilen.headers.frameDeny=true');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-kopfzeilen.headers.referrerPolicy=strict-origin-when-cross-origin');\n            mittel.push(dienst + '-kopfzeilen');\n        }\n        if (eingabe.ratenbremse) {\n            etiketten.push('traefik.http.middlewares.' + dienst + '-bremse.ratelimit.average=50');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-bremse.ratelimit.burst=100');\n            mittel.push(dienst + '-bremse');\n        }\n        if (auth !== '') {\n            \/\/ In einer compose-Datei muss jedes Dollarzeichen verdoppelt\n            \/\/ werden, sonst h\u00e4lt compose es f\u00fcr eine Variable und ersetzt es\n            \/\/ durch nichts - der Hash ist dann still kaputt.\n            const geschuetzt = auth.replace(\/\\$\/g, '$$$$');\n            etiketten.push('traefik.http.middlewares.' + dienst + '-auth.basicauth.users=' + geschuetzt);\n            mittel.push(dienst + '-auth');\n        }\n        if (mittel.length) {\n            etiketten.push('traefik.http.routers.' + dienst + '.middlewares=' + mittel.join(','));\n        }<\/p>\n<p>        ergebnis.etiketten = etiketten;<\/p>\n<p>        const zeilen = [];\n        zeilen.push('services:');\n        zeilen.push('  ' + dienst + ':');\n        zeilen.push('    image: ' + dienst + ':latest');\n        zeilen.push('    container_name: ' + dienst);\n        zeilen.push('    restart: unless-stopped');\n        zeilen.push('    networks:');\n        zeilen.push('      - ' + netz);\n        zeilen.push('    labels:');\n        etiketten.forEach(function (l) { zeilen.push('      - \"' + l + '\"'); });\n        zeilen.push('');\n        zeilen.push('networks:');\n        zeilen.push('  ' + netz + ':');\n        zeilen.push('    external: true');\n        ergebnis.compose = zeilen.join('\\n');<\/p>\n<p>        \/\/ --- Befunde ---\n        if (auth !== '') {\n            ergebnis.befunde.push({ schwer: true, text: T.b_dollar });\n            if (auth.indexOf('$') === -1) {\n                ergebnis.befunde.push({ schwer: true, text: T.b_kein_hash });\n            }\n            if (auth.indexOf(':') === -1) {\n                ergebnis.befunde.push({ schwer: true, text: T.b_ohne_doppelpunkt });\n            }\n        }\n        if (resolver === '') {\n            ergebnis.befunde.push({ schwer: true, text: T.b_ohne_tls });\n        } else {\n            ergebnis.befunde.push({ schwer: false, text: T.b_resolver.replace('%s', resolver) });\n        }\n        if (!eingabe.weiterleitung) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_ohne_weiterleitung });\n        }\n        if (!eingabe.kopfzeilen) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_ohne_kopfzeilen });\n        }\n        ergebnis.befunde.push({ schwer: false, text: T.b_netz.replace('%s', netz) });\n        ergebnis.befunde.push({ schwer: false, text: T.b_port });\n        ergebnis.befunde.push({ schwer: false, text: T.b_enable });<\/p>\n<p>        ergebnis.ok = true;\n        return ergebnis;\n    }<\/p>\n<p>    if (typeof window !== 'undefined') {\n        window.LW_TEST = window.LW_TEST || {};\n        window.LW_TEST.TR = { bauen: bauen, OPTIONEN: OPTIONEN };\n    }<\/p>\n<p>    \/\/ --- Anbindung an das Dokument ---<\/p>\n<p>    const btn = document.getElementById('tr-btn');\n    const out = document.getElementById('tr-ergebnis');\n    const optionenFeld = document.getElementById('tr-optionen');\n    if (!btn || !out || !optionenFeld) { return; }<\/p>\n<p>    const KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 14px; margin-bottom: 18px;';\n    const UEBERSCHRIFT = 'color: var(--text-primary, #e8e8ee); font-weight: 700; margin-bottom: 8px;';<\/p>\n<p>    function el(tag, css, inhalt) {\n        const knoten = document.createElement(tag);\n        if (css) { knoten.setAttribute('style', css); }\n        if (inhalt !== undefined && inhalt !== null) { knoten.textContent = inhalt; }\n        return knoten;\n    }<\/p>\n<p>    function wert(id) {\n        const knoten = document.getElementById(id);\n        return knoten ? knoten.value : '';\n    }<\/p>\n<p>    OPTIONEN.forEach(function (name) {\n        const zeile = el('label', 'display: flex; gap: 8px; align-items: center; cursor: pointer; min-width: 210px;');\n        const kasten = document.createElement('input');\n        kasten.type = 'checkbox';\n        kasten.id = 'tr-o-' + name;\n        kasten.checked = name === 'weiterleitung' || name === 'kopfzeilen';\n        zeile.appendChild(kasten);\n        zeile.appendChild(el('span', 'color: var(--text-primary, #e8e8ee); font-size: 0.88rem;', T['o_' + name]));\n        optionenFeld.appendChild(zeile);\n    });<\/p>\n<p>    btn.addEventListener('click', function () {\n        const eingabe = {\n            dienst: wert('tr-dienst'), host: wert('tr-host'), port: wert('tr-port'),\n            netz: wert('tr-netz'), resolver: wert('tr-resolver'), pfad: wert('tr-pfad'), auth: wert('tr-auth')\n        };\n        OPTIONEN.forEach(function (name) {\n            const knoten = document.getElementById('tr-o-' + name);\n            eingabe[name] = knoten ? knoten.checked : false;\n        });<\/p>\n<p>        const erg = bauen(eingabe);\n        out.textContent = '';\n        if (!erg.ok) {\n            out.appendChild(el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid #ffb86c; color: var(--text-secondary, #a0a0b0); padding: 14px; border-radius: 6px;', erg.fehler));\n            return;\n        }<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_compose));\n        out.appendChild(el('pre', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); padding: 16px; border-radius: 6px; overflow-x: auto; font-family: monospace; font-size: 0.78rem; line-height: 1.5; white-space: pre; margin-bottom: 18px;', erg.compose));<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        const befunde = el('div', KASTEN);\n        erg.befunde.forEach(function (b) {\n            const z = el('div', 'display: flex; gap: 10px; padding: 5px 0;');\n            z.appendChild(el('span', 'color: ' + (b.schwer ? '#ffb86c' : 'var(--text-secondary, #a0a0b0)') + '; font-family: monospace;', b.schwer ? '!' : '-'));\n            z.appendChild(el('span', 'color: var(--text-secondary, #a0a0b0); font-size: 0.9rem; line-height: 1.5;', b.text));\n            befunde.appendChild(z);\n        });\n        out.appendChild(befunde);\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Writes the Traefik labels for a container &#8211; router, service, TLS and middlewares &#8211; and names the pitfalls that leave a service unreachable or unprotected.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[91145,91237,91115],"class_list":["post-10280","page","type-page","status-publish","hentry","tag-docker","tag-self-hosting","tag-web-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Traefik Label &amp; Compose Generator - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Traefik Label &amp; Compose Generator - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Writes the Traefik labels for a container - router, service, TLS and middlewares - and names the pitfalls that leave a service unreachable or unprotected.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/traefik-label-compose-generator\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/traefik-label-compose-generator\\\/\",\"name\":\"Traefik Label & Compose Generator - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-14T23:13:32+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/traefik-label-compose-generator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/traefik-label-compose-generator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/traefik-label-compose-generator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Traefik Label &#038; Compose Generator\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Traefik Label & Compose Generator - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/","og_locale":"en_US","og_type":"article","og_title":"Traefik Label & Compose Generator - Lukas Wojcik - Blog","og_description":"Writes the Traefik labels for a container - router, service, TLS and middlewares - and names the pitfalls that leave a service unreachable or unprotected.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/","og_site_name":"Lukas Wojcik - Blog","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/","name":"Traefik Label & Compose Generator - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-14T23:13:32+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/traefik-label-compose-generator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"Traefik Label &#038; Compose Generator"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=10280"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10280\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=10280"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=10280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}