[{"data":1,"prerenderedAt":5313},["ShallowReactive",2],{"blog-current-shopware-plugin-gitlab-pipeline-test-de":3,"blog-previous-shopware-plugin-gitlab-pipeline-test-de":2448,"blog-next-shopware-plugin-gitlab-pipeline-test-de":2459,"blog-alt-de-shopware-plugin-gitlab-pipeline-test-de":2470,"blog-alt-en-shopware-plugin-gitlab-pipeline-test-de":2471,"employee-robert-juzak":2473,"related-refs-shopware_devops--de":2571,"content-query-TVldk4ROTj":2621,"content-query-w8qtEh68yX":4117,"content-query-KtO3wftRle":5278},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"author":10,"image":11,"releaseDate":12,"blogCategories":13,"articleTags":16,"tags":19,"body":22,"_type":2442,"_id":2443,"_source":2444,"_file":2445,"_stem":2446,"_extension":2447},"/blog/shopware-plugin-gitlab-pipeline-test","blog",false,"","Testen, Bauen und Veröffentlichen eines Shopware 6 Plugins mit GitLab CI - Teil 3: Testen","Teil 3: Testen - Verwendung von GitLab zum Testen, Bauen und Veröffentlichen eines Shopware 6 Plugins","robert-juzak","/images/dev-ops-dark.svg","2026-02-26",[14,15],"Was uns bewegt","DevOps",[15,17,18],"Open Source","Shopware",[20,21],"shopware","devops",{"type":23,"children":24,"toc":2433},"root",[25,34,41,95,102,116,129,182,195,203,215,222,227,536,541,546,551,556,569,574,599,605,617,1441,1446,1474,1479,1485,1490,2427],{"type":26,"tag":27,"props":28,"children":33},"element","img",{"alt":7,"aspect-ratio":29,"height":30,"object-fit":31,"src":32},"1.78",300,"fill","/blog/shopware-plugin-test.png",[],{"type":26,"tag":35,"props":36,"children":37},"p",{},[38],{"type":39,"value":40},"text","Wenn es um das Testen eines Shopware 6 Plugins geht, gibt es zwei Arten von Tests, die durchgeführt werden können:",{"type":26,"tag":42,"props":43,"children":44},"ol",{},[45,83],{"type":26,"tag":46,"props":47,"children":48},"li",{},[49,51,58,60],{"type":39,"value":50},"Testen des Codes selbst (",{"type":26,"tag":52,"props":53,"children":55},"a",{"href":54},"https://developer.shopware.com/docs/guides/plugins/plugins/testing/",[56],{"type":39,"value":57},"mehr in der offiziellen Dokumentation",{"type":39,"value":59},")\n",{"type":26,"tag":42,"props":61,"children":62},{},[63,68,73,78],{"type":26,"tag":46,"props":64,"children":65},{},[66],{"type":39,"value":67},"PHP-Unit-Tests",{"type":26,"tag":46,"props":69,"children":70},{},[71],{"type":39,"value":72},"Jest-Unit-Tests in Shopwares Storefront",{"type":26,"tag":46,"props":74,"children":75},{},[76],{"type":39,"value":77},"Jest-Unit-Tests in Shopwares Administration",{"type":26,"tag":46,"props":79,"children":80},{},[81],{"type":39,"value":82},"End-to-End (E2E) Testing",{"type":26,"tag":46,"props":84,"children":85},{},[86,88,93],{"type":39,"value":87},"Sicherstellen einer hohen Code-Qualität (",{"type":26,"tag":52,"props":89,"children":91},{"href":90},"https://developer.shopware.com/docs/products/cli/validation.html",[92],{"type":39,"value":57},{"type":39,"value":94},")",{"type":26,"tag":96,"props":97,"children":99},"h2",{"id":98},"code-qualität",[100],{"type":39,"value":101},"Code-Qualität",{"type":26,"tag":35,"props":103,"children":104},{},[105,107,114],{"type":39,"value":106},"Fangen wir mit der Code-Qualität an, da es einfacher ist, diese außerhalb einer ",{"type":26,"tag":108,"props":109,"children":111},"code",{"className":110},[],[112],{"type":39,"value":113},"CI/CD",{"type":39,"value":115},"-Umgebung auszuführen.",{"type":26,"tag":35,"props":117,"children":118},{},[119,121,127],{"type":39,"value":120},"Wir werden wieder das ",{"type":26,"tag":108,"props":122,"children":124},{"className":123},[],[125],{"type":39,"value":126},"shopware-cli",{"type":39,"value":128}," verwenden.",{"type":26,"tag":130,"props":131,"children":135},"pre",{"code":132,"language":133,"meta":7,"className":134,"style":7},"shopware-cli extension validate --full --reporter summary .\n","shell","language-shell shiki shiki-themes github-dark github-dark monokai",[136],{"type":26,"tag":108,"props":137,"children":138},{"__ignoreMap":7},[139],{"type":26,"tag":140,"props":141,"children":144},"span",{"class":142,"line":143},"line",1,[145,150,156,161,167,172,177],{"type":26,"tag":140,"props":146,"children":148},{"style":147},"--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E",[149],{"type":39,"value":126},{"type":26,"tag":140,"props":151,"children":153},{"style":152},"--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74",[154],{"type":39,"value":155}," extension",{"type":26,"tag":140,"props":157,"children":158},{"style":152},[159],{"type":39,"value":160}," validate",{"type":26,"tag":140,"props":162,"children":164},{"style":163},"--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF",[165],{"type":39,"value":166}," --full",{"type":26,"tag":140,"props":168,"children":169},{"style":163},[170],{"type":39,"value":171}," --reporter",{"type":26,"tag":140,"props":173,"children":174},{"style":152},[175],{"type":39,"value":176}," summary",{"type":26,"tag":140,"props":178,"children":179},{"style":152},[180],{"type":39,"value":181}," .\n",{"type":26,"tag":35,"props":183,"children":184},{},[185,187,193],{"type":39,"value":186},"Dies wird alle Tests ausführen, die ",{"type":26,"tag":52,"props":188,"children":190},{"href":189},"https://developer.shopware.com/docs/products/cli/validation.html#running-all-validation-tools",[191],{"type":39,"value":192},"hier",{"type":39,"value":194}," beschrieben sind,\nund hoffentlich eine Ausgabe wie diese erzeugen:",{"type":26,"tag":130,"props":196,"children":198},{"code":197},"✖ 0 problems (0 errors, 0 warnings)\n",[199],{"type":26,"tag":108,"props":200,"children":201},{"__ignoreMap":7},[202],{"type":39,"value":197},{"type":26,"tag":35,"props":204,"children":205},{},[206,208,213],{"type":39,"value":207},"Falls Fehler auftreten, schaue in der Shopware-Dokumentation nach, wie diese zu beheben sind, und führe nur die fehlgeschlagenen Tests erneut aus, wie ",{"type":26,"tag":52,"props":209,"children":211},{"href":210},"https://developer.shopware.com/docs/products/cli/validation.html#running-specific-tools",[212],{"type":39,"value":192},{"type":39,"value":214}," beschrieben.",{"type":26,"tag":216,"props":217,"children":219},"h3",{"id":218},"code-qualität-pipeline",[220],{"type":39,"value":221},"Code-Qualität Pipeline",{"type":26,"tag":35,"props":223,"children":224},{},[225],{"type":39,"value":226},"Nun werden wir das Ganze in GitLab ausführen.",{"type":26,"tag":130,"props":228,"children":240},{"code":229,"filename":230,"highlights":231,"language":238,"meta":7,"className":239,"style":7},"stages:\n  - test\n\ncode-quality:\n   image:\n      name: ghcr.io/shopware/shopware-cli:latest-php-8.2\n      entrypoint: [\"\"]\n   stage: test\n   script:\n      - shopware-cli extension validate --full . | tee report.json\n   artifacts:\n      reports:\n         codequality: report.json\n   rules:\n      - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n        when: never\n      - if: $CI_COMMIT_BRANCH\n","\u003Cplugin-root>/.gitlab-ci.yml",[232,233,234,235,236,237],6,14,15,16,17,18,"yaml","language-yaml shiki shiki-themes github-dark github-dark monokai",[241],{"type":26,"tag":108,"props":242,"children":243},{"__ignoreMap":7},[244,259,273,283,296,309,329,353,370,383,397,410,423,441,454,476,497,515],{"type":26,"tag":140,"props":245,"children":246},{"class":142,"line":143},[247,253],{"type":26,"tag":140,"props":248,"children":250},{"style":249},"--shiki-default:#85E89D;--shiki-dark:#85E89D;--shiki-sepia:#F92672",[251],{"type":39,"value":252},"stages",{"type":26,"tag":140,"props":254,"children":256},{"style":255},"--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2",[257],{"type":39,"value":258},":\n",{"type":26,"tag":140,"props":260,"children":262},{"class":142,"line":261},2,[263,268],{"type":26,"tag":140,"props":264,"children":265},{"style":255},[266],{"type":39,"value":267},"  - ",{"type":26,"tag":140,"props":269,"children":270},{"style":152},[271],{"type":39,"value":272},"test\n",{"type":26,"tag":140,"props":274,"children":276},{"class":142,"line":275},3,[277],{"type":26,"tag":140,"props":278,"children":280},{"emptyLinePlaceholder":279},true,[281],{"type":39,"value":282},"\n",{"type":26,"tag":140,"props":284,"children":286},{"class":142,"line":285},4,[287,292],{"type":26,"tag":140,"props":288,"children":289},{"style":249},[290],{"type":39,"value":291},"code-quality",{"type":26,"tag":140,"props":293,"children":294},{"style":255},[295],{"type":39,"value":258},{"type":26,"tag":140,"props":297,"children":299},{"class":142,"line":298},5,[300,305],{"type":26,"tag":140,"props":301,"children":302},{"style":249},[303],{"type":39,"value":304},"   image",{"type":26,"tag":140,"props":306,"children":307},{"style":255},[308],{"type":39,"value":258},{"type":26,"tag":140,"props":310,"children":313},{"class":311,"line":232},[142,312],"highlight",[314,319,324],{"type":26,"tag":140,"props":315,"children":316},{"style":249},[317],{"type":39,"value":318},"      name",{"type":26,"tag":140,"props":320,"children":321},{"style":255},[322],{"type":39,"value":323},": ",{"type":26,"tag":140,"props":325,"children":326},{"style":152},[327],{"type":39,"value":328},"ghcr.io/shopware/shopware-cli:latest-php-8.2\n",{"type":26,"tag":140,"props":330,"children":332},{"class":142,"line":331},7,[333,338,343,348],{"type":26,"tag":140,"props":334,"children":335},{"style":249},[336],{"type":39,"value":337},"      entrypoint",{"type":26,"tag":140,"props":339,"children":340},{"style":255},[341],{"type":39,"value":342},": [",{"type":26,"tag":140,"props":344,"children":345},{"style":152},[346],{"type":39,"value":347},"\"\"",{"type":26,"tag":140,"props":349,"children":350},{"style":255},[351],{"type":39,"value":352},"]\n",{"type":26,"tag":140,"props":354,"children":356},{"class":142,"line":355},8,[357,362,366],{"type":26,"tag":140,"props":358,"children":359},{"style":249},[360],{"type":39,"value":361},"   stage",{"type":26,"tag":140,"props":363,"children":364},{"style":255},[365],{"type":39,"value":323},{"type":26,"tag":140,"props":367,"children":368},{"style":152},[369],{"type":39,"value":272},{"type":26,"tag":140,"props":371,"children":373},{"class":142,"line":372},9,[374,379],{"type":26,"tag":140,"props":375,"children":376},{"style":249},[377],{"type":39,"value":378},"   script",{"type":26,"tag":140,"props":380,"children":381},{"style":255},[382],{"type":39,"value":258},{"type":26,"tag":140,"props":384,"children":386},{"class":142,"line":385},10,[387,392],{"type":26,"tag":140,"props":388,"children":389},{"style":255},[390],{"type":39,"value":391},"      - ",{"type":26,"tag":140,"props":393,"children":394},{"style":152},[395],{"type":39,"value":396},"shopware-cli extension validate --full . | tee report.json\n",{"type":26,"tag":140,"props":398,"children":400},{"class":142,"line":399},11,[401,406],{"type":26,"tag":140,"props":402,"children":403},{"style":249},[404],{"type":39,"value":405},"   artifacts",{"type":26,"tag":140,"props":407,"children":408},{"style":255},[409],{"type":39,"value":258},{"type":26,"tag":140,"props":411,"children":413},{"class":142,"line":412},12,[414,419],{"type":26,"tag":140,"props":415,"children":416},{"style":249},[417],{"type":39,"value":418},"      reports",{"type":26,"tag":140,"props":420,"children":421},{"style":255},[422],{"type":39,"value":258},{"type":26,"tag":140,"props":424,"children":426},{"class":142,"line":425},13,[427,432,436],{"type":26,"tag":140,"props":428,"children":429},{"style":249},[430],{"type":39,"value":431},"         codequality",{"type":26,"tag":140,"props":433,"children":434},{"style":255},[435],{"type":39,"value":323},{"type":26,"tag":140,"props":437,"children":438},{"style":152},[439],{"type":39,"value":440},"report.json\n",{"type":26,"tag":140,"props":442,"children":444},{"class":443,"line":233},[142,312],[445,450],{"type":26,"tag":140,"props":446,"children":447},{"style":249},[448],{"type":39,"value":449},"   rules",{"type":26,"tag":140,"props":451,"children":452},{"style":255},[453],{"type":39,"value":258},{"type":26,"tag":140,"props":455,"children":457},{"class":456,"line":234},[142,312],[458,462,467,471],{"type":26,"tag":140,"props":459,"children":460},{"style":255},[461],{"type":39,"value":391},{"type":26,"tag":140,"props":463,"children":464},{"style":249},[465],{"type":39,"value":466},"if",{"type":26,"tag":140,"props":468,"children":469},{"style":255},[470],{"type":39,"value":323},{"type":26,"tag":140,"props":472,"children":473},{"style":152},[474],{"type":39,"value":475},"$CI_PIPELINE_SOURCE == \"merge_request_event\"\n",{"type":26,"tag":140,"props":477,"children":479},{"class":478,"line":235},[142,312],[480,484,488,492],{"type":26,"tag":140,"props":481,"children":482},{"style":255},[483],{"type":39,"value":391},{"type":26,"tag":140,"props":485,"children":486},{"style":249},[487],{"type":39,"value":466},{"type":26,"tag":140,"props":489,"children":490},{"style":255},[491],{"type":39,"value":323},{"type":26,"tag":140,"props":493,"children":494},{"style":152},[495],{"type":39,"value":496},"$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n",{"type":26,"tag":140,"props":498,"children":500},{"class":499,"line":236},[142,312],[501,506,510],{"type":26,"tag":140,"props":502,"children":503},{"style":249},[504],{"type":39,"value":505},"        when",{"type":26,"tag":140,"props":507,"children":508},{"style":255},[509],{"type":39,"value":323},{"type":26,"tag":140,"props":511,"children":512},{"style":152},[513],{"type":39,"value":514},"never\n",{"type":26,"tag":140,"props":516,"children":518},{"class":517,"line":237},[142,312],[519,523,527,531],{"type":26,"tag":140,"props":520,"children":521},{"style":255},[522],{"type":39,"value":391},{"type":26,"tag":140,"props":524,"children":525},{"style":249},[526],{"type":39,"value":466},{"type":26,"tag":140,"props":528,"children":529},{"style":255},[530],{"type":39,"value":323},{"type":26,"tag":140,"props":532,"children":533},{"style":152},[534],{"type":39,"value":535},"$CI_COMMIT_BRANCH\n",{"type":26,"tag":35,"props":537,"children":538},{},[539],{"type":39,"value":540},"Diese Pipeline wird auf dem Standard-Branch und bei Merge-Request-Pipelines ausgeführt.",{"type":26,"tag":35,"props":542,"children":543},{},[544],{"type":39,"value":545},"Das Ausführen auf dem Standard-Branch vor dem Bauen und Veröffentlichen verhindert, dass versehentlich ein Release mit geringer Qualität erstellt wird.",{"type":26,"tag":35,"props":547,"children":548},{},[549],{"type":39,"value":550},"Ein nettes Extra für die MR-Pipeline ist die Integration des Code-Quality-Reports!",{"type":26,"tag":96,"props":552,"children":554},{"id":553},"php-unit-tests",[555],{"type":39,"value":67},{"type":26,"tag":35,"props":557,"children":558},{},[559,561,567],{"type":39,"value":560},"Zuerst müssen wir PHPUnit konfigurieren, indem wir der ",{"type":26,"tag":52,"props":562,"children":564},{"href":563},"https://developer.shopware.com/docs/guides/plugins/plugins/testing/php-unit.html",[565],{"type":39,"value":566},"offiziellen Shopware-Dokumentation",{"type":39,"value":568}," folgen.",{"type":26,"tag":35,"props":570,"children":571},{},[572],{"type":39,"value":573},"Wir werden uns hier nicht auf diesen Prozess konzentrieren. Wenn alles eingerichtet ist, sollten wir in der Lage sein, unseren Test wie folgt im Root-Verzeichnis unseres Shopware-Projekts auszuführen:",{"type":26,"tag":130,"props":575,"children":577},{"code":576,"language":133,"meta":7,"className":134,"style":7},"./vendor/bin/phpunit --configuration=\"custom/static-plugins/SwagBasicExample\"\n",[578],{"type":26,"tag":108,"props":579,"children":580},{"__ignoreMap":7},[581],{"type":26,"tag":140,"props":582,"children":583},{"class":142,"line":143},[584,589,594],{"type":26,"tag":140,"props":585,"children":586},{"style":147},[587],{"type":39,"value":588},"./vendor/bin/phpunit",{"type":26,"tag":140,"props":590,"children":591},{"style":163},[592],{"type":39,"value":593}," --configuration=",{"type":26,"tag":140,"props":595,"children":596},{"style":152},[597],{"type":39,"value":598},"\"custom/static-plugins/SwagBasicExample\"\n",{"type":26,"tag":216,"props":600,"children":602},{"id":601},"phpunit-pipeline",[603],{"type":39,"value":604},"PHPUnit Pipeline",{"type":26,"tag":35,"props":606,"children":607},{},[608,610,615],{"type":39,"value":609},"Das Ausführen von PHPUnit für ein Plugin erfordert eine vollständige Shopware-Instanz. Glücklicherweise kann uns das ",{"type":26,"tag":108,"props":611,"children":613},{"className":612},[],[614],{"type":39,"value":126},{"type":39,"value":616}," dabei helfen.",{"type":26,"tag":130,"props":618,"children":636},{"code":619,"filename":230,"highlights":620,"language":238,"meta":7,"className":239,"style":7},"stages:\n   - test\n\nphpunit:\n  stage: test\n  image:\n    name: ghcr.io/shopware/shopware-cli:latest-php-8.2\n    entrypoint: [\"\"]\n  services:\n    - name: mysql:8.3.0\n      alias: test_database\n      variables:\n        MYSQL_SKIP_TEST_DB: 'yes'\n        MYSQL_ALLOW_EMPTY_PASSWORD: yes\n  variables:\n    GIT_STRATEGY: none\n    SHOPWARE_ROOT: ${CI_PROJECT_DIR}/shopware\n    SHOPWARE_VERSION: 6.6.10.13\n    \n    APP_SECRET: def00000bb5acb32b54ff8ee130270586eec0e878f7337dc7a837acc31d3ff00f93a56b595448b4b29664847dd51991b3314ff65aeeeb761a133b0ec0e070433bff08e48\n    MESSENGER_TRANSPORT_DSN: sync://\n    DATABASE_URL: mysql://root@test_database/shopware\n    COMPOSER_CACHE_DIR: ${CI_PROJECT_DIR}/.composer\n\n    XDEBUG_MODE: coverage\n  before_script:\n    - apk add --no-cache php-8.2-xdebug\n    - shopware-cli project create shopware ${SHOPWARE_VERSION}\n    - cd $SHOPWARE_ROOT\n    - composer req --dev shopware/dev-tools phpunit/phpunit\n    - git clone \"https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\" \"custom/plugins/${CI_PROJECT_NAME}\"\n    - cd custom/plugins/${CI_PROJECT_NAME}\n    - git checkout ${CI_COMMIT_SHA}\n    - cd ${SHOPWARE_ROOT}\n    - composer require $(composer -d custom/plugins/${CI_PROJECT_NAME} config name)\n    - cd custom/plugins/${CI_PROJECT_NAME}\n  script:\n    - ${SHOPWARE_ROOT}/vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml\n\n  cache:\n    - key: $CI_JOB_NAME\n      paths:\n        - $COMPOSER_CACHE_DIR\n  coverage: /^\\s*Lines:\\s*\\d+.\\d+\\%/\n  artifacts:\n    reports:\n      coverage_report:\n        coverage_format: cobertura\n        path: coverage.cobertura.xml\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: never\n    - if: $CI_COMMIT_BRANCH\n",[372,385,399,412,425,233,235,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635],20,21,22,23,27,28,29,30,31,32,33,34,35,36,38,[637],{"type":26,"tag":108,"props":638,"children":639},{"__ignoreMap":7},[640,651,663,670,682,698,710,726,746,759,782,800,813,831,849,861,879,896,913,922,940,958,976,994,1002,1020,1033,1046,1059,1072,1085,1098,1111,1124,1137,1150,1162,1175,1188,1196,1209,1231,1244,1258,1276,1289,1302,1315,1333,1351,1364,1384,1404,1421],{"type":26,"tag":140,"props":641,"children":642},{"class":142,"line":143},[643,647],{"type":26,"tag":140,"props":644,"children":645},{"style":249},[646],{"type":39,"value":252},{"type":26,"tag":140,"props":648,"children":649},{"style":255},[650],{"type":39,"value":258},{"type":26,"tag":140,"props":652,"children":653},{"class":142,"line":261},[654,659],{"type":26,"tag":140,"props":655,"children":656},{"style":255},[657],{"type":39,"value":658},"   - ",{"type":26,"tag":140,"props":660,"children":661},{"style":152},[662],{"type":39,"value":272},{"type":26,"tag":140,"props":664,"children":665},{"class":142,"line":275},[666],{"type":26,"tag":140,"props":667,"children":668},{"emptyLinePlaceholder":279},[669],{"type":39,"value":282},{"type":26,"tag":140,"props":671,"children":672},{"class":142,"line":285},[673,678],{"type":26,"tag":140,"props":674,"children":675},{"style":249},[676],{"type":39,"value":677},"phpunit",{"type":26,"tag":140,"props":679,"children":680},{"style":255},[681],{"type":39,"value":258},{"type":26,"tag":140,"props":683,"children":684},{"class":142,"line":298},[685,690,694],{"type":26,"tag":140,"props":686,"children":687},{"style":249},[688],{"type":39,"value":689},"  stage",{"type":26,"tag":140,"props":691,"children":692},{"style":255},[693],{"type":39,"value":323},{"type":26,"tag":140,"props":695,"children":696},{"style":152},[697],{"type":39,"value":272},{"type":26,"tag":140,"props":699,"children":700},{"class":142,"line":232},[701,706],{"type":26,"tag":140,"props":702,"children":703},{"style":249},[704],{"type":39,"value":705},"  image",{"type":26,"tag":140,"props":707,"children":708},{"style":255},[709],{"type":39,"value":258},{"type":26,"tag":140,"props":711,"children":712},{"class":142,"line":331},[713,718,722],{"type":26,"tag":140,"props":714,"children":715},{"style":249},[716],{"type":39,"value":717},"    name",{"type":26,"tag":140,"props":719,"children":720},{"style":255},[721],{"type":39,"value":323},{"type":26,"tag":140,"props":723,"children":724},{"style":152},[725],{"type":39,"value":328},{"type":26,"tag":140,"props":727,"children":728},{"class":142,"line":355},[729,734,738,742],{"type":26,"tag":140,"props":730,"children":731},{"style":249},[732],{"type":39,"value":733},"    entrypoint",{"type":26,"tag":140,"props":735,"children":736},{"style":255},[737],{"type":39,"value":342},{"type":26,"tag":140,"props":739,"children":740},{"style":152},[741],{"type":39,"value":347},{"type":26,"tag":140,"props":743,"children":744},{"style":255},[745],{"type":39,"value":352},{"type":26,"tag":140,"props":747,"children":749},{"class":748,"line":372},[142,312],[750,755],{"type":26,"tag":140,"props":751,"children":752},{"style":249},[753],{"type":39,"value":754},"  services",{"type":26,"tag":140,"props":756,"children":757},{"style":255},[758],{"type":39,"value":258},{"type":26,"tag":140,"props":760,"children":762},{"class":761,"line":385},[142,312],[763,768,773,777],{"type":26,"tag":140,"props":764,"children":765},{"style":255},[766],{"type":39,"value":767},"    - ",{"type":26,"tag":140,"props":769,"children":770},{"style":249},[771],{"type":39,"value":772},"name",{"type":26,"tag":140,"props":774,"children":775},{"style":255},[776],{"type":39,"value":323},{"type":26,"tag":140,"props":778,"children":779},{"style":152},[780],{"type":39,"value":781},"mysql:8.3.0\n",{"type":26,"tag":140,"props":783,"children":785},{"class":784,"line":399},[142,312],[786,791,795],{"type":26,"tag":140,"props":787,"children":788},{"style":249},[789],{"type":39,"value":790},"      alias",{"type":26,"tag":140,"props":792,"children":793},{"style":255},[794],{"type":39,"value":323},{"type":26,"tag":140,"props":796,"children":797},{"style":152},[798],{"type":39,"value":799},"test_database\n",{"type":26,"tag":140,"props":801,"children":803},{"class":802,"line":412},[142,312],[804,809],{"type":26,"tag":140,"props":805,"children":806},{"style":249},[807],{"type":39,"value":808},"      variables",{"type":26,"tag":140,"props":810,"children":811},{"style":255},[812],{"type":39,"value":258},{"type":26,"tag":140,"props":814,"children":816},{"class":815,"line":425},[142,312],[817,822,826],{"type":26,"tag":140,"props":818,"children":819},{"style":249},[820],{"type":39,"value":821},"        MYSQL_SKIP_TEST_DB",{"type":26,"tag":140,"props":823,"children":824},{"style":255},[825],{"type":39,"value":323},{"type":26,"tag":140,"props":827,"children":828},{"style":152},[829],{"type":39,"value":830},"'yes'\n",{"type":26,"tag":140,"props":832,"children":834},{"class":833,"line":233},[142,312],[835,840,844],{"type":26,"tag":140,"props":836,"children":837},{"style":249},[838],{"type":39,"value":839},"        MYSQL_ALLOW_EMPTY_PASSWORD",{"type":26,"tag":140,"props":841,"children":842},{"style":255},[843],{"type":39,"value":323},{"type":26,"tag":140,"props":845,"children":846},{"style":163},[847],{"type":39,"value":848},"yes\n",{"type":26,"tag":140,"props":850,"children":851},{"class":142,"line":234},[852,857],{"type":26,"tag":140,"props":853,"children":854},{"style":249},[855],{"type":39,"value":856},"  variables",{"type":26,"tag":140,"props":858,"children":859},{"style":255},[860],{"type":39,"value":258},{"type":26,"tag":140,"props":862,"children":864},{"class":863,"line":235},[142,312],[865,870,874],{"type":26,"tag":140,"props":866,"children":867},{"style":249},[868],{"type":39,"value":869},"    GIT_STRATEGY",{"type":26,"tag":140,"props":871,"children":872},{"style":255},[873],{"type":39,"value":323},{"type":26,"tag":140,"props":875,"children":876},{"style":152},[877],{"type":39,"value":878},"none\n",{"type":26,"tag":140,"props":880,"children":881},{"class":142,"line":236},[882,887,891],{"type":26,"tag":140,"props":883,"children":884},{"style":249},[885],{"type":39,"value":886},"    SHOPWARE_ROOT",{"type":26,"tag":140,"props":888,"children":889},{"style":255},[890],{"type":39,"value":323},{"type":26,"tag":140,"props":892,"children":893},{"style":152},[894],{"type":39,"value":895},"${CI_PROJECT_DIR}/shopware\n",{"type":26,"tag":140,"props":897,"children":898},{"class":142,"line":237},[899,904,908],{"type":26,"tag":140,"props":900,"children":901},{"style":249},[902],{"type":39,"value":903},"    SHOPWARE_VERSION",{"type":26,"tag":140,"props":905,"children":906},{"style":255},[907],{"type":39,"value":323},{"type":26,"tag":140,"props":909,"children":910},{"style":163},[911],{"type":39,"value":912},"6.6.10.13\n",{"type":26,"tag":140,"props":914,"children":916},{"class":142,"line":915},19,[917],{"type":26,"tag":140,"props":918,"children":919},{"style":255},[920],{"type":39,"value":921},"    \n",{"type":26,"tag":140,"props":923,"children":925},{"class":924,"line":621},[142,312],[926,931,935],{"type":26,"tag":140,"props":927,"children":928},{"style":249},[929],{"type":39,"value":930},"    APP_SECRET",{"type":26,"tag":140,"props":932,"children":933},{"style":255},[934],{"type":39,"value":323},{"type":26,"tag":140,"props":936,"children":937},{"style":152},[938],{"type":39,"value":939},"def00000bb5acb32b54ff8ee130270586eec0e878f7337dc7a837acc31d3ff00f93a56b595448b4b29664847dd51991b3314ff65aeeeb761a133b0ec0e070433bff08e48\n",{"type":26,"tag":140,"props":941,"children":943},{"class":942,"line":622},[142,312],[944,949,953],{"type":26,"tag":140,"props":945,"children":946},{"style":249},[947],{"type":39,"value":948},"    MESSENGER_TRANSPORT_DSN",{"type":26,"tag":140,"props":950,"children":951},{"style":255},[952],{"type":39,"value":323},{"type":26,"tag":140,"props":954,"children":955},{"style":152},[956],{"type":39,"value":957},"sync://\n",{"type":26,"tag":140,"props":959,"children":961},{"class":960,"line":623},[142,312],[962,967,971],{"type":26,"tag":140,"props":963,"children":964},{"style":249},[965],{"type":39,"value":966},"    DATABASE_URL",{"type":26,"tag":140,"props":968,"children":969},{"style":255},[970],{"type":39,"value":323},{"type":26,"tag":140,"props":972,"children":973},{"style":152},[974],{"type":39,"value":975},"mysql://root@test_database/shopware\n",{"type":26,"tag":140,"props":977,"children":979},{"class":978,"line":624},[142,312],[980,985,989],{"type":26,"tag":140,"props":981,"children":982},{"style":249},[983],{"type":39,"value":984},"    COMPOSER_CACHE_DIR",{"type":26,"tag":140,"props":986,"children":987},{"style":255},[988],{"type":39,"value":323},{"type":26,"tag":140,"props":990,"children":991},{"style":152},[992],{"type":39,"value":993},"${CI_PROJECT_DIR}/.composer\n",{"type":26,"tag":140,"props":995,"children":997},{"class":142,"line":996},24,[998],{"type":26,"tag":140,"props":999,"children":1000},{"emptyLinePlaceholder":279},[1001],{"type":39,"value":282},{"type":26,"tag":140,"props":1003,"children":1005},{"class":142,"line":1004},25,[1006,1011,1015],{"type":26,"tag":140,"props":1007,"children":1008},{"style":249},[1009],{"type":39,"value":1010},"    XDEBUG_MODE",{"type":26,"tag":140,"props":1012,"children":1013},{"style":255},[1014],{"type":39,"value":323},{"type":26,"tag":140,"props":1016,"children":1017},{"style":152},[1018],{"type":39,"value":1019},"coverage\n",{"type":26,"tag":140,"props":1021,"children":1023},{"class":142,"line":1022},26,[1024,1029],{"type":26,"tag":140,"props":1025,"children":1026},{"style":249},[1027],{"type":39,"value":1028},"  before_script",{"type":26,"tag":140,"props":1030,"children":1031},{"style":255},[1032],{"type":39,"value":258},{"type":26,"tag":140,"props":1034,"children":1036},{"class":1035,"line":625},[142,312],[1037,1041],{"type":26,"tag":140,"props":1038,"children":1039},{"style":255},[1040],{"type":39,"value":767},{"type":26,"tag":140,"props":1042,"children":1043},{"style":152},[1044],{"type":39,"value":1045},"apk add --no-cache php-8.2-xdebug\n",{"type":26,"tag":140,"props":1047,"children":1049},{"class":1048,"line":626},[142,312],[1050,1054],{"type":26,"tag":140,"props":1051,"children":1052},{"style":255},[1053],{"type":39,"value":767},{"type":26,"tag":140,"props":1055,"children":1056},{"style":152},[1057],{"type":39,"value":1058},"shopware-cli project create shopware ${SHOPWARE_VERSION}\n",{"type":26,"tag":140,"props":1060,"children":1062},{"class":1061,"line":627},[142,312],[1063,1067],{"type":26,"tag":140,"props":1064,"children":1065},{"style":255},[1066],{"type":39,"value":767},{"type":26,"tag":140,"props":1068,"children":1069},{"style":152},[1070],{"type":39,"value":1071},"cd $SHOPWARE_ROOT\n",{"type":26,"tag":140,"props":1073,"children":1075},{"class":1074,"line":628},[142,312],[1076,1080],{"type":26,"tag":140,"props":1077,"children":1078},{"style":255},[1079],{"type":39,"value":767},{"type":26,"tag":140,"props":1081,"children":1082},{"style":152},[1083],{"type":39,"value":1084},"composer req --dev shopware/dev-tools phpunit/phpunit\n",{"type":26,"tag":140,"props":1086,"children":1088},{"class":1087,"line":629},[142,312],[1089,1093],{"type":26,"tag":140,"props":1090,"children":1091},{"style":255},[1092],{"type":39,"value":767},{"type":26,"tag":140,"props":1094,"children":1095},{"style":152},[1096],{"type":39,"value":1097},"git clone \"https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\" \"custom/plugins/${CI_PROJECT_NAME}\"\n",{"type":26,"tag":140,"props":1099,"children":1101},{"class":1100,"line":630},[142,312],[1102,1106],{"type":26,"tag":140,"props":1103,"children":1104},{"style":255},[1105],{"type":39,"value":767},{"type":26,"tag":140,"props":1107,"children":1108},{"style":152},[1109],{"type":39,"value":1110},"cd custom/plugins/${CI_PROJECT_NAME}\n",{"type":26,"tag":140,"props":1112,"children":1114},{"class":1113,"line":631},[142,312],[1115,1119],{"type":26,"tag":140,"props":1116,"children":1117},{"style":255},[1118],{"type":39,"value":767},{"type":26,"tag":140,"props":1120,"children":1121},{"style":152},[1122],{"type":39,"value":1123},"git checkout ${CI_COMMIT_SHA}\n",{"type":26,"tag":140,"props":1125,"children":1127},{"class":1126,"line":632},[142,312],[1128,1132],{"type":26,"tag":140,"props":1129,"children":1130},{"style":255},[1131],{"type":39,"value":767},{"type":26,"tag":140,"props":1133,"children":1134},{"style":152},[1135],{"type":39,"value":1136},"cd ${SHOPWARE_ROOT}\n",{"type":26,"tag":140,"props":1138,"children":1140},{"class":1139,"line":633},[142,312],[1141,1145],{"type":26,"tag":140,"props":1142,"children":1143},{"style":255},[1144],{"type":39,"value":767},{"type":26,"tag":140,"props":1146,"children":1147},{"style":152},[1148],{"type":39,"value":1149},"composer require $(composer -d custom/plugins/${CI_PROJECT_NAME} config name)\n",{"type":26,"tag":140,"props":1151,"children":1153},{"class":1152,"line":634},[142,312],[1154,1158],{"type":26,"tag":140,"props":1155,"children":1156},{"style":255},[1157],{"type":39,"value":767},{"type":26,"tag":140,"props":1159,"children":1160},{"style":152},[1161],{"type":39,"value":1110},{"type":26,"tag":140,"props":1163,"children":1165},{"class":142,"line":1164},37,[1166,1171],{"type":26,"tag":140,"props":1167,"children":1168},{"style":249},[1169],{"type":39,"value":1170},"  script",{"type":26,"tag":140,"props":1172,"children":1173},{"style":255},[1174],{"type":39,"value":258},{"type":26,"tag":140,"props":1176,"children":1178},{"class":1177,"line":635},[142,312],[1179,1183],{"type":26,"tag":140,"props":1180,"children":1181},{"style":255},[1182],{"type":39,"value":767},{"type":26,"tag":140,"props":1184,"children":1185},{"style":152},[1186],{"type":39,"value":1187},"${SHOPWARE_ROOT}/vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml\n",{"type":26,"tag":140,"props":1189,"children":1191},{"class":142,"line":1190},39,[1192],{"type":26,"tag":140,"props":1193,"children":1194},{"emptyLinePlaceholder":279},[1195],{"type":39,"value":282},{"type":26,"tag":140,"props":1197,"children":1199},{"class":142,"line":1198},40,[1200,1205],{"type":26,"tag":140,"props":1201,"children":1202},{"style":249},[1203],{"type":39,"value":1204},"  cache",{"type":26,"tag":140,"props":1206,"children":1207},{"style":255},[1208],{"type":39,"value":258},{"type":26,"tag":140,"props":1210,"children":1212},{"class":142,"line":1211},41,[1213,1217,1222,1226],{"type":26,"tag":140,"props":1214,"children":1215},{"style":255},[1216],{"type":39,"value":767},{"type":26,"tag":140,"props":1218,"children":1219},{"style":249},[1220],{"type":39,"value":1221},"key",{"type":26,"tag":140,"props":1223,"children":1224},{"style":255},[1225],{"type":39,"value":323},{"type":26,"tag":140,"props":1227,"children":1228},{"style":152},[1229],{"type":39,"value":1230},"$CI_JOB_NAME\n",{"type":26,"tag":140,"props":1232,"children":1234},{"class":142,"line":1233},42,[1235,1240],{"type":26,"tag":140,"props":1236,"children":1237},{"style":249},[1238],{"type":39,"value":1239},"      paths",{"type":26,"tag":140,"props":1241,"children":1242},{"style":255},[1243],{"type":39,"value":258},{"type":26,"tag":140,"props":1245,"children":1247},{"class":142,"line":1246},43,[1248,1253],{"type":26,"tag":140,"props":1249,"children":1250},{"style":255},[1251],{"type":39,"value":1252},"        - ",{"type":26,"tag":140,"props":1254,"children":1255},{"style":152},[1256],{"type":39,"value":1257},"$COMPOSER_CACHE_DIR\n",{"type":26,"tag":140,"props":1259,"children":1261},{"class":142,"line":1260},44,[1262,1267,1271],{"type":26,"tag":140,"props":1263,"children":1264},{"style":249},[1265],{"type":39,"value":1266},"  coverage",{"type":26,"tag":140,"props":1268,"children":1269},{"style":255},[1270],{"type":39,"value":323},{"type":26,"tag":140,"props":1272,"children":1273},{"style":152},[1274],{"type":39,"value":1275},"/^\\s*Lines:\\s*\\d+.\\d+\\%/\n",{"type":26,"tag":140,"props":1277,"children":1279},{"class":142,"line":1278},45,[1280,1285],{"type":26,"tag":140,"props":1281,"children":1282},{"style":249},[1283],{"type":39,"value":1284},"  artifacts",{"type":26,"tag":140,"props":1286,"children":1287},{"style":255},[1288],{"type":39,"value":258},{"type":26,"tag":140,"props":1290,"children":1292},{"class":142,"line":1291},46,[1293,1298],{"type":26,"tag":140,"props":1294,"children":1295},{"style":249},[1296],{"type":39,"value":1297},"    reports",{"type":26,"tag":140,"props":1299,"children":1300},{"style":255},[1301],{"type":39,"value":258},{"type":26,"tag":140,"props":1303,"children":1305},{"class":142,"line":1304},47,[1306,1311],{"type":26,"tag":140,"props":1307,"children":1308},{"style":249},[1309],{"type":39,"value":1310},"      coverage_report",{"type":26,"tag":140,"props":1312,"children":1313},{"style":255},[1314],{"type":39,"value":258},{"type":26,"tag":140,"props":1316,"children":1318},{"class":142,"line":1317},48,[1319,1324,1328],{"type":26,"tag":140,"props":1320,"children":1321},{"style":249},[1322],{"type":39,"value":1323},"        coverage_format",{"type":26,"tag":140,"props":1325,"children":1326},{"style":255},[1327],{"type":39,"value":323},{"type":26,"tag":140,"props":1329,"children":1330},{"style":152},[1331],{"type":39,"value":1332},"cobertura\n",{"type":26,"tag":140,"props":1334,"children":1336},{"class":142,"line":1335},49,[1337,1342,1346],{"type":26,"tag":140,"props":1338,"children":1339},{"style":249},[1340],{"type":39,"value":1341},"        path",{"type":26,"tag":140,"props":1343,"children":1344},{"style":255},[1345],{"type":39,"value":323},{"type":26,"tag":140,"props":1347,"children":1348},{"style":152},[1349],{"type":39,"value":1350},"coverage.cobertura.xml\n",{"type":26,"tag":140,"props":1352,"children":1354},{"class":142,"line":1353},50,[1355,1360],{"type":26,"tag":140,"props":1356,"children":1357},{"style":249},[1358],{"type":39,"value":1359},"  rules",{"type":26,"tag":140,"props":1361,"children":1362},{"style":255},[1363],{"type":39,"value":258},{"type":26,"tag":140,"props":1365,"children":1367},{"class":142,"line":1366},51,[1368,1372,1376,1380],{"type":26,"tag":140,"props":1369,"children":1370},{"style":255},[1371],{"type":39,"value":767},{"type":26,"tag":140,"props":1373,"children":1374},{"style":249},[1375],{"type":39,"value":466},{"type":26,"tag":140,"props":1377,"children":1378},{"style":255},[1379],{"type":39,"value":323},{"type":26,"tag":140,"props":1381,"children":1382},{"style":152},[1383],{"type":39,"value":475},{"type":26,"tag":140,"props":1385,"children":1387},{"class":142,"line":1386},52,[1388,1392,1396,1400],{"type":26,"tag":140,"props":1389,"children":1390},{"style":255},[1391],{"type":39,"value":767},{"type":26,"tag":140,"props":1393,"children":1394},{"style":249},[1395],{"type":39,"value":466},{"type":26,"tag":140,"props":1397,"children":1398},{"style":255},[1399],{"type":39,"value":323},{"type":26,"tag":140,"props":1401,"children":1402},{"style":152},[1403],{"type":39,"value":496},{"type":26,"tag":140,"props":1405,"children":1407},{"class":142,"line":1406},53,[1408,1413,1417],{"type":26,"tag":140,"props":1409,"children":1410},{"style":249},[1411],{"type":39,"value":1412},"      when",{"type":26,"tag":140,"props":1414,"children":1415},{"style":255},[1416],{"type":39,"value":323},{"type":26,"tag":140,"props":1418,"children":1419},{"style":152},[1420],{"type":39,"value":514},{"type":26,"tag":140,"props":1422,"children":1424},{"class":142,"line":1423},54,[1425,1429,1433,1437],{"type":26,"tag":140,"props":1426,"children":1427},{"style":255},[1428],{"type":39,"value":767},{"type":26,"tag":140,"props":1430,"children":1431},{"style":249},[1432],{"type":39,"value":466},{"type":26,"tag":140,"props":1434,"children":1435},{"style":255},[1436],{"type":39,"value":323},{"type":26,"tag":140,"props":1438,"children":1439},{"style":152},[1440],{"type":39,"value":535},{"type":26,"tag":35,"props":1442,"children":1443},{},[1444],{"type":39,"value":1445},"Lass uns das ein wenig erklären:",{"type":26,"tag":42,"props":1447,"children":1448},{},[1449,1454,1459,1464,1469],{"type":26,"tag":46,"props":1450,"children":1451},{},[1452],{"type":39,"value":1453},"Wir deaktivieren das automatische Klonen des Repositories (16)",{"type":26,"tag":46,"props":1455,"children":1456},{},[1457],{"type":39,"value":1458},"Wir binden einen Datenbank-Service ein (9-14)",{"type":26,"tag":46,"props":1460,"children":1461},{},[1462],{"type":39,"value":1463},"Wir setzen einige erforderliche Shopware-Umgebungsvariablen (20-23)",{"type":26,"tag":46,"props":1465,"children":1466},{},[1467],{"type":39,"value":1468},"Erstellen ein leeres Shopware-Projekt mit PHPUnit und Xdebug (27-36)",{"type":26,"tag":46,"props":1470,"children":1471},{},[1472],{"type":39,"value":1473},"Führen PHPUnit mit Code-Coverage-Generierung als Text und im Cobertura-Format aus (38)",{"type":26,"tag":35,"props":1475,"children":1476},{},[1477],{"type":39,"value":1478},"Wie die Code-Quality-Pipeline nutzt auch diese die Vorteile des GitLab-Coverage-Reportings voll aus.",{"type":26,"tag":96,"props":1480,"children":1482},{"id":1481},"alles-zusammenfügen",[1483],{"type":39,"value":1484},"Alles zusammenfügen",{"type":26,"tag":35,"props":1486,"children":1487},{},[1488],{"type":39,"value":1489},"Für diesen Teil lassen wir den Build- und Release-Teil weg.",{"type":26,"tag":130,"props":1491,"children":1493},{"code":1492,"filename":230,"language":238,"meta":7,"className":239,"style":7},"stages:\n   - test\n\nphpunit:\n  stage: test\n  image:\n    name: ghcr.io/shopware/shopware-cli:latest-php-8.2\n    entrypoint: [\"\"]\n  services:\n    - name: mysql:8.3.0\n      alias: test_database\n      variables:\n        MYSQL_SKIP_TEST_DB: 'yes'\n        MYSQL_ALLOW_EMPTY_PASSWORD: yes\n  variables:\n    GIT_STRATEGY: none\n    SHOPWARE_ROOT: ${CI_PROJECT_DIR}/shopware\n    SHOPWARE_VERSION: 6.6.10.13\n    \n    APP_SECRET: def00000bb5acb32b54ff8ee130270586eec0e878f7337dc7a837acc31d3ff00f93a56b595448b4b29664847dd51991b3314ff65aeeeb761a133b0ec0e070433bff08e48\n    MESSENGER_TRANSPORT_DSN: sync://\n    DATABASE_URL: mysql://root@test_database/shopware\n    COMPOSER_CACHE_DIR: ${CI_PROJECT_DIR}/.composer\n\n    XDEBUG_MODE: coverage\n  before_script:\n    - apk add --no-cache php-8.2-xdebug\n    - shopware-cli project create shopware ${SHOPWARE_VERSION}\n    - cd $SHOPWARE_ROOT\n    - composer req --dev shopware/dev-tools phpunit/phpunit\n    - git clone \"https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\" \"custom/plugins/${CI_PROJECT_NAME}\"\n    - cd custom/plugins/${CI_PROJECT_NAME}\n    - git checkout ${CI_COMMIT_SHA}\n    - cd ${SHOPWARE_ROOT}\n    - composer require $(composer -d custom/plugins/${CI_PROJECT_NAME} config name)\n    - cd custom/plugins/${CI_PROJECT_NAME}\n  script:\n    - ${SHOPWARE_ROOT}/vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml\n\n  cache:\n    - key: $CI_JOB_NAME\n      paths:\n        - $COMPOSER_CACHE_DIR\n  coverage: /^\\s*Lines:\\s*\\d+.\\d+\\%/\n  artifacts:\n    reports:\n      coverage_report:\n        coverage_format: cobertura\n        path: coverage.cobertura.xml\n  rules:\n    - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: never\n    - if: $CI_COMMIT_BRANCH\n\ncode-quality:\n   image:\n      name: ghcr.io/shopware/shopware-cli:latest-php-8.2\n      entrypoint: [\"\"]\n   stage: test\n   script:\n      - shopware-cli extension validate --full . | tee report.json\n   artifacts:\n      reports:\n         codequality: report.json\n   rules:\n      - if: $CI_PIPELINE_SOURCE == \"merge_request_event\"\n      - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n        when: never\n      - if: $CI_COMMIT_BRANCH\n",[1494],{"type":26,"tag":108,"props":1495,"children":1496},{"__ignoreMap":7},[1497,1508,1519,1526,1537,1552,1563,1578,1597,1608,1627,1642,1653,1668,1683,1694,1709,1724,1739,1746,1761,1776,1791,1806,1813,1828,1839,1850,1861,1872,1883,1894,1905,1916,1927,1938,1949,1960,1971,1978,1989,2008,2019,2030,2045,2056,2067,2078,2093,2108,2119,2138,2157,2172,2191,2199,2211,2223,2239,2259,2275,2287,2299,2311,2323,2339,2351,2371,2391,2407],{"type":26,"tag":140,"props":1498,"children":1499},{"class":142,"line":143},[1500,1504],{"type":26,"tag":140,"props":1501,"children":1502},{"style":249},[1503],{"type":39,"value":252},{"type":26,"tag":140,"props":1505,"children":1506},{"style":255},[1507],{"type":39,"value":258},{"type":26,"tag":140,"props":1509,"children":1510},{"class":142,"line":261},[1511,1515],{"type":26,"tag":140,"props":1512,"children":1513},{"style":255},[1514],{"type":39,"value":658},{"type":26,"tag":140,"props":1516,"children":1517},{"style":152},[1518],{"type":39,"value":272},{"type":26,"tag":140,"props":1520,"children":1521},{"class":142,"line":275},[1522],{"type":26,"tag":140,"props":1523,"children":1524},{"emptyLinePlaceholder":279},[1525],{"type":39,"value":282},{"type":26,"tag":140,"props":1527,"children":1528},{"class":142,"line":285},[1529,1533],{"type":26,"tag":140,"props":1530,"children":1531},{"style":249},[1532],{"type":39,"value":677},{"type":26,"tag":140,"props":1534,"children":1535},{"style":255},[1536],{"type":39,"value":258},{"type":26,"tag":140,"props":1538,"children":1539},{"class":142,"line":298},[1540,1544,1548],{"type":26,"tag":140,"props":1541,"children":1542},{"style":249},[1543],{"type":39,"value":689},{"type":26,"tag":140,"props":1545,"children":1546},{"style":255},[1547],{"type":39,"value":323},{"type":26,"tag":140,"props":1549,"children":1550},{"style":152},[1551],{"type":39,"value":272},{"type":26,"tag":140,"props":1553,"children":1554},{"class":142,"line":232},[1555,1559],{"type":26,"tag":140,"props":1556,"children":1557},{"style":249},[1558],{"type":39,"value":705},{"type":26,"tag":140,"props":1560,"children":1561},{"style":255},[1562],{"type":39,"value":258},{"type":26,"tag":140,"props":1564,"children":1565},{"class":142,"line":331},[1566,1570,1574],{"type":26,"tag":140,"props":1567,"children":1568},{"style":249},[1569],{"type":39,"value":717},{"type":26,"tag":140,"props":1571,"children":1572},{"style":255},[1573],{"type":39,"value":323},{"type":26,"tag":140,"props":1575,"children":1576},{"style":152},[1577],{"type":39,"value":328},{"type":26,"tag":140,"props":1579,"children":1580},{"class":142,"line":355},[1581,1585,1589,1593],{"type":26,"tag":140,"props":1582,"children":1583},{"style":249},[1584],{"type":39,"value":733},{"type":26,"tag":140,"props":1586,"children":1587},{"style":255},[1588],{"type":39,"value":342},{"type":26,"tag":140,"props":1590,"children":1591},{"style":152},[1592],{"type":39,"value":347},{"type":26,"tag":140,"props":1594,"children":1595},{"style":255},[1596],{"type":39,"value":352},{"type":26,"tag":140,"props":1598,"children":1599},{"class":142,"line":372},[1600,1604],{"type":26,"tag":140,"props":1601,"children":1602},{"style":249},[1603],{"type":39,"value":754},{"type":26,"tag":140,"props":1605,"children":1606},{"style":255},[1607],{"type":39,"value":258},{"type":26,"tag":140,"props":1609,"children":1610},{"class":142,"line":385},[1611,1615,1619,1623],{"type":26,"tag":140,"props":1612,"children":1613},{"style":255},[1614],{"type":39,"value":767},{"type":26,"tag":140,"props":1616,"children":1617},{"style":249},[1618],{"type":39,"value":772},{"type":26,"tag":140,"props":1620,"children":1621},{"style":255},[1622],{"type":39,"value":323},{"type":26,"tag":140,"props":1624,"children":1625},{"style":152},[1626],{"type":39,"value":781},{"type":26,"tag":140,"props":1628,"children":1629},{"class":142,"line":399},[1630,1634,1638],{"type":26,"tag":140,"props":1631,"children":1632},{"style":249},[1633],{"type":39,"value":790},{"type":26,"tag":140,"props":1635,"children":1636},{"style":255},[1637],{"type":39,"value":323},{"type":26,"tag":140,"props":1639,"children":1640},{"style":152},[1641],{"type":39,"value":799},{"type":26,"tag":140,"props":1643,"children":1644},{"class":142,"line":412},[1645,1649],{"type":26,"tag":140,"props":1646,"children":1647},{"style":249},[1648],{"type":39,"value":808},{"type":26,"tag":140,"props":1650,"children":1651},{"style":255},[1652],{"type":39,"value":258},{"type":26,"tag":140,"props":1654,"children":1655},{"class":142,"line":425},[1656,1660,1664],{"type":26,"tag":140,"props":1657,"children":1658},{"style":249},[1659],{"type":39,"value":821},{"type":26,"tag":140,"props":1661,"children":1662},{"style":255},[1663],{"type":39,"value":323},{"type":26,"tag":140,"props":1665,"children":1666},{"style":152},[1667],{"type":39,"value":830},{"type":26,"tag":140,"props":1669,"children":1670},{"class":142,"line":233},[1671,1675,1679],{"type":26,"tag":140,"props":1672,"children":1673},{"style":249},[1674],{"type":39,"value":839},{"type":26,"tag":140,"props":1676,"children":1677},{"style":255},[1678],{"type":39,"value":323},{"type":26,"tag":140,"props":1680,"children":1681},{"style":163},[1682],{"type":39,"value":848},{"type":26,"tag":140,"props":1684,"children":1685},{"class":142,"line":234},[1686,1690],{"type":26,"tag":140,"props":1687,"children":1688},{"style":249},[1689],{"type":39,"value":856},{"type":26,"tag":140,"props":1691,"children":1692},{"style":255},[1693],{"type":39,"value":258},{"type":26,"tag":140,"props":1695,"children":1696},{"class":142,"line":235},[1697,1701,1705],{"type":26,"tag":140,"props":1698,"children":1699},{"style":249},[1700],{"type":39,"value":869},{"type":26,"tag":140,"props":1702,"children":1703},{"style":255},[1704],{"type":39,"value":323},{"type":26,"tag":140,"props":1706,"children":1707},{"style":152},[1708],{"type":39,"value":878},{"type":26,"tag":140,"props":1710,"children":1711},{"class":142,"line":236},[1712,1716,1720],{"type":26,"tag":140,"props":1713,"children":1714},{"style":249},[1715],{"type":39,"value":886},{"type":26,"tag":140,"props":1717,"children":1718},{"style":255},[1719],{"type":39,"value":323},{"type":26,"tag":140,"props":1721,"children":1722},{"style":152},[1723],{"type":39,"value":895},{"type":26,"tag":140,"props":1725,"children":1726},{"class":142,"line":237},[1727,1731,1735],{"type":26,"tag":140,"props":1728,"children":1729},{"style":249},[1730],{"type":39,"value":903},{"type":26,"tag":140,"props":1732,"children":1733},{"style":255},[1734],{"type":39,"value":323},{"type":26,"tag":140,"props":1736,"children":1737},{"style":163},[1738],{"type":39,"value":912},{"type":26,"tag":140,"props":1740,"children":1741},{"class":142,"line":915},[1742],{"type":26,"tag":140,"props":1743,"children":1744},{"style":255},[1745],{"type":39,"value":921},{"type":26,"tag":140,"props":1747,"children":1748},{"class":142,"line":621},[1749,1753,1757],{"type":26,"tag":140,"props":1750,"children":1751},{"style":249},[1752],{"type":39,"value":930},{"type":26,"tag":140,"props":1754,"children":1755},{"style":255},[1756],{"type":39,"value":323},{"type":26,"tag":140,"props":1758,"children":1759},{"style":152},[1760],{"type":39,"value":939},{"type":26,"tag":140,"props":1762,"children":1763},{"class":142,"line":622},[1764,1768,1772],{"type":26,"tag":140,"props":1765,"children":1766},{"style":249},[1767],{"type":39,"value":948},{"type":26,"tag":140,"props":1769,"children":1770},{"style":255},[1771],{"type":39,"value":323},{"type":26,"tag":140,"props":1773,"children":1774},{"style":152},[1775],{"type":39,"value":957},{"type":26,"tag":140,"props":1777,"children":1778},{"class":142,"line":623},[1779,1783,1787],{"type":26,"tag":140,"props":1780,"children":1781},{"style":249},[1782],{"type":39,"value":966},{"type":26,"tag":140,"props":1784,"children":1785},{"style":255},[1786],{"type":39,"value":323},{"type":26,"tag":140,"props":1788,"children":1789},{"style":152},[1790],{"type":39,"value":975},{"type":26,"tag":140,"props":1792,"children":1793},{"class":142,"line":624},[1794,1798,1802],{"type":26,"tag":140,"props":1795,"children":1796},{"style":249},[1797],{"type":39,"value":984},{"type":26,"tag":140,"props":1799,"children":1800},{"style":255},[1801],{"type":39,"value":323},{"type":26,"tag":140,"props":1803,"children":1804},{"style":152},[1805],{"type":39,"value":993},{"type":26,"tag":140,"props":1807,"children":1808},{"class":142,"line":996},[1809],{"type":26,"tag":140,"props":1810,"children":1811},{"emptyLinePlaceholder":279},[1812],{"type":39,"value":282},{"type":26,"tag":140,"props":1814,"children":1815},{"class":142,"line":1004},[1816,1820,1824],{"type":26,"tag":140,"props":1817,"children":1818},{"style":249},[1819],{"type":39,"value":1010},{"type":26,"tag":140,"props":1821,"children":1822},{"style":255},[1823],{"type":39,"value":323},{"type":26,"tag":140,"props":1825,"children":1826},{"style":152},[1827],{"type":39,"value":1019},{"type":26,"tag":140,"props":1829,"children":1830},{"class":142,"line":1022},[1831,1835],{"type":26,"tag":140,"props":1832,"children":1833},{"style":249},[1834],{"type":39,"value":1028},{"type":26,"tag":140,"props":1836,"children":1837},{"style":255},[1838],{"type":39,"value":258},{"type":26,"tag":140,"props":1840,"children":1841},{"class":142,"line":625},[1842,1846],{"type":26,"tag":140,"props":1843,"children":1844},{"style":255},[1845],{"type":39,"value":767},{"type":26,"tag":140,"props":1847,"children":1848},{"style":152},[1849],{"type":39,"value":1045},{"type":26,"tag":140,"props":1851,"children":1852},{"class":142,"line":626},[1853,1857],{"type":26,"tag":140,"props":1854,"children":1855},{"style":255},[1856],{"type":39,"value":767},{"type":26,"tag":140,"props":1858,"children":1859},{"style":152},[1860],{"type":39,"value":1058},{"type":26,"tag":140,"props":1862,"children":1863},{"class":142,"line":627},[1864,1868],{"type":26,"tag":140,"props":1865,"children":1866},{"style":255},[1867],{"type":39,"value":767},{"type":26,"tag":140,"props":1869,"children":1870},{"style":152},[1871],{"type":39,"value":1071},{"type":26,"tag":140,"props":1873,"children":1874},{"class":142,"line":628},[1875,1879],{"type":26,"tag":140,"props":1876,"children":1877},{"style":255},[1878],{"type":39,"value":767},{"type":26,"tag":140,"props":1880,"children":1881},{"style":152},[1882],{"type":39,"value":1084},{"type":26,"tag":140,"props":1884,"children":1885},{"class":142,"line":629},[1886,1890],{"type":26,"tag":140,"props":1887,"children":1888},{"style":255},[1889],{"type":39,"value":767},{"type":26,"tag":140,"props":1891,"children":1892},{"style":152},[1893],{"type":39,"value":1097},{"type":26,"tag":140,"props":1895,"children":1896},{"class":142,"line":630},[1897,1901],{"type":26,"tag":140,"props":1898,"children":1899},{"style":255},[1900],{"type":39,"value":767},{"type":26,"tag":140,"props":1902,"children":1903},{"style":152},[1904],{"type":39,"value":1110},{"type":26,"tag":140,"props":1906,"children":1907},{"class":142,"line":631},[1908,1912],{"type":26,"tag":140,"props":1909,"children":1910},{"style":255},[1911],{"type":39,"value":767},{"type":26,"tag":140,"props":1913,"children":1914},{"style":152},[1915],{"type":39,"value":1123},{"type":26,"tag":140,"props":1917,"children":1918},{"class":142,"line":632},[1919,1923],{"type":26,"tag":140,"props":1920,"children":1921},{"style":255},[1922],{"type":39,"value":767},{"type":26,"tag":140,"props":1924,"children":1925},{"style":152},[1926],{"type":39,"value":1136},{"type":26,"tag":140,"props":1928,"children":1929},{"class":142,"line":633},[1930,1934],{"type":26,"tag":140,"props":1931,"children":1932},{"style":255},[1933],{"type":39,"value":767},{"type":26,"tag":140,"props":1935,"children":1936},{"style":152},[1937],{"type":39,"value":1149},{"type":26,"tag":140,"props":1939,"children":1940},{"class":142,"line":634},[1941,1945],{"type":26,"tag":140,"props":1942,"children":1943},{"style":255},[1944],{"type":39,"value":767},{"type":26,"tag":140,"props":1946,"children":1947},{"style":152},[1948],{"type":39,"value":1110},{"type":26,"tag":140,"props":1950,"children":1951},{"class":142,"line":1164},[1952,1956],{"type":26,"tag":140,"props":1953,"children":1954},{"style":249},[1955],{"type":39,"value":1170},{"type":26,"tag":140,"props":1957,"children":1958},{"style":255},[1959],{"type":39,"value":258},{"type":26,"tag":140,"props":1961,"children":1962},{"class":142,"line":635},[1963,1967],{"type":26,"tag":140,"props":1964,"children":1965},{"style":255},[1966],{"type":39,"value":767},{"type":26,"tag":140,"props":1968,"children":1969},{"style":152},[1970],{"type":39,"value":1187},{"type":26,"tag":140,"props":1972,"children":1973},{"class":142,"line":1190},[1974],{"type":26,"tag":140,"props":1975,"children":1976},{"emptyLinePlaceholder":279},[1977],{"type":39,"value":282},{"type":26,"tag":140,"props":1979,"children":1980},{"class":142,"line":1198},[1981,1985],{"type":26,"tag":140,"props":1982,"children":1983},{"style":249},[1984],{"type":39,"value":1204},{"type":26,"tag":140,"props":1986,"children":1987},{"style":255},[1988],{"type":39,"value":258},{"type":26,"tag":140,"props":1990,"children":1991},{"class":142,"line":1211},[1992,1996,2000,2004],{"type":26,"tag":140,"props":1993,"children":1994},{"style":255},[1995],{"type":39,"value":767},{"type":26,"tag":140,"props":1997,"children":1998},{"style":249},[1999],{"type":39,"value":1221},{"type":26,"tag":140,"props":2001,"children":2002},{"style":255},[2003],{"type":39,"value":323},{"type":26,"tag":140,"props":2005,"children":2006},{"style":152},[2007],{"type":39,"value":1230},{"type":26,"tag":140,"props":2009,"children":2010},{"class":142,"line":1233},[2011,2015],{"type":26,"tag":140,"props":2012,"children":2013},{"style":249},[2014],{"type":39,"value":1239},{"type":26,"tag":140,"props":2016,"children":2017},{"style":255},[2018],{"type":39,"value":258},{"type":26,"tag":140,"props":2020,"children":2021},{"class":142,"line":1246},[2022,2026],{"type":26,"tag":140,"props":2023,"children":2024},{"style":255},[2025],{"type":39,"value":1252},{"type":26,"tag":140,"props":2027,"children":2028},{"style":152},[2029],{"type":39,"value":1257},{"type":26,"tag":140,"props":2031,"children":2032},{"class":142,"line":1260},[2033,2037,2041],{"type":26,"tag":140,"props":2034,"children":2035},{"style":249},[2036],{"type":39,"value":1266},{"type":26,"tag":140,"props":2038,"children":2039},{"style":255},[2040],{"type":39,"value":323},{"type":26,"tag":140,"props":2042,"children":2043},{"style":152},[2044],{"type":39,"value":1275},{"type":26,"tag":140,"props":2046,"children":2047},{"class":142,"line":1278},[2048,2052],{"type":26,"tag":140,"props":2049,"children":2050},{"style":249},[2051],{"type":39,"value":1284},{"type":26,"tag":140,"props":2053,"children":2054},{"style":255},[2055],{"type":39,"value":258},{"type":26,"tag":140,"props":2057,"children":2058},{"class":142,"line":1291},[2059,2063],{"type":26,"tag":140,"props":2060,"children":2061},{"style":249},[2062],{"type":39,"value":1297},{"type":26,"tag":140,"props":2064,"children":2065},{"style":255},[2066],{"type":39,"value":258},{"type":26,"tag":140,"props":2068,"children":2069},{"class":142,"line":1304},[2070,2074],{"type":26,"tag":140,"props":2071,"children":2072},{"style":249},[2073],{"type":39,"value":1310},{"type":26,"tag":140,"props":2075,"children":2076},{"style":255},[2077],{"type":39,"value":258},{"type":26,"tag":140,"props":2079,"children":2080},{"class":142,"line":1317},[2081,2085,2089],{"type":26,"tag":140,"props":2082,"children":2083},{"style":249},[2084],{"type":39,"value":1323},{"type":26,"tag":140,"props":2086,"children":2087},{"style":255},[2088],{"type":39,"value":323},{"type":26,"tag":140,"props":2090,"children":2091},{"style":152},[2092],{"type":39,"value":1332},{"type":26,"tag":140,"props":2094,"children":2095},{"class":142,"line":1335},[2096,2100,2104],{"type":26,"tag":140,"props":2097,"children":2098},{"style":249},[2099],{"type":39,"value":1341},{"type":26,"tag":140,"props":2101,"children":2102},{"style":255},[2103],{"type":39,"value":323},{"type":26,"tag":140,"props":2105,"children":2106},{"style":152},[2107],{"type":39,"value":1350},{"type":26,"tag":140,"props":2109,"children":2110},{"class":142,"line":1353},[2111,2115],{"type":26,"tag":140,"props":2112,"children":2113},{"style":249},[2114],{"type":39,"value":1359},{"type":26,"tag":140,"props":2116,"children":2117},{"style":255},[2118],{"type":39,"value":258},{"type":26,"tag":140,"props":2120,"children":2121},{"class":142,"line":1366},[2122,2126,2130,2134],{"type":26,"tag":140,"props":2123,"children":2124},{"style":255},[2125],{"type":39,"value":767},{"type":26,"tag":140,"props":2127,"children":2128},{"style":249},[2129],{"type":39,"value":466},{"type":26,"tag":140,"props":2131,"children":2132},{"style":255},[2133],{"type":39,"value":323},{"type":26,"tag":140,"props":2135,"children":2136},{"style":152},[2137],{"type":39,"value":475},{"type":26,"tag":140,"props":2139,"children":2140},{"class":142,"line":1386},[2141,2145,2149,2153],{"type":26,"tag":140,"props":2142,"children":2143},{"style":255},[2144],{"type":39,"value":767},{"type":26,"tag":140,"props":2146,"children":2147},{"style":249},[2148],{"type":39,"value":466},{"type":26,"tag":140,"props":2150,"children":2151},{"style":255},[2152],{"type":39,"value":323},{"type":26,"tag":140,"props":2154,"children":2155},{"style":152},[2156],{"type":39,"value":496},{"type":26,"tag":140,"props":2158,"children":2159},{"class":142,"line":1406},[2160,2164,2168],{"type":26,"tag":140,"props":2161,"children":2162},{"style":249},[2163],{"type":39,"value":1412},{"type":26,"tag":140,"props":2165,"children":2166},{"style":255},[2167],{"type":39,"value":323},{"type":26,"tag":140,"props":2169,"children":2170},{"style":152},[2171],{"type":39,"value":514},{"type":26,"tag":140,"props":2173,"children":2174},{"class":142,"line":1423},[2175,2179,2183,2187],{"type":26,"tag":140,"props":2176,"children":2177},{"style":255},[2178],{"type":39,"value":767},{"type":26,"tag":140,"props":2180,"children":2181},{"style":249},[2182],{"type":39,"value":466},{"type":26,"tag":140,"props":2184,"children":2185},{"style":255},[2186],{"type":39,"value":323},{"type":26,"tag":140,"props":2188,"children":2189},{"style":152},[2190],{"type":39,"value":535},{"type":26,"tag":140,"props":2192,"children":2194},{"class":142,"line":2193},55,[2195],{"type":26,"tag":140,"props":2196,"children":2197},{"emptyLinePlaceholder":279},[2198],{"type":39,"value":282},{"type":26,"tag":140,"props":2200,"children":2202},{"class":142,"line":2201},56,[2203,2207],{"type":26,"tag":140,"props":2204,"children":2205},{"style":249},[2206],{"type":39,"value":291},{"type":26,"tag":140,"props":2208,"children":2209},{"style":255},[2210],{"type":39,"value":258},{"type":26,"tag":140,"props":2212,"children":2214},{"class":142,"line":2213},57,[2215,2219],{"type":26,"tag":140,"props":2216,"children":2217},{"style":249},[2218],{"type":39,"value":304},{"type":26,"tag":140,"props":2220,"children":2221},{"style":255},[2222],{"type":39,"value":258},{"type":26,"tag":140,"props":2224,"children":2226},{"class":142,"line":2225},58,[2227,2231,2235],{"type":26,"tag":140,"props":2228,"children":2229},{"style":249},[2230],{"type":39,"value":318},{"type":26,"tag":140,"props":2232,"children":2233},{"style":255},[2234],{"type":39,"value":323},{"type":26,"tag":140,"props":2236,"children":2237},{"style":152},[2238],{"type":39,"value":328},{"type":26,"tag":140,"props":2240,"children":2242},{"class":142,"line":2241},59,[2243,2247,2251,2255],{"type":26,"tag":140,"props":2244,"children":2245},{"style":249},[2246],{"type":39,"value":337},{"type":26,"tag":140,"props":2248,"children":2249},{"style":255},[2250],{"type":39,"value":342},{"type":26,"tag":140,"props":2252,"children":2253},{"style":152},[2254],{"type":39,"value":347},{"type":26,"tag":140,"props":2256,"children":2257},{"style":255},[2258],{"type":39,"value":352},{"type":26,"tag":140,"props":2260,"children":2262},{"class":142,"line":2261},60,[2263,2267,2271],{"type":26,"tag":140,"props":2264,"children":2265},{"style":249},[2266],{"type":39,"value":361},{"type":26,"tag":140,"props":2268,"children":2269},{"style":255},[2270],{"type":39,"value":323},{"type":26,"tag":140,"props":2272,"children":2273},{"style":152},[2274],{"type":39,"value":272},{"type":26,"tag":140,"props":2276,"children":2278},{"class":142,"line":2277},61,[2279,2283],{"type":26,"tag":140,"props":2280,"children":2281},{"style":249},[2282],{"type":39,"value":378},{"type":26,"tag":140,"props":2284,"children":2285},{"style":255},[2286],{"type":39,"value":258},{"type":26,"tag":140,"props":2288,"children":2290},{"class":142,"line":2289},62,[2291,2295],{"type":26,"tag":140,"props":2292,"children":2293},{"style":255},[2294],{"type":39,"value":391},{"type":26,"tag":140,"props":2296,"children":2297},{"style":152},[2298],{"type":39,"value":396},{"type":26,"tag":140,"props":2300,"children":2302},{"class":142,"line":2301},63,[2303,2307],{"type":26,"tag":140,"props":2304,"children":2305},{"style":249},[2306],{"type":39,"value":405},{"type":26,"tag":140,"props":2308,"children":2309},{"style":255},[2310],{"type":39,"value":258},{"type":26,"tag":140,"props":2312,"children":2314},{"class":142,"line":2313},64,[2315,2319],{"type":26,"tag":140,"props":2316,"children":2317},{"style":249},[2318],{"type":39,"value":418},{"type":26,"tag":140,"props":2320,"children":2321},{"style":255},[2322],{"type":39,"value":258},{"type":26,"tag":140,"props":2324,"children":2326},{"class":142,"line":2325},65,[2327,2331,2335],{"type":26,"tag":140,"props":2328,"children":2329},{"style":249},[2330],{"type":39,"value":431},{"type":26,"tag":140,"props":2332,"children":2333},{"style":255},[2334],{"type":39,"value":323},{"type":26,"tag":140,"props":2336,"children":2337},{"style":152},[2338],{"type":39,"value":440},{"type":26,"tag":140,"props":2340,"children":2342},{"class":142,"line":2341},66,[2343,2347],{"type":26,"tag":140,"props":2344,"children":2345},{"style":249},[2346],{"type":39,"value":449},{"type":26,"tag":140,"props":2348,"children":2349},{"style":255},[2350],{"type":39,"value":258},{"type":26,"tag":140,"props":2352,"children":2354},{"class":142,"line":2353},67,[2355,2359,2363,2367],{"type":26,"tag":140,"props":2356,"children":2357},{"style":255},[2358],{"type":39,"value":391},{"type":26,"tag":140,"props":2360,"children":2361},{"style":249},[2362],{"type":39,"value":466},{"type":26,"tag":140,"props":2364,"children":2365},{"style":255},[2366],{"type":39,"value":323},{"type":26,"tag":140,"props":2368,"children":2369},{"style":152},[2370],{"type":39,"value":475},{"type":26,"tag":140,"props":2372,"children":2374},{"class":142,"line":2373},68,[2375,2379,2383,2387],{"type":26,"tag":140,"props":2376,"children":2377},{"style":255},[2378],{"type":39,"value":391},{"type":26,"tag":140,"props":2380,"children":2381},{"style":249},[2382],{"type":39,"value":466},{"type":26,"tag":140,"props":2384,"children":2385},{"style":255},[2386],{"type":39,"value":323},{"type":26,"tag":140,"props":2388,"children":2389},{"style":152},[2390],{"type":39,"value":496},{"type":26,"tag":140,"props":2392,"children":2394},{"class":142,"line":2393},69,[2395,2399,2403],{"type":26,"tag":140,"props":2396,"children":2397},{"style":249},[2398],{"type":39,"value":505},{"type":26,"tag":140,"props":2400,"children":2401},{"style":255},[2402],{"type":39,"value":323},{"type":26,"tag":140,"props":2404,"children":2405},{"style":152},[2406],{"type":39,"value":514},{"type":26,"tag":140,"props":2408,"children":2410},{"class":142,"line":2409},70,[2411,2415,2419,2423],{"type":26,"tag":140,"props":2412,"children":2413},{"style":255},[2414],{"type":39,"value":391},{"type":26,"tag":140,"props":2416,"children":2417},{"style":249},[2418],{"type":39,"value":466},{"type":26,"tag":140,"props":2420,"children":2421},{"style":255},[2422],{"type":39,"value":323},{"type":26,"tag":140,"props":2424,"children":2425},{"style":152},[2426],{"type":39,"value":535},{"type":26,"tag":2428,"props":2429,"children":2430},"style",{},[2431],{"type":39,"value":2432},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":7,"searchDepth":261,"depth":261,"links":2434},[2435,2438,2441],{"id":98,"depth":261,"text":101,"children":2436},[2437],{"id":218,"depth":275,"text":221},{"id":553,"depth":261,"text":67,"children":2439},[2440],{"id":601,"depth":275,"text":604},{"id":1481,"depth":261,"text":1484},"markdown","common:blog:20.shopware-plugin-gitlab-pipeline-test.md","common","blog/20.shopware-plugin-gitlab-pipeline-test.md","blog/20.shopware-plugin-gitlab-pipeline-test","md",{"_path":2449,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2450,"description":2451,"author":10,"image":11,"releaseDate":2452,"blogCategories":2453,"articleTags":2454,"tags":2455,"_type":2442,"_id":2456,"_source":2444,"_file":2457,"_stem":2458,"_extension":2447},"/blog/gitops-docker-renovate","Softwareverwaltung mit GitLab, Renovate Bot und Docker","Software auf einem Server zu verwalten ist nicht einfach. Oder doch?","2025-10-30",[14,15],[15,17],[21],"common:blog:17.gitops-docker-renovate.md","blog/17.gitops-docker-renovate.md","blog/17.gitops-docker-renovate",{"_path":2460,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2461,"description":2462,"author":10,"image":11,"releaseDate":2463,"blogCategories":2464,"articleTags":2465,"tags":2466,"_type":2442,"_id":2467,"_source":2444,"_file":2468,"_stem":2469,"_extension":2447},"/blog/traefik-magic","Verwendung von Traefik als Reverse Proxy - Convention over Configuration","Wie man den Traefik Reverse Proxy so konfiguriert, dass man auf Traefik-spezifische Labels verzichten kann und automatisch Subdomains passend zum Namen des Compose-Projekts geroutet werden.","2026-03-13",[14,15],[15],[21],"common:blog:21.traefik-magic.md","blog/21.traefik-magic.md","blog/21.traefik-magic",{"_path":4},{"_path":2472},"/en/blog/shopware-plugin-gitlab-pipeline-test",{"_path":2474,"_dir":2475,"_draft":6,"_partial":6,"_locale":7,"slug":10,"teams":2476,"primaryTeam":2478,"firstName":2479,"lastName":2480,"prefixTitle":7,"suffixTitle":2481,"education":2482,"role":2487,"workingSince":2492,"inTheCompanySince":2493,"techSkills":2494,"skills":2533,"projects":2550,"contactDetails":2560,"_image":2564,"image":2565,"_id":2566,"_type":2567,"title":2568,"_source":2475,"_file":2569,"_stem":2570,"_extension":2567},"/employees/robert-juzak","employees",[2477,2478],"appDev","devOps","Robert","Juzak","B.Sc.",[2483],[2484,2485,2486],"Bachelor of Computer Science","Technische Universität Breslau","2016",[2488,2489,2490,2491],"softwareDeveloper","fullstackDeveloper","admin","consultant","2015","2018",[2495,2499,2501,2504,2507,2510,2512,2515,2518,2522,2525,2527,2530],{"name":2496,"level":2497,"icon":2498},"Docker","expert","/images/Docker.svg",{"name":2500,"level":2497},"GitLab",{"name":2502,"level":2497,"icon":2503},"Kubernetes","/images/Kubernetes.svg",{"name":2505,"level":2497,"icon":2506},"PHPUnit","/images/PHP-Unit.svg",{"name":2508,"level":2497,"icon":2509},"Portainer","/images/Portainer.svg",{"name":2511,"level":2497},"Sentry",{"name":2513,"level":2497,"icon":2514},"Sonarqube","/images/Sonarqube.svg",{"name":2516,"level":2497,"icon":2517},"Linux","/images/linux_os-mono.svg",{"name":2519,"level":2520,"icon":2521},"CSS","advanced","/images/css.svg",{"name":2523,"level":2520,"icon":2524},"HTML","/images/html.svg",{"name":2526,"level":2520},"PHP",{"name":2528,"level":2520,"icon":2529},"SQL","/images/SQL.svg",{"name":2531,"level":2520,"icon":2532},"VueJS","/images/vuejs.svg",[2534,2535,2537,2538,2540,2542,2544,2546,2548],{"name":113,"level":2497},{"name":2536,"level":2497},"qualityAssurance",{"name":2478,"level":2497},{"name":2539,"level":2497},"testDrivenBugfix",{"name":2541,"level":2497},"testDrivenDevelopment",{"name":2543,"level":2520},"accessibility",{"name":2545,"level":2520},"databases",{"name":2547,"level":2520},"linuxServerAdministration",{"name":2549,"level":2520},"softwareArchitect",[2551,2556,2558],{"project":2552,"position":2553},"Herole",[2554,2555],"Dev-Ops","Frontend Developer",{"project":2557,"position":2555},"Huawei-Calibration-aaS",{"project":2559,"position":2555},"Huawei-Inspect-3D",{"eMail":2561,"phone":2562,"visibility":2563},"robert.juzak@helmundwalter.de","+49 351 799 035 26","1","images/employees/Portraits/robert_juzak.webp","images/employees/Portraits/RobertJuzak_MS.webp","employees:employees:6.robert-juzak.json","json","Robert Juzak","employees/6.robert-juzak.json","employees/6.robert-juzak",[2572,2586,2598,2610],{"_path":2573,"_dir":2574,"_draft":6,"_partial":279,"_locale":7,"name":2575,"slug":2574,"text":2576,"hoverText":2577,"image":2578,"customer":2579,"tags":2580,"_id":2582,"_type":238,"title":2583,"_source":2444,"_file":2584,"_stem":2585,"_extension":238},"/portfolio/bitburger/_teaser","bitburger","Bitburger B2B- und Marken-Shops","Launch des B2B Shops und Migration der Markenshops auf eine neue Plattform","Die Bitburger Braugruppe modernisierte ihr digitales Angebot. Nach dem Start des B2B Shops wurden fünf Markenshops auf eine gemeinsame Plattform migriert und weiterentwickelt.","/images/portfolio/bitburger/Bitburger_HuW_Glaeser.jpg","Bitburger Braugruppe",[20,2581],"e-commerce","common:portfolio:900.bitburger:_teaser.yaml","Teaser","portfolio/900.bitburger/_teaser.yaml","portfolio/900.bitburger/_teaser",{"_path":2587,"_dir":2588,"_draft":6,"_partial":279,"_locale":7,"name":2589,"slug":2588,"text":2590,"hoverText":2591,"image":2592,"customer":2593,"tags":2594,"_id":2595,"_type":238,"title":2583,"_source":2444,"_file":2596,"_stem":2597,"_extension":238},"/portfolio/purize/_teaser","purize","Purize Filters","E-Commerce für hochwertige Aktivkohlefilter","Wir unterstützen PURIZE® Filters mit einem vollständigen E-Commerce-Service inklusive Fulfillment-Lösung und Anbindung an Versanddienstleister. Unsere Expertise im Online-Handel ermöglicht dem Hersteller qualitativ hochwertiger Aktivkohlefilter \"Made in Germany\" eine reibungslose Abwicklung ihrer Bestellprozesse.","/images/portfolio/barcode-machine-verdandijpg.jpg","PURIZE® Filters",[20,2581],"common:portfolio:9000.purize:_teaser.yaml","portfolio/9000.purize/_teaser.yaml","portfolio/9000.purize/_teaser",{"_path":2599,"_dir":2600,"_draft":6,"_partial":279,"_locale":7,"name":2601,"slug":2600,"text":2602,"hoverText":2603,"image":2604,"customer":2601,"tags":2605,"_id":2607,"_type":238,"title":2583,"_source":2444,"_file":2608,"_stem":2609,"_extension":238},"/portfolio/pixelx/_teaser","pixelx","PixelX","IT-Sicherheit mit Augenmaß und Sachverstand","Für PixelX haben wir eine gezielte Sicherheitsanalyse durchgeführt, bei der wir dank unseres tiefen technischen Verständnisses eine kritische Schwachstelle identifizieren konnten. Mit minimalem Zeitaufwand erzielten wir maximalen Sicherheitsgewinn.","/images/portfolio/pixelx/pixelx_secured.png",[2606,21],"security","common:portfolio:9010.pixelx:_teaser.yaml","portfolio/9010.pixelx/_teaser.yaml","portfolio/9010.pixelx/_teaser",{"_path":2611,"_dir":2612,"_draft":6,"_partial":279,"_locale":7,"name":2613,"slug":2612,"text":2614,"hoverText":2615,"image":2616,"customer":2613,"tags":2617,"_id":2618,"_type":238,"title":2583,"_source":2444,"_file":2619,"_stem":2620,"_extension":238},"/portfolio/slimspots/_teaser","slimspots","SlimSpots","Große Datenmengen in Echtzeit verarbeiten","Für SlimSpots, einen weltweit agierenden Anbieter von Ad-Marketing-Lösungen, haben wir eine hochskalierbare Infrastruktur entwickelt, die die Verarbeitung von Billionen Datensätzen in Echtzeit ermöglicht.","/images/portfolio/slimspots/slim_spots_prtfolio.png",[2545,21],"common:portfolio:9020.slimspots:_teaser.yaml","portfolio/9020.slimspots/_teaser.yaml","portfolio/9020.slimspots/_teaser",{"_path":2449,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2450,"description":2451,"author":10,"image":11,"releaseDate":2452,"blogCategories":2622,"articleTags":2623,"tags":2624,"body":2625,"_type":2442,"_id":2456,"_source":2444,"_file":2457,"_stem":2458,"_extension":2447},[14,15],[15,17],[21],{"type":23,"children":2626,"toc":4110},[2627,2632,2637,2642,2647,2652,2671,2676,2718,2724,2737,2750,2755,2761,2774,2787,2796,2802,2807,2920,3444,3480,3493,3497,3502,3665,3678,3684,3689,3767,3772,3778,3783,3796,3809,3843,3870,3882,3901,3914,3917,3922,3935,3955,3960,3965,4087,4106],{"type":26,"tag":35,"props":2628,"children":2629},{},[2630],{"type":39,"value":2631},"Die Verwaltung eines Servers mit mehreren Diensten kann knifflig sein. Nicht jede Software ist miteinander kompatibel. Beispielsweise gibt es Anforderungen an Datenbank- oder PHP-Versionen.",{"type":26,"tag":35,"props":2633,"children":2634},{},[2635],{"type":39,"value":2636},"Außerdem sollte die Software auf dem neuesten Stand sein, um mögliche Sicherheitsrisiken zu minimieren.",{"type":26,"tag":35,"props":2638,"children":2639},{},[2640],{"type":39,"value":2641},"Es gibt viele Möglichkeiten, damit umzugehen, wie etwa Ansible, Chef usw.",{"type":26,"tag":35,"props":2643,"children":2644},{},[2645],{"type":39,"value":2646},"Unser Ziel war eine einfach zu bedienende, automatisierte und kostenlose Lösung.",{"type":26,"tag":35,"props":2648,"children":2649},{},[2650],{"type":39,"value":2651},"Hier sind die Ziele:",{"type":26,"tag":2653,"props":2654,"children":2655},"ul",{},[2656,2661,2666],{"type":26,"tag":46,"props":2657,"children":2658},{},[2659],{"type":39,"value":2660},"den GitOps-Ansatz nutzen, um die Konfiguration zu speichern und per Versionskontrolle nachvollziehbar zu machen",{"type":26,"tag":46,"props":2662,"children":2663},{},[2664],{"type":39,"value":2665},"Container verwenden, um die Software auszuführen",{"type":26,"tag":46,"props":2667,"children":2668},{},[2669],{"type":39,"value":2670},"Sicherheitsupdates automatisch ausspielen und Minor-/Major-Updates per Opt-in steuern",{"type":26,"tag":35,"props":2672,"children":2673},{},[2674],{"type":39,"value":2675},"Wir haben uns am Ende für den folgenden Stack entschieden:",{"type":26,"tag":2653,"props":2677,"children":2678},{},[2679,2697,2707],{"type":26,"tag":46,"props":2680,"children":2681},{},[2682,2687,2689,2695],{"type":26,"tag":52,"props":2683,"children":2685},{"href":2684},"https://www.docker.com/",[2686],{"type":39,"value":2496},{"type":39,"value":2688}," und ",{"type":26,"tag":52,"props":2690,"children":2692},{"href":2691},"https://docs.docker.com/compose/",[2693],{"type":39,"value":2694},"Docker Compose",{"type":39,"value":2696}," zum Verwalten der Software",{"type":26,"tag":46,"props":2698,"children":2699},{},[2700,2705],{"type":26,"tag":52,"props":2701,"children":2703},{"href":2702},"https://about.gitlab.com/",[2704],{"type":39,"value":2500},{"type":39,"value":2706}," zum Speichern aller Compose-Dateien",{"type":26,"tag":46,"props":2708,"children":2709},{},[2710,2716],{"type":26,"tag":52,"props":2711,"children":2713},{"href":2712},"https://docs.renovatebot.com",[2714],{"type":39,"value":2715},"Renovate Bot",{"type":39,"value":2717},", um die Software aktuell zu halten",{"type":26,"tag":96,"props":2719,"children":2721},{"id":2720},"über-den-stack",[2722],{"type":39,"value":2723},"Über den Stack",{"type":26,"tag":35,"props":2725,"children":2726},{},[2727,2729,2735],{"type":39,"value":2728},"Wir verwenden Docker bereits seit einiger Zeit in der Produktion. Je nach Situation erstellen wir die Compose-Datei direkt auf dem Server, verwalten sie über Portainer oder übertragen sie per ",{"type":26,"tag":108,"props":2730,"children":2732},{"className":2731},[],[2733],{"type":39,"value":2734},"scp",{"type":39,"value":2736}," in eine Pipeline.",{"type":26,"tag":35,"props":2738,"children":2739},{},[2740,2742,2748],{"type":39,"value":2741},"GitLab ist unser primäres Tool für die Versionskontrolle. Zusätzlich kümmert sich ein ",{"type":26,"tag":52,"props":2743,"children":2745},{"href":2744},"https://docs.gitlab.com/runner/",[2746],{"type":39,"value":2747},"GitLab Runner",{"type":39,"value":2749}," um das Ausführen der Pipelines.",{"type":26,"tag":35,"props":2751,"children":2752},{},[2753],{"type":39,"value":2754},"Renovate automatisiert Abhängigkeitsupdates. PHP, Go, Python, Docker – um nur ein paar zu nennen. Wir nutzen es bereits in verschiedenen Projekten.",{"type":26,"tag":96,"props":2756,"children":2758},{"id":2757},"container-mit-docker-und-docker-compose",[2759],{"type":39,"value":2760},"Container mit Docker und Docker Compose",{"type":26,"tag":35,"props":2762,"children":2763},{},[2764,2766,2772],{"type":39,"value":2765},"Der Hauptgrund, warum wir Docker gewählt haben, ist die Möglichkeit, auf einen remoten Docker-Host zuzugreifen und Docker-Befehle ausführen zu können.\nWeitere Informationen findest du in der ",{"type":26,"tag":52,"props":2767,"children":2769},{"href":2768},"https://docs.docker.com/reference/cli/docker/#host",[2770],{"type":39,"value":2771},"offiziellen Dokumentation",{"type":39,"value":2773},".",{"type":26,"tag":35,"props":2775,"children":2776},{},[2777,2779,2785],{"type":39,"value":2778},"Wir verwenden ",{"type":26,"tag":108,"props":2780,"children":2782},{"className":2781},[],[2783],{"type":39,"value":2784},"ssh",{"type":39,"value":2786},", um auf unseren Zielserver zuzugreifen.",{"type":26,"tag":35,"props":2788,"children":2789},{},[2790],{"type":26,"tag":108,"props":2791,"children":2793},{"className":2792},[],[2794],{"type":39,"value":2795},"DOCKER_HOST=ssh://[username@]\u003CIP or host>[:port] docker compose up --wait",{"type":26,"tag":96,"props":2797,"children":2799},{"id":2798},"gitops-mit-gitlab",[2800],{"type":39,"value":2801},"GitOps mit GitLab",{"type":26,"tag":35,"props":2803,"children":2804},{},[2805],{"type":39,"value":2806},"Die Idee hinter GitOps ist, ein Git-Repository zur Ablage der Konfiguration zu verwenden. Hier ein Beispiel:",{"type":26,"tag":130,"props":2808,"children":2810},{"className":134,"code":2809,"language":133,"meta":7,"style":7},".\n├──.gitlab-ci.yml             # Pipeline-Definition\n├── renovate.json             # Renovate-Konfiguration\n├── nextcloud\n│   ├── docker-compose.yml   # Nextcloud Datei-Hosting und Zusammenarbeit\n└── traefik\n    └── docker-compose.yml   # Traefik Reverse-Proxy-Konfiguration\n\n",[2811],{"type":26,"tag":108,"props":2812,"children":2813},{"__ignoreMap":7},[2814,2823,2837,2855,2867,2890,2903],{"type":26,"tag":140,"props":2815,"children":2816},{"class":142,"line":143},[2817],{"type":26,"tag":140,"props":2818,"children":2820},{"style":2819},"--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-sepia:#66D9EF",[2821],{"type":39,"value":2822},".\n",{"type":26,"tag":140,"props":2824,"children":2825},{"class":142,"line":261},[2826,2831],{"type":26,"tag":140,"props":2827,"children":2828},{"style":147},[2829],{"type":39,"value":2830},"├──.gitlab-ci.yml",{"type":26,"tag":140,"props":2832,"children":2834},{"style":2833},"--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F",[2835],{"type":39,"value":2836},"             # Pipeline-Definition\n",{"type":26,"tag":140,"props":2838,"children":2839},{"class":142,"line":275},[2840,2845,2850],{"type":26,"tag":140,"props":2841,"children":2842},{"style":147},[2843],{"type":39,"value":2844},"├──",{"type":26,"tag":140,"props":2846,"children":2847},{"style":152},[2848],{"type":39,"value":2849}," renovate.json",{"type":26,"tag":140,"props":2851,"children":2852},{"style":2833},[2853],{"type":39,"value":2854},"             # Renovate-Konfiguration\n",{"type":26,"tag":140,"props":2856,"children":2857},{"class":142,"line":285},[2858,2862],{"type":26,"tag":140,"props":2859,"children":2860},{"style":147},[2861],{"type":39,"value":2844},{"type":26,"tag":140,"props":2863,"children":2864},{"style":152},[2865],{"type":39,"value":2866}," nextcloud\n",{"type":26,"tag":140,"props":2868,"children":2869},{"class":142,"line":298},[2870,2875,2880,2885],{"type":26,"tag":140,"props":2871,"children":2872},{"style":147},[2873],{"type":39,"value":2874},"│",{"type":26,"tag":140,"props":2876,"children":2877},{"style":152},[2878],{"type":39,"value":2879},"   ├──",{"type":26,"tag":140,"props":2881,"children":2882},{"style":152},[2883],{"type":39,"value":2884}," docker-compose.yml",{"type":26,"tag":140,"props":2886,"children":2887},{"style":2833},[2888],{"type":39,"value":2889},"   # Nextcloud Datei-Hosting und Zusammenarbeit\n",{"type":26,"tag":140,"props":2891,"children":2892},{"class":142,"line":232},[2893,2898],{"type":26,"tag":140,"props":2894,"children":2895},{"style":147},[2896],{"type":39,"value":2897},"└──",{"type":26,"tag":140,"props":2899,"children":2900},{"style":152},[2901],{"type":39,"value":2902}," traefik\n",{"type":26,"tag":140,"props":2904,"children":2905},{"class":142,"line":331},[2906,2911,2915],{"type":26,"tag":140,"props":2907,"children":2908},{"style":147},[2909],{"type":39,"value":2910},"    └──",{"type":26,"tag":140,"props":2912,"children":2913},{"style":152},[2914],{"type":39,"value":2884},{"type":26,"tag":140,"props":2916,"children":2917},{"style":2833},[2918],{"type":39,"value":2919},"   # Traefik Reverse-Proxy-Konfiguration\n",{"type":26,"tag":130,"props":2921,"children":2924},{"className":239,"code":2922,"filename":2923,"language":238,"meta":7,"style":7},"volumes:\n  nextcloud:\n  db:\n\nservices:\n  db:\n    image: mariadb:11.8\n    restart: unless-stopped\n    volumes:\n      - db:/var/lib/mysql\n    environment:\n      - MARIADB_ROOT_PASSWORD=${NEXTCLOUD_MARIADB_ROOT_PASSWORD:?error}\n      - MARIADB_PASSWORD=${NEXTCLOUD_MARIADB_PASSWORD:?error}\n      - MARIADB_DATABASE=nextcloud\n      - MARIADB_USER=nextcloud\n    command:\n      - --transaction-isolation=READ-COMMITTED\n      - --log-bin=binlog\n      - --binlog-format=ROW\n    healthcheck:\n      test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n      interval: 15s\n      timeout: 5s\n      retries: 6\n\n  nextcloud:\n    image: nextcloud:32.0.0\n    restart: unless-stopped\n    depends_on:\n      db:\n        condition: service_healthy\n    volumes:\n      - nextcloud:/var/www/html\n    environment:\n      - MYSQL_PASSWORD=${NEXTCLOUD_MARIADB_PASSWORD:?error}\n      - MYSQL_DATABASE=nextcloud\n      - MYSQL_USER=nextcloud\n      - MYSQL_HOST=db\n","nextcloud/docker-compose.yaml",[2925],{"type":26,"tag":108,"props":2926,"children":2927},{"__ignoreMap":7},[2928,2940,2952,2964,2971,2983,2994,3011,3028,3040,3052,3064,3076,3088,3100,3112,3124,3136,3148,3160,3172,3221,3238,3255,3272,3279,3290,3306,3321,3333,3345,3362,3373,3385,3396,3408,3420,3432],{"type":26,"tag":140,"props":2929,"children":2930},{"class":142,"line":143},[2931,2936],{"type":26,"tag":140,"props":2932,"children":2933},{"style":249},[2934],{"type":39,"value":2935},"volumes",{"type":26,"tag":140,"props":2937,"children":2938},{"style":255},[2939],{"type":39,"value":258},{"type":26,"tag":140,"props":2941,"children":2942},{"class":142,"line":261},[2943,2948],{"type":26,"tag":140,"props":2944,"children":2945},{"style":249},[2946],{"type":39,"value":2947},"  nextcloud",{"type":26,"tag":140,"props":2949,"children":2950},{"style":255},[2951],{"type":39,"value":258},{"type":26,"tag":140,"props":2953,"children":2954},{"class":142,"line":275},[2955,2960],{"type":26,"tag":140,"props":2956,"children":2957},{"style":249},[2958],{"type":39,"value":2959},"  db",{"type":26,"tag":140,"props":2961,"children":2962},{"style":255},[2963],{"type":39,"value":258},{"type":26,"tag":140,"props":2965,"children":2966},{"class":142,"line":285},[2967],{"type":26,"tag":140,"props":2968,"children":2969},{"emptyLinePlaceholder":279},[2970],{"type":39,"value":282},{"type":26,"tag":140,"props":2972,"children":2973},{"class":142,"line":298},[2974,2979],{"type":26,"tag":140,"props":2975,"children":2976},{"style":249},[2977],{"type":39,"value":2978},"services",{"type":26,"tag":140,"props":2980,"children":2981},{"style":255},[2982],{"type":39,"value":258},{"type":26,"tag":140,"props":2984,"children":2985},{"class":142,"line":232},[2986,2990],{"type":26,"tag":140,"props":2987,"children":2988},{"style":249},[2989],{"type":39,"value":2959},{"type":26,"tag":140,"props":2991,"children":2992},{"style":255},[2993],{"type":39,"value":258},{"type":26,"tag":140,"props":2995,"children":2996},{"class":142,"line":331},[2997,3002,3006],{"type":26,"tag":140,"props":2998,"children":2999},{"style":249},[3000],{"type":39,"value":3001},"    image",{"type":26,"tag":140,"props":3003,"children":3004},{"style":255},[3005],{"type":39,"value":323},{"type":26,"tag":140,"props":3007,"children":3008},{"style":152},[3009],{"type":39,"value":3010},"mariadb:11.8\n",{"type":26,"tag":140,"props":3012,"children":3013},{"class":142,"line":355},[3014,3019,3023],{"type":26,"tag":140,"props":3015,"children":3016},{"style":249},[3017],{"type":39,"value":3018},"    restart",{"type":26,"tag":140,"props":3020,"children":3021},{"style":255},[3022],{"type":39,"value":323},{"type":26,"tag":140,"props":3024,"children":3025},{"style":152},[3026],{"type":39,"value":3027},"unless-stopped\n",{"type":26,"tag":140,"props":3029,"children":3030},{"class":142,"line":372},[3031,3036],{"type":26,"tag":140,"props":3032,"children":3033},{"style":249},[3034],{"type":39,"value":3035},"    volumes",{"type":26,"tag":140,"props":3037,"children":3038},{"style":255},[3039],{"type":39,"value":258},{"type":26,"tag":140,"props":3041,"children":3042},{"class":142,"line":385},[3043,3047],{"type":26,"tag":140,"props":3044,"children":3045},{"style":255},[3046],{"type":39,"value":391},{"type":26,"tag":140,"props":3048,"children":3049},{"style":152},[3050],{"type":39,"value":3051},"db:/var/lib/mysql\n",{"type":26,"tag":140,"props":3053,"children":3054},{"class":142,"line":399},[3055,3060],{"type":26,"tag":140,"props":3056,"children":3057},{"style":249},[3058],{"type":39,"value":3059},"    environment",{"type":26,"tag":140,"props":3061,"children":3062},{"style":255},[3063],{"type":39,"value":258},{"type":26,"tag":140,"props":3065,"children":3066},{"class":142,"line":412},[3067,3071],{"type":26,"tag":140,"props":3068,"children":3069},{"style":255},[3070],{"type":39,"value":391},{"type":26,"tag":140,"props":3072,"children":3073},{"style":152},[3074],{"type":39,"value":3075},"MARIADB_ROOT_PASSWORD=${NEXTCLOUD_MARIADB_ROOT_PASSWORD:?error}\n",{"type":26,"tag":140,"props":3077,"children":3078},{"class":142,"line":425},[3079,3083],{"type":26,"tag":140,"props":3080,"children":3081},{"style":255},[3082],{"type":39,"value":391},{"type":26,"tag":140,"props":3084,"children":3085},{"style":152},[3086],{"type":39,"value":3087},"MARIADB_PASSWORD=${NEXTCLOUD_MARIADB_PASSWORD:?error}\n",{"type":26,"tag":140,"props":3089,"children":3090},{"class":142,"line":233},[3091,3095],{"type":26,"tag":140,"props":3092,"children":3093},{"style":255},[3094],{"type":39,"value":391},{"type":26,"tag":140,"props":3096,"children":3097},{"style":152},[3098],{"type":39,"value":3099},"MARIADB_DATABASE=nextcloud\n",{"type":26,"tag":140,"props":3101,"children":3102},{"class":142,"line":234},[3103,3107],{"type":26,"tag":140,"props":3104,"children":3105},{"style":255},[3106],{"type":39,"value":391},{"type":26,"tag":140,"props":3108,"children":3109},{"style":152},[3110],{"type":39,"value":3111},"MARIADB_USER=nextcloud\n",{"type":26,"tag":140,"props":3113,"children":3114},{"class":142,"line":235},[3115,3120],{"type":26,"tag":140,"props":3116,"children":3117},{"style":249},[3118],{"type":39,"value":3119},"    command",{"type":26,"tag":140,"props":3121,"children":3122},{"style":255},[3123],{"type":39,"value":258},{"type":26,"tag":140,"props":3125,"children":3126},{"class":142,"line":236},[3127,3131],{"type":26,"tag":140,"props":3128,"children":3129},{"style":255},[3130],{"type":39,"value":391},{"type":26,"tag":140,"props":3132,"children":3133},{"style":152},[3134],{"type":39,"value":3135},"--transaction-isolation=READ-COMMITTED\n",{"type":26,"tag":140,"props":3137,"children":3138},{"class":142,"line":237},[3139,3143],{"type":26,"tag":140,"props":3140,"children":3141},{"style":255},[3142],{"type":39,"value":391},{"type":26,"tag":140,"props":3144,"children":3145},{"style":152},[3146],{"type":39,"value":3147},"--log-bin=binlog\n",{"type":26,"tag":140,"props":3149,"children":3150},{"class":142,"line":915},[3151,3155],{"type":26,"tag":140,"props":3152,"children":3153},{"style":255},[3154],{"type":39,"value":391},{"type":26,"tag":140,"props":3156,"children":3157},{"style":152},[3158],{"type":39,"value":3159},"--binlog-format=ROW\n",{"type":26,"tag":140,"props":3161,"children":3162},{"class":142,"line":621},[3163,3168],{"type":26,"tag":140,"props":3164,"children":3165},{"style":249},[3166],{"type":39,"value":3167},"    healthcheck",{"type":26,"tag":140,"props":3169,"children":3170},{"style":255},[3171],{"type":39,"value":258},{"type":26,"tag":140,"props":3173,"children":3174},{"class":142,"line":622},[3175,3180,3184,3189,3194,3199,3203,3208,3212,3217],{"type":26,"tag":140,"props":3176,"children":3177},{"style":249},[3178],{"type":39,"value":3179},"      test",{"type":26,"tag":140,"props":3181,"children":3182},{"style":255},[3183],{"type":39,"value":342},{"type":26,"tag":140,"props":3185,"children":3186},{"style":152},[3187],{"type":39,"value":3188},"\"CMD\"",{"type":26,"tag":140,"props":3190,"children":3191},{"style":255},[3192],{"type":39,"value":3193},", ",{"type":26,"tag":140,"props":3195,"children":3196},{"style":152},[3197],{"type":39,"value":3198},"\"healthcheck.sh\"",{"type":26,"tag":140,"props":3200,"children":3201},{"style":255},[3202],{"type":39,"value":3193},{"type":26,"tag":140,"props":3204,"children":3205},{"style":152},[3206],{"type":39,"value":3207},"\"--connect\"",{"type":26,"tag":140,"props":3209,"children":3210},{"style":255},[3211],{"type":39,"value":3193},{"type":26,"tag":140,"props":3213,"children":3214},{"style":152},[3215],{"type":39,"value":3216},"\"--innodb_initialized\"",{"type":26,"tag":140,"props":3218,"children":3219},{"style":255},[3220],{"type":39,"value":352},{"type":26,"tag":140,"props":3222,"children":3223},{"class":142,"line":623},[3224,3229,3233],{"type":26,"tag":140,"props":3225,"children":3226},{"style":249},[3227],{"type":39,"value":3228},"      interval",{"type":26,"tag":140,"props":3230,"children":3231},{"style":255},[3232],{"type":39,"value":323},{"type":26,"tag":140,"props":3234,"children":3235},{"style":152},[3236],{"type":39,"value":3237},"15s\n",{"type":26,"tag":140,"props":3239,"children":3240},{"class":142,"line":624},[3241,3246,3250],{"type":26,"tag":140,"props":3242,"children":3243},{"style":249},[3244],{"type":39,"value":3245},"      timeout",{"type":26,"tag":140,"props":3247,"children":3248},{"style":255},[3249],{"type":39,"value":323},{"type":26,"tag":140,"props":3251,"children":3252},{"style":152},[3253],{"type":39,"value":3254},"5s\n",{"type":26,"tag":140,"props":3256,"children":3257},{"class":142,"line":996},[3258,3263,3267],{"type":26,"tag":140,"props":3259,"children":3260},{"style":249},[3261],{"type":39,"value":3262},"      retries",{"type":26,"tag":140,"props":3264,"children":3265},{"style":255},[3266],{"type":39,"value":323},{"type":26,"tag":140,"props":3268,"children":3269},{"style":163},[3270],{"type":39,"value":3271},"6\n",{"type":26,"tag":140,"props":3273,"children":3274},{"class":142,"line":1004},[3275],{"type":26,"tag":140,"props":3276,"children":3277},{"emptyLinePlaceholder":279},[3278],{"type":39,"value":282},{"type":26,"tag":140,"props":3280,"children":3281},{"class":142,"line":1022},[3282,3286],{"type":26,"tag":140,"props":3283,"children":3284},{"style":249},[3285],{"type":39,"value":2947},{"type":26,"tag":140,"props":3287,"children":3288},{"style":255},[3289],{"type":39,"value":258},{"type":26,"tag":140,"props":3291,"children":3292},{"class":142,"line":625},[3293,3297,3301],{"type":26,"tag":140,"props":3294,"children":3295},{"style":249},[3296],{"type":39,"value":3001},{"type":26,"tag":140,"props":3298,"children":3299},{"style":255},[3300],{"type":39,"value":323},{"type":26,"tag":140,"props":3302,"children":3303},{"style":152},[3304],{"type":39,"value":3305},"nextcloud:32.0.0\n",{"type":26,"tag":140,"props":3307,"children":3308},{"class":142,"line":626},[3309,3313,3317],{"type":26,"tag":140,"props":3310,"children":3311},{"style":249},[3312],{"type":39,"value":3018},{"type":26,"tag":140,"props":3314,"children":3315},{"style":255},[3316],{"type":39,"value":323},{"type":26,"tag":140,"props":3318,"children":3319},{"style":152},[3320],{"type":39,"value":3027},{"type":26,"tag":140,"props":3322,"children":3323},{"class":142,"line":627},[3324,3329],{"type":26,"tag":140,"props":3325,"children":3326},{"style":249},[3327],{"type":39,"value":3328},"    depends_on",{"type":26,"tag":140,"props":3330,"children":3331},{"style":255},[3332],{"type":39,"value":258},{"type":26,"tag":140,"props":3334,"children":3335},{"class":142,"line":628},[3336,3341],{"type":26,"tag":140,"props":3337,"children":3338},{"style":249},[3339],{"type":39,"value":3340},"      db",{"type":26,"tag":140,"props":3342,"children":3343},{"style":255},[3344],{"type":39,"value":258},{"type":26,"tag":140,"props":3346,"children":3347},{"class":142,"line":629},[3348,3353,3357],{"type":26,"tag":140,"props":3349,"children":3350},{"style":249},[3351],{"type":39,"value":3352},"        condition",{"type":26,"tag":140,"props":3354,"children":3355},{"style":255},[3356],{"type":39,"value":323},{"type":26,"tag":140,"props":3358,"children":3359},{"style":152},[3360],{"type":39,"value":3361},"service_healthy\n",{"type":26,"tag":140,"props":3363,"children":3364},{"class":142,"line":630},[3365,3369],{"type":26,"tag":140,"props":3366,"children":3367},{"style":249},[3368],{"type":39,"value":3035},{"type":26,"tag":140,"props":3370,"children":3371},{"style":255},[3372],{"type":39,"value":258},{"type":26,"tag":140,"props":3374,"children":3375},{"class":142,"line":631},[3376,3380],{"type":26,"tag":140,"props":3377,"children":3378},{"style":255},[3379],{"type":39,"value":391},{"type":26,"tag":140,"props":3381,"children":3382},{"style":152},[3383],{"type":39,"value":3384},"nextcloud:/var/www/html\n",{"type":26,"tag":140,"props":3386,"children":3387},{"class":142,"line":632},[3388,3392],{"type":26,"tag":140,"props":3389,"children":3390},{"style":249},[3391],{"type":39,"value":3059},{"type":26,"tag":140,"props":3393,"children":3394},{"style":255},[3395],{"type":39,"value":258},{"type":26,"tag":140,"props":3397,"children":3398},{"class":142,"line":633},[3399,3403],{"type":26,"tag":140,"props":3400,"children":3401},{"style":255},[3402],{"type":39,"value":391},{"type":26,"tag":140,"props":3404,"children":3405},{"style":152},[3406],{"type":39,"value":3407},"MYSQL_PASSWORD=${NEXTCLOUD_MARIADB_PASSWORD:?error}\n",{"type":26,"tag":140,"props":3409,"children":3410},{"class":142,"line":634},[3411,3415],{"type":26,"tag":140,"props":3412,"children":3413},{"style":255},[3414],{"type":39,"value":391},{"type":26,"tag":140,"props":3416,"children":3417},{"style":152},[3418],{"type":39,"value":3419},"MYSQL_DATABASE=nextcloud\n",{"type":26,"tag":140,"props":3421,"children":3422},{"class":142,"line":1164},[3423,3427],{"type":26,"tag":140,"props":3424,"children":3425},{"style":255},[3426],{"type":39,"value":391},{"type":26,"tag":140,"props":3428,"children":3429},{"style":152},[3430],{"type":39,"value":3431},"MYSQL_USER=nextcloud\n",{"type":26,"tag":140,"props":3433,"children":3434},{"class":142,"line":635},[3435,3439],{"type":26,"tag":140,"props":3436,"children":3437},{"style":255},[3438],{"type":39,"value":391},{"type":26,"tag":140,"props":3440,"children":3441},{"style":152},[3442],{"type":39,"value":3443},"MYSQL_HOST=db\n",{"type":26,"tag":130,"props":3445,"children":3449},{"className":3446,"code":3447,"language":3448,"meta":7,"style":7},"language-dotenv shiki shiki-themes github-dark github-dark monokai","NEXTCLOUD_MARIADB_ROOT_PASSWORD=\nNEXTCLOUD_MARIADB_PASSWORD=\n","dotenv",[3450],{"type":26,"tag":108,"props":3451,"children":3452},{"__ignoreMap":7},[3453,3468],{"type":26,"tag":140,"props":3454,"children":3455},{"class":142,"line":143},[3456,3462],{"type":26,"tag":140,"props":3457,"children":3459},{"style":3458},"--shiki-default:#FFAB70;--shiki-dark:#FFAB70;--shiki-sepia:#F8F8F2",[3460],{"type":39,"value":3461},"NEXTCLOUD_MARIADB_ROOT_PASSWORD",{"type":26,"tag":140,"props":3463,"children":3465},{"style":3464},"--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-sepia:#F92672",[3466],{"type":39,"value":3467},"=\n",{"type":26,"tag":140,"props":3469,"children":3470},{"class":142,"line":261},[3471,3476],{"type":26,"tag":140,"props":3472,"children":3473},{"style":3458},[3474],{"type":39,"value":3475},"NEXTCLOUD_MARIADB_PASSWORD",{"type":26,"tag":140,"props":3477,"children":3478},{"style":3464},[3479],{"type":39,"value":3467},{"type":26,"tag":35,"props":3481,"children":3482},{},[3483,3485,3491],{"type":39,"value":3484},"Werden als ",{"type":26,"tag":52,"props":3486,"children":3488},{"href":3487},"https://docs.gitlab.com/ci/variables/",[3489],{"type":39,"value":3490},"CI/CD-Variablen",{"type":39,"value":3492}," gespeichert.",{"type":26,"tag":3494,"props":3495,"children":3496},"hr",{},[],{"type":26,"tag":35,"props":3498,"children":3499},{},[3500],{"type":39,"value":3501},"Um den Stack zu deployen, haben wir folgende Pipeline:",{"type":26,"tag":130,"props":3503,"children":3506},{"className":239,"code":3504,"filename":3505,"language":238,"meta":7,"style":7},"stages:\n  - deploy\n\ndeploy:\n  stage: deploy\n  image: docker:28\n  variables:\n    DOCKER_HOST: ssh://[username@]\u003CIP or host>[:port]\n  script:\n    - for file in $(find . -type f -name docker-compose.yml); do docker compose -f $file up --remove-orphans --wait; done\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\n",".gitlab-ci.yml",[3507],{"type":26,"tag":108,"props":3508,"children":3509},{"__ignoreMap":7},[3510,3521,3533,3540,3552,3567,3583,3594,3611,3622,3634,3645],{"type":26,"tag":140,"props":3511,"children":3512},{"class":142,"line":143},[3513,3517],{"type":26,"tag":140,"props":3514,"children":3515},{"style":249},[3516],{"type":39,"value":252},{"type":26,"tag":140,"props":3518,"children":3519},{"style":255},[3520],{"type":39,"value":258},{"type":26,"tag":140,"props":3522,"children":3523},{"class":142,"line":261},[3524,3528],{"type":26,"tag":140,"props":3525,"children":3526},{"style":255},[3527],{"type":39,"value":267},{"type":26,"tag":140,"props":3529,"children":3530},{"style":152},[3531],{"type":39,"value":3532},"deploy\n",{"type":26,"tag":140,"props":3534,"children":3535},{"class":142,"line":275},[3536],{"type":26,"tag":140,"props":3537,"children":3538},{"emptyLinePlaceholder":279},[3539],{"type":39,"value":282},{"type":26,"tag":140,"props":3541,"children":3542},{"class":142,"line":285},[3543,3548],{"type":26,"tag":140,"props":3544,"children":3545},{"style":249},[3546],{"type":39,"value":3547},"deploy",{"type":26,"tag":140,"props":3549,"children":3550},{"style":255},[3551],{"type":39,"value":258},{"type":26,"tag":140,"props":3553,"children":3554},{"class":142,"line":298},[3555,3559,3563],{"type":26,"tag":140,"props":3556,"children":3557},{"style":249},[3558],{"type":39,"value":689},{"type":26,"tag":140,"props":3560,"children":3561},{"style":255},[3562],{"type":39,"value":323},{"type":26,"tag":140,"props":3564,"children":3565},{"style":152},[3566],{"type":39,"value":3532},{"type":26,"tag":140,"props":3568,"children":3569},{"class":142,"line":232},[3570,3574,3578],{"type":26,"tag":140,"props":3571,"children":3572},{"style":249},[3573],{"type":39,"value":705},{"type":26,"tag":140,"props":3575,"children":3576},{"style":255},[3577],{"type":39,"value":323},{"type":26,"tag":140,"props":3579,"children":3580},{"style":152},[3581],{"type":39,"value":3582},"docker:28\n",{"type":26,"tag":140,"props":3584,"children":3585},{"class":142,"line":331},[3586,3590],{"type":26,"tag":140,"props":3587,"children":3588},{"style":249},[3589],{"type":39,"value":856},{"type":26,"tag":140,"props":3591,"children":3592},{"style":255},[3593],{"type":39,"value":258},{"type":26,"tag":140,"props":3595,"children":3596},{"class":142,"line":355},[3597,3602,3606],{"type":26,"tag":140,"props":3598,"children":3599},{"style":249},[3600],{"type":39,"value":3601},"    DOCKER_HOST",{"type":26,"tag":140,"props":3603,"children":3604},{"style":255},[3605],{"type":39,"value":323},{"type":26,"tag":140,"props":3607,"children":3608},{"style":152},[3609],{"type":39,"value":3610},"ssh://[username@]\u003CIP or host>[:port]\n",{"type":26,"tag":140,"props":3612,"children":3613},{"class":142,"line":372},[3614,3618],{"type":26,"tag":140,"props":3615,"children":3616},{"style":249},[3617],{"type":39,"value":1170},{"type":26,"tag":140,"props":3619,"children":3620},{"style":255},[3621],{"type":39,"value":258},{"type":26,"tag":140,"props":3623,"children":3624},{"class":142,"line":385},[3625,3629],{"type":26,"tag":140,"props":3626,"children":3627},{"style":255},[3628],{"type":39,"value":767},{"type":26,"tag":140,"props":3630,"children":3631},{"style":152},[3632],{"type":39,"value":3633},"for file in $(find . -type f -name docker-compose.yml); do docker compose -f $file up --remove-orphans --wait; done\n",{"type":26,"tag":140,"props":3635,"children":3636},{"class":142,"line":399},[3637,3641],{"type":26,"tag":140,"props":3638,"children":3639},{"style":249},[3640],{"type":39,"value":1359},{"type":26,"tag":140,"props":3642,"children":3643},{"style":255},[3644],{"type":39,"value":258},{"type":26,"tag":140,"props":3646,"children":3647},{"class":142,"line":412},[3648,3652,3656,3660],{"type":26,"tag":140,"props":3649,"children":3650},{"style":255},[3651],{"type":39,"value":767},{"type":26,"tag":140,"props":3653,"children":3654},{"style":249},[3655],{"type":39,"value":466},{"type":26,"tag":140,"props":3657,"children":3658},{"style":255},[3659],{"type":39,"value":323},{"type":26,"tag":140,"props":3661,"children":3662},{"style":152},[3663],{"type":39,"value":3664},"$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n",{"type":26,"tag":35,"props":3666,"children":3667},{},[3668,3670,3676],{"type":39,"value":3669},"Die Pipeline läuft bei jedem Commit auf dem Standard-Branch, iteriert über alle ",{"type":26,"tag":108,"props":3671,"children":3673},{"className":3672},[],[3674],{"type":39,"value":3675},"docker-compose.yml",{"type":39,"value":3677},"-Dateien und deployt sie.",{"type":26,"tag":96,"props":3679,"children":3681},{"id":3680},"halte-deine-software-aktuell-mit-renovate-bot",[3682],{"type":39,"value":3683},"Halte deine Software aktuell mit Renovate-Bot",{"type":26,"tag":35,"props":3685,"children":3686},{},[3687],{"type":39,"value":3688},"Hier kommt Renovate ins Spiel.",{"type":26,"tag":130,"props":3690,"children":3694},{"className":3691,"code":3692,"filename":3693,"language":2567,"meta":7,"style":7},"language-json shiki shiki-themes github-dark github-dark monokai","{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:best-practices\"\n  ]\n}\n","renovate.json",[3695],{"type":26,"tag":108,"props":3696,"children":3697},{"__ignoreMap":7},[3698,3706,3730,3743,3751,3759],{"type":26,"tag":140,"props":3699,"children":3700},{"class":142,"line":143},[3701],{"type":26,"tag":140,"props":3702,"children":3703},{"style":255},[3704],{"type":39,"value":3705},"{\n",{"type":26,"tag":140,"props":3707,"children":3708},{"class":142,"line":261},[3709,3715,3719,3725],{"type":26,"tag":140,"props":3710,"children":3712},{"style":3711},"--shiki-default:#79B8FF;--shiki-default-font-style:inherit;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic",[3713],{"type":39,"value":3714},"  \"$schema\"",{"type":26,"tag":140,"props":3716,"children":3717},{"style":255},[3718],{"type":39,"value":323},{"type":26,"tag":140,"props":3720,"children":3722},{"style":3721},"--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-sepia:#CFCFC2",[3723],{"type":39,"value":3724},"\"https://docs.renovatebot.com/renovate-schema.json\"",{"type":26,"tag":140,"props":3726,"children":3727},{"style":255},[3728],{"type":39,"value":3729},",\n",{"type":26,"tag":140,"props":3731,"children":3732},{"class":142,"line":275},[3733,3738],{"type":26,"tag":140,"props":3734,"children":3735},{"style":3711},[3736],{"type":39,"value":3737},"  \"extends\"",{"type":26,"tag":140,"props":3739,"children":3740},{"style":255},[3741],{"type":39,"value":3742},": [\n",{"type":26,"tag":140,"props":3744,"children":3745},{"class":142,"line":285},[3746],{"type":26,"tag":140,"props":3747,"children":3748},{"style":3721},[3749],{"type":39,"value":3750},"    \"config:best-practices\"\n",{"type":26,"tag":140,"props":3752,"children":3753},{"class":142,"line":298},[3754],{"type":26,"tag":140,"props":3755,"children":3756},{"style":255},[3757],{"type":39,"value":3758},"  ]\n",{"type":26,"tag":140,"props":3760,"children":3761},{"class":142,"line":232},[3762],{"type":26,"tag":140,"props":3763,"children":3764},{"style":255},[3765],{"type":39,"value":3766},"}\n",{"type":26,"tag":35,"props":3768,"children":3769},{},[3770],{"type":39,"value":3771},"Renovate erstellt für jedes Update einen Merge-Request. Super!",{"type":26,"tag":96,"props":3773,"children":3775},{"id":3774},"automatisierte-sicherheitsupdates-und-opt-in-für-minor-major-versionen",[3776],{"type":39,"value":3777},"Automatisierte Sicherheitsupdates und Opt-in für Minor-/Major-Versionen",{"type":26,"tag":35,"props":3779,"children":3780},{},[3781],{"type":39,"value":3782},"Die aktuelle Konfiguration erstellt für jedes Update einen Merge-Request, aber wir möchten, dass Sicherheitsupdates ohne Benutzerinteraktion erfolgen.",{"type":26,"tag":35,"props":3784,"children":3785},{},[3786,3788,3794],{"type":39,"value":3787},"Es ist wichtig zu verstehen, wie Docker-Images versioniert bzw. getaggt werden. Es hängt vom jeweiligen Image ab, aber nehmen wir die offizielle ",{"type":26,"tag":52,"props":3789,"children":3791},{"href":3790},"https://hub.docker.com/_/mariadb",[3792],{"type":39,"value":3793},"MariaDB",{"type":39,"value":3795}," als Beispiel.",{"type":26,"tag":35,"props":3797,"children":3798},{},[3799,3801,3807],{"type":39,"value":3800},"Es gibt ",{"type":26,"tag":108,"props":3802,"children":3804},{"className":3803},[],[3805],{"type":39,"value":3806},"11.8.3-noble, 11.8-noble, 11-noble, lts-noble, 11.8.3, 11.8, 11, lts",{"type":39,"value":3808},", die alle auf dasselbe Image verweisen.",{"type":26,"tag":35,"props":3810,"children":3811},{},[3812,3818,3820,3826,3828,3834,3835,3841],{"type":26,"tag":108,"props":3813,"children":3815},{"className":3814},[],[3816],{"type":39,"value":3817},"11.8.3-noble",{"type":39,"value":3819}," bedeutet, dass wir MariaDB in Version ",{"type":26,"tag":108,"props":3821,"children":3823},{"className":3822},[],[3824],{"type":39,"value":3825},"11.8.3",{"type":39,"value":3827}," auf Basis von Ubuntu Noble erhalten.\n",{"type":26,"tag":108,"props":3829,"children":3831},{"className":3830},[],[3832],{"type":39,"value":3833},"11.8-noble",{"type":39,"value":3819},{"type":26,"tag":108,"props":3836,"children":3838},{"className":3837},[],[3839],{"type":39,"value":3840},"11.8.\u003Clatest_patch>",{"type":39,"value":3842}," auf Basis von Ubuntu Noble erhalten.",{"type":26,"tag":35,"props":3844,"children":3845},{},[3846,3848,3854,3856,3861,3863,3868],{"type":39,"value":3847},"Wenn eine neue Version von MariaDB veröffentlicht wird, z. B. ",{"type":26,"tag":108,"props":3849,"children":3851},{"className":3850},[],[3852],{"type":39,"value":3853},"11.8.4-noble",{"type":39,"value":3855},", wird ein neuer Tag ",{"type":26,"tag":108,"props":3857,"children":3859},{"className":3858},[],[3860],{"type":39,"value":3853},{"type":39,"value":3862}," veröffentlicht, aber der Tag ",{"type":26,"tag":108,"props":3864,"children":3866},{"className":3865},[],[3867],{"type":39,"value":3833},{"type":39,"value":3869}," wird aktualisiert.",{"type":26,"tag":35,"props":3871,"children":3872},{},[3873,3875,3880],{"type":39,"value":3874},"Gleiches gilt für das Ubuntu-Update. Der Tag ",{"type":26,"tag":108,"props":3876,"children":3878},{"className":3877},[],[3879],{"type":39,"value":3817},{"type":39,"value":3881}," kann aktualisiert werden, wenn das Image mit dem neuesten Ubuntu-Image erneut gebaut wird.",{"type":26,"tag":35,"props":3883,"children":3884},{},[3885,3891,3893,3899],{"type":26,"tag":108,"props":3886,"children":3888},{"className":3887},[],[3889],{"type":39,"value":3890},"docker compose up",{"type":39,"value":3892}," mit ",{"type":26,"tag":108,"props":3894,"children":3896},{"className":3895},[],[3897],{"type":39,"value":3898},"mariadb:11.8-noble",{"type":39,"value":3900}," wird nichts bewirken, weil Docker sich dieser Änderung nicht bewusst ist.",{"type":26,"tag":35,"props":3902,"children":3903},{},[3904,3906,3912],{"type":39,"value":3905},"Im Beispiel oben verweisen wir auf ",{"type":26,"tag":108,"props":3907,"children":3909},{"className":3908},[],[3910],{"type":39,"value":3911},"mariadb:11.8",{"type":39,"value":3913},", weil wir die neueste Patch-Version auf Basis des neuesten Betriebssystems verwenden möchten.",{"type":26,"tag":3494,"props":3915,"children":3916},{},[],{"type":26,"tag":35,"props":3918,"children":3919},{},[3920],{"type":39,"value":3921},"Wie soll Docker mitgeteilt werden, dass es eine neue Version gibt?",{"type":26,"tag":35,"props":3923,"children":3924},{},[3925,3927,3933],{"type":39,"value":3926},"Die Hauptidee ist, das Docker-Image zusätzlich mit einem ",{"type":26,"tag":52,"props":3928,"children":3930},{"href":3929},"https://docs.docker.com/dhi/core-concepts/digests/",[3931],{"type":39,"value":3932},"Digest",{"type":39,"value":3934}," anzugeben.",{"type":26,"tag":35,"props":3936,"children":3937},{},[3938,3940,3945,3947,3953],{"type":39,"value":3939},"Wenn Renovate das erste Mal läuft, findet es den Verweis auf ",{"type":26,"tag":108,"props":3941,"children":3943},{"className":3942},[],[3944],{"type":39,"value":3911},{"type":39,"value":3946}," und erstellt einen Merge-Request, um den Digest auf so etwas wie ",{"type":26,"tag":108,"props":3948,"children":3950},{"className":3949},[],[3951],{"type":39,"value":3952},"mariadb:11.8@sha256:ae6119716edac6998ae85508431b3d2e666530ddf4e94c61a10710caec9b0f71",{"type":39,"value":3954}," festzulegen.",{"type":26,"tag":35,"props":3956,"children":3957},{},[3958],{"type":39,"value":3959},"Es überwacht das auch, sodass bei jedem Update des Images der Digest wechselt und Renovate einen Merge-Request erstellt.",{"type":26,"tag":35,"props":3961,"children":3962},{},[3963],{"type":39,"value":3964},"Damit diese Updates automatisch gemergt werden, müssen wir ein paar Anpassungen vornehmen.",{"type":26,"tag":130,"props":3966,"children":3969},{"className":3691,"code":3967,"filename":3693,"highlights":3968,"language":2567,"meta":7,"style":7},"{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:best-practices\",\n    \"default:automergeDigest\"\n  ],\n  \"automergeType\": \"branch\",\n  \"ignoreTests\": true\n}\n",[298,232,331,355],[3970],{"type":26,"tag":108,"props":3971,"children":3972},{"__ignoreMap":7},[3973,3980,3999,4010,4022,4031,4040,4062,4080],{"type":26,"tag":140,"props":3974,"children":3975},{"class":142,"line":143},[3976],{"type":26,"tag":140,"props":3977,"children":3978},{"style":255},[3979],{"type":39,"value":3705},{"type":26,"tag":140,"props":3981,"children":3982},{"class":142,"line":261},[3983,3987,3991,3995],{"type":26,"tag":140,"props":3984,"children":3985},{"style":3711},[3986],{"type":39,"value":3714},{"type":26,"tag":140,"props":3988,"children":3989},{"style":255},[3990],{"type":39,"value":323},{"type":26,"tag":140,"props":3992,"children":3993},{"style":3721},[3994],{"type":39,"value":3724},{"type":26,"tag":140,"props":3996,"children":3997},{"style":255},[3998],{"type":39,"value":3729},{"type":26,"tag":140,"props":4000,"children":4001},{"class":142,"line":275},[4002,4006],{"type":26,"tag":140,"props":4003,"children":4004},{"style":3711},[4005],{"type":39,"value":3737},{"type":26,"tag":140,"props":4007,"children":4008},{"style":255},[4009],{"type":39,"value":3742},{"type":26,"tag":140,"props":4011,"children":4012},{"class":142,"line":285},[4013,4018],{"type":26,"tag":140,"props":4014,"children":4015},{"style":3721},[4016],{"type":39,"value":4017},"    \"config:best-practices\"",{"type":26,"tag":140,"props":4019,"children":4020},{"style":255},[4021],{"type":39,"value":3729},{"type":26,"tag":140,"props":4023,"children":4025},{"class":4024,"line":298},[142,312],[4026],{"type":26,"tag":140,"props":4027,"children":4028},{"style":3721},[4029],{"type":39,"value":4030},"    \"default:automergeDigest\"\n",{"type":26,"tag":140,"props":4032,"children":4034},{"class":4033,"line":232},[142,312],[4035],{"type":26,"tag":140,"props":4036,"children":4037},{"style":255},[4038],{"type":39,"value":4039},"  ],\n",{"type":26,"tag":140,"props":4041,"children":4043},{"class":4042,"line":331},[142,312],[4044,4049,4053,4058],{"type":26,"tag":140,"props":4045,"children":4046},{"style":3711},[4047],{"type":39,"value":4048},"  \"automergeType\"",{"type":26,"tag":140,"props":4050,"children":4051},{"style":255},[4052],{"type":39,"value":323},{"type":26,"tag":140,"props":4054,"children":4055},{"style":3721},[4056],{"type":39,"value":4057},"\"branch\"",{"type":26,"tag":140,"props":4059,"children":4060},{"style":255},[4061],{"type":39,"value":3729},{"type":26,"tag":140,"props":4063,"children":4065},{"class":4064,"line":355},[142,312],[4066,4071,4075],{"type":26,"tag":140,"props":4067,"children":4068},{"style":3711},[4069],{"type":39,"value":4070},"  \"ignoreTests\"",{"type":26,"tag":140,"props":4072,"children":4073},{"style":255},[4074],{"type":39,"value":323},{"type":26,"tag":140,"props":4076,"children":4077},{"style":163},[4078],{"type":39,"value":4079},"true\n",{"type":26,"tag":140,"props":4081,"children":4082},{"class":142,"line":372},[4083],{"type":26,"tag":140,"props":4084,"children":4085},{"style":255},[4086],{"type":39,"value":3766},{"type":26,"tag":35,"props":4088,"children":4089},{},[4090,4092,4098,4099,4105],{"type":39,"value":4091},"Das weist Renovate an, die Digest-Updates automatisch zu mergen, ohne einen Merge-Request zu erstellen. Das reduziert das \"Rauschen\", weil es keine Merge-Request-Benachrichtigung gibt.\nMehr dazu findest du unter ",{"type":26,"tag":52,"props":4093,"children":4095},{"href":4094},"https://docs.renovatebot.com/key-concepts/automerge/#branch-vs-pr-automerging",[4096],{"type":39,"value":4097},"automergeType",{"type":39,"value":2688},{"type":26,"tag":52,"props":4100,"children":4102},{"href":4101},"https://docs.renovatebot.com/key-concepts/automerge/#absence-of-tests",[4103],{"type":39,"value":4104},"ignoreTests",{"type":39,"value":2773},{"type":26,"tag":2428,"props":4107,"children":4108},{},[4109],{"type":39,"value":2432},{"title":7,"searchDepth":261,"depth":261,"links":4111},[4112,4113,4114,4115,4116],{"id":2720,"depth":261,"text":2723},{"id":2757,"depth":261,"text":2760},{"id":2798,"depth":261,"text":2801},{"id":3680,"depth":261,"text":3683},{"id":3774,"depth":261,"text":3777},{"_path":2460,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2461,"description":2462,"author":10,"image":11,"releaseDate":2463,"blogCategories":4118,"articleTags":4119,"tags":4120,"body":4121,"_type":2442,"_id":2467,"_source":2444,"_file":2468,"_stem":2469,"_extension":2447},[14,15],[15],[21],{"type":23,"children":4122,"toc":5268},[4123,4134,4139,4264,4269,4342,4348,4374,4379,4407,4420,4438,4444,4461,4562,4567,4572,4597,4643,4646,4651,4990,4995,5031,5037,5045,5098,5102,5109,5137,5143,5148,5154,5159,5171,5179,5185,5197,5264],{"type":26,"tag":35,"props":4124,"children":4125},{},[4126,4132],{"type":26,"tag":52,"props":4127,"children":4129},{"href":4128},"https://doc.traefik.io/traefik/",[4130],{"type":39,"value":4131},"Traefik",{"type":39,"value":4133}," ist ein Reverse Proxy mit exzellenter Docker-Integration. Er verwendet Labels, die an Containern angebracht sind, um den Datenverkehr zu ihnen zu leiten.",{"type":26,"tag":35,"props":4135,"children":4136},{},[4137],{"type":39,"value":4138},"Ein typisches Set an Labels sieht ungefähr so aus:",{"type":26,"tag":130,"props":4140,"children":4144},{"code":4141,"filename":4142,"highlights":4143,"language":238,"meta":7,"className":239,"style":7},"services:\n  whoami:\n    image: traefik/whoami\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.whoami.rule=Host(`whoami.example.com`)\"\n      - \"traefik.http.routers.whoami.entrypoints=websecure\"\n      - \"traefik.http.routers.whoami.tls=true\"\n      - \"traefik.http.routers.whoami.tls.certresolver=letsencrypt\"\n","whoami/docker-compose.yaml",[298,232,331,355,372],[4145],{"type":26,"tag":108,"props":4146,"children":4147},{"__ignoreMap":7},[4148,4159,4171,4187,4199,4212,4225,4238,4251],{"type":26,"tag":140,"props":4149,"children":4150},{"class":142,"line":143},[4151,4155],{"type":26,"tag":140,"props":4152,"children":4153},{"style":249},[4154],{"type":39,"value":2978},{"type":26,"tag":140,"props":4156,"children":4157},{"style":255},[4158],{"type":39,"value":258},{"type":26,"tag":140,"props":4160,"children":4161},{"class":142,"line":261},[4162,4167],{"type":26,"tag":140,"props":4163,"children":4164},{"style":249},[4165],{"type":39,"value":4166},"  whoami",{"type":26,"tag":140,"props":4168,"children":4169},{"style":255},[4170],{"type":39,"value":258},{"type":26,"tag":140,"props":4172,"children":4173},{"class":142,"line":275},[4174,4178,4182],{"type":26,"tag":140,"props":4175,"children":4176},{"style":249},[4177],{"type":39,"value":3001},{"type":26,"tag":140,"props":4179,"children":4180},{"style":255},[4181],{"type":39,"value":323},{"type":26,"tag":140,"props":4183,"children":4184},{"style":152},[4185],{"type":39,"value":4186},"traefik/whoami\n",{"type":26,"tag":140,"props":4188,"children":4189},{"class":142,"line":285},[4190,4195],{"type":26,"tag":140,"props":4191,"children":4192},{"style":249},[4193],{"type":39,"value":4194},"    labels",{"type":26,"tag":140,"props":4196,"children":4197},{"style":255},[4198],{"type":39,"value":258},{"type":26,"tag":140,"props":4200,"children":4202},{"class":4201,"line":298},[142,312],[4203,4207],{"type":26,"tag":140,"props":4204,"children":4205},{"style":255},[4206],{"type":39,"value":391},{"type":26,"tag":140,"props":4208,"children":4209},{"style":152},[4210],{"type":39,"value":4211},"\"traefik.enable=true\"\n",{"type":26,"tag":140,"props":4213,"children":4215},{"class":4214,"line":232},[142,312],[4216,4220],{"type":26,"tag":140,"props":4217,"children":4218},{"style":255},[4219],{"type":39,"value":391},{"type":26,"tag":140,"props":4221,"children":4222},{"style":152},[4223],{"type":39,"value":4224},"\"traefik.http.routers.whoami.rule=Host(`whoami.example.com`)\"\n",{"type":26,"tag":140,"props":4226,"children":4228},{"class":4227,"line":331},[142,312],[4229,4233],{"type":26,"tag":140,"props":4230,"children":4231},{"style":255},[4232],{"type":39,"value":391},{"type":26,"tag":140,"props":4234,"children":4235},{"style":152},[4236],{"type":39,"value":4237},"\"traefik.http.routers.whoami.entrypoints=websecure\"\n",{"type":26,"tag":140,"props":4239,"children":4241},{"class":4240,"line":355},[142,312],[4242,4246],{"type":26,"tag":140,"props":4243,"children":4244},{"style":255},[4245],{"type":39,"value":391},{"type":26,"tag":140,"props":4247,"children":4248},{"style":152},[4249],{"type":39,"value":4250},"\"traefik.http.routers.whoami.tls=true\"\n",{"type":26,"tag":140,"props":4252,"children":4254},{"class":4253,"line":372},[142,312],[4255,4259],{"type":26,"tag":140,"props":4256,"children":4257},{"style":255},[4258],{"type":39,"value":391},{"type":26,"tag":140,"props":4260,"children":4261},{"style":152},[4262],{"type":39,"value":4263},"\"traefik.http.routers.whoami.tls.certresolver=letsencrypt\"\n",{"type":26,"tag":35,"props":4265,"children":4266},{},[4267],{"type":39,"value":4268},"In diesem Beispiel:",{"type":26,"tag":2653,"props":4270,"children":4271},{},[4272,4283,4299,4304,4316,4321],{"type":26,"tag":46,"props":4273,"children":4274},{},[4275,4281],{"type":26,"tag":108,"props":4276,"children":4278},{"className":4277},[],[4279],{"type":39,"value":4280},"whoami",{"type":39,"value":4282}," ist der Name des \"Haupt\"-Dienstes (2)",{"type":26,"tag":46,"props":4284,"children":4285},{},[4286,4291,4293],{"type":26,"tag":108,"props":4287,"children":4289},{"className":4288},[],[4290],{"type":39,"value":4280},{"type":39,"value":4292}," ist auch der Standard-",{"type":26,"tag":52,"props":4294,"children":4296},{"href":4295},"https://docs.docker.com/compose/how-tos/project-name/",[4297],{"type":39,"value":4298},"Name des Compose-Projekts",{"type":26,"tag":46,"props":4300,"children":4301},{},[4302],{"type":39,"value":4303},"Traefik wird aktiviert (5)",{"type":26,"tag":46,"props":4305,"children":4306},{},[4307,4309,4314],{"type":39,"value":4308},"Der Dienst wird unter der Subdomain ",{"type":26,"tag":108,"props":4310,"children":4312},{"className":4311},[],[4313],{"type":39,"value":4280},{"type":39,"value":4315}," bereitgestellt (6)",{"type":26,"tag":46,"props":4317,"children":4318},{},[4319],{"type":39,"value":4320},"Die Auslieferung erfolgt über HTTPS (7)",{"type":26,"tag":46,"props":4322,"children":4323},{},[4324,4326,4332,4334,4340],{"type":39,"value":4325},"Ein vorkonfigurierter Certresolver namens ",{"type":26,"tag":108,"props":4327,"children":4329},{"className":4328},[],[4330],{"type":39,"value":4331},"letsencrypt",{"type":39,"value":4333}," wird für ",{"type":26,"tag":108,"props":4335,"children":4337},{"className":4336},[],[4338],{"type":39,"value":4339},"tls",{"type":39,"value":4341}," verwendet (8-9)",{"type":26,"tag":96,"props":4343,"children":4345},{"id":4344},"das-problem",[4346],{"type":39,"value":4347},"Das Problem",{"type":26,"tag":35,"props":4349,"children":4350},{},[4351,4353,4358,4360,4366,4368,4372],{"type":39,"value":4352},"In meinem ",{"type":26,"tag":52,"props":4354,"children":4355},{"href":2449},[4356],{"type":39,"value":4357},"anderen Beitrag über GitOps mit Docker",{"type":39,"value":4359}," habe ich das Konzept eingeführt,\n",{"type":26,"tag":108,"props":4361,"children":4363},{"className":4362},[],[4364],{"type":39,"value":4365},"git",{"type":39,"value":4367}," als „Source of Truth“ für Docker-Deployments mittels ",{"type":26,"tag":52,"props":4369,"children":4370},{"href":2691},[4371],{"type":39,"value":2694},{"type":39,"value":4373}," zu nutzen.",{"type":26,"tag":35,"props":4375,"children":4376},{},[4377],{"type":39,"value":4378},"Dabei gibt es einige Anforderungen:",{"type":26,"tag":2653,"props":4380,"children":4381},{},[4382,4395],{"type":26,"tag":46,"props":4383,"children":4384},{},[4385,4387,4393],{"type":39,"value":4386},"Jeder Stack ist unter ",{"type":26,"tag":108,"props":4388,"children":4390},{"className":4389},[],[4391],{"type":39,"value":4392},"\u003Cstack_name>.\u003Cyour_domain>",{"type":39,"value":4394}," erreichbar",{"type":26,"tag":46,"props":4396,"children":4397},{},[4398,4400,4405],{"type":39,"value":4399},"Jeder Stack ist mit ",{"type":26,"tag":108,"props":4401,"children":4403},{"className":4402},[],[4404],{"type":39,"value":4339},{"type":39,"value":4406}," geschützt",{"type":26,"tag":35,"props":4408,"children":4409},{},[4410,4412,4418],{"type":39,"value":4411},"Wir könnten zwar in jeder ",{"type":26,"tag":108,"props":4413,"children":4415},{"className":4414},[],[4416],{"type":39,"value":4417},"docker-compose.yaml",{"type":39,"value":4419}," die Labels manuell hinzufügen, doch dabei zeigt sich schnell,\ndass wir die Konfiguration redundant wiederholen.",{"type":26,"tag":42,"props":4421,"children":4422},{},[4423,4428,4433],{"type":26,"tag":46,"props":4424,"children":4425},{},[4426],{"type":39,"value":4427},"Traefik aktivieren",{"type":26,"tag":46,"props":4429,"children":4430},{},[4431],{"type":39,"value":4432},"Eine Subdomain zuweisen",{"type":26,"tag":46,"props":4434,"children":4435},{},[4436],{"type":39,"value":4437},"HTTPS aktivieren",{"type":26,"tag":96,"props":4439,"children":4441},{"id":4440},"die-lösung",[4442],{"type":39,"value":4443},"Die Lösung",{"type":26,"tag":35,"props":4445,"children":4446},{},[4447,4449,4459],{"type":39,"value":4448},"Mit hilfe der ",{"type":26,"tag":52,"props":4450,"children":4452},{"href":4451},"https://docs.docker.com/compose/how-tos/environment-variables/envvars/#compose_project_name",[4453],{"type":26,"tag":108,"props":4454,"children":4456},{"className":4455},[],[4457],{"type":39,"value":4458},"$COMPOSE_PROJECT_NAME",{"type":39,"value":4460},"\nVariable können wir ein generisches Template für eine solche Konfiguration erstellen.\nDadurch stellen wir sicher, dass die Traefik-Regeln einheitlich sind.",{"type":26,"tag":130,"props":4462,"children":4465},{"code":4463,"filename":4464,"language":238,"meta":7,"className":239,"style":7},"services:\n  \u003Cmain_service>:\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.$COMPOSE_PROJECT_NAME.rule=Host(`\u003Cstack_name>.example.com`)\"\n      - \"traefik.http.routers.$COMPOSE_PROJECT_NAME.entrypoints=websecure\"\n      - \"traefik.http.routers.$COMPOSE_PROJECT_NAME.tls=true\"\n      - \"traefik.http.routers.$COMPOSE_PROJECT_NAME.tls.certresolver=letsencrypt\"\n","\u003Cstack_name>/docker-compose.yaml",[4466],{"type":26,"tag":108,"props":4467,"children":4468},{"__ignoreMap":7},[4469,4480,4492,4503,4514,4526,4538,4550],{"type":26,"tag":140,"props":4470,"children":4471},{"class":142,"line":143},[4472,4476],{"type":26,"tag":140,"props":4473,"children":4474},{"style":249},[4475],{"type":39,"value":2978},{"type":26,"tag":140,"props":4477,"children":4478},{"style":255},[4479],{"type":39,"value":258},{"type":26,"tag":140,"props":4481,"children":4482},{"class":142,"line":261},[4483,4488],{"type":26,"tag":140,"props":4484,"children":4485},{"style":249},[4486],{"type":39,"value":4487},"  \u003Cmain_service>",{"type":26,"tag":140,"props":4489,"children":4490},{"style":255},[4491],{"type":39,"value":258},{"type":26,"tag":140,"props":4493,"children":4494},{"class":142,"line":275},[4495,4499],{"type":26,"tag":140,"props":4496,"children":4497},{"style":249},[4498],{"type":39,"value":4194},{"type":26,"tag":140,"props":4500,"children":4501},{"style":255},[4502],{"type":39,"value":258},{"type":26,"tag":140,"props":4504,"children":4505},{"class":142,"line":285},[4506,4510],{"type":26,"tag":140,"props":4507,"children":4508},{"style":255},[4509],{"type":39,"value":391},{"type":26,"tag":140,"props":4511,"children":4512},{"style":152},[4513],{"type":39,"value":4211},{"type":26,"tag":140,"props":4515,"children":4516},{"class":142,"line":298},[4517,4521],{"type":26,"tag":140,"props":4518,"children":4519},{"style":255},[4520],{"type":39,"value":391},{"type":26,"tag":140,"props":4522,"children":4523},{"style":152},[4524],{"type":39,"value":4525},"\"traefik.http.routers.$COMPOSE_PROJECT_NAME.rule=Host(`\u003Cstack_name>.example.com`)\"\n",{"type":26,"tag":140,"props":4527,"children":4528},{"class":142,"line":232},[4529,4533],{"type":26,"tag":140,"props":4530,"children":4531},{"style":255},[4532],{"type":39,"value":391},{"type":26,"tag":140,"props":4534,"children":4535},{"style":152},[4536],{"type":39,"value":4537},"\"traefik.http.routers.$COMPOSE_PROJECT_NAME.entrypoints=websecure\"\n",{"type":26,"tag":140,"props":4539,"children":4540},{"class":142,"line":331},[4541,4545],{"type":26,"tag":140,"props":4542,"children":4543},{"style":255},[4544],{"type":39,"value":391},{"type":26,"tag":140,"props":4546,"children":4547},{"style":152},[4548],{"type":39,"value":4549},"\"traefik.http.routers.$COMPOSE_PROJECT_NAME.tls=true\"\n",{"type":26,"tag":140,"props":4551,"children":4552},{"class":142,"line":355},[4553,4557],{"type":26,"tag":140,"props":4554,"children":4555},{"style":255},[4556],{"type":39,"value":391},{"type":26,"tag":140,"props":4558,"children":4559},{"style":152},[4560],{"type":39,"value":4561},"\"traefik.http.routers.$COMPOSE_PROJECT_NAME.tls.certresolver=letsencrypt\"\n",{"type":26,"tag":35,"props":4563,"children":4564},{},[4565],{"type":39,"value":4566},"Die gute Nachricht ist, dass Traefik es uns ermöglicht, einige Standardwerte zu konfigurieren, die den oben genannten Boilerplate-Code abdecken!",{"type":26,"tag":35,"props":4568,"children":4569},{},[4570],{"type":39,"value":4571},"Führen wir zwei einfache Konventionen ein:",{"type":26,"tag":42,"props":4573,"children":4574},{},[4575,4586],{"type":26,"tag":46,"props":4576,"children":4577},{},[4578,4584],{"type":26,"tag":108,"props":4579,"children":4581},{"className":4580},[],[4582],{"type":39,"value":4583},"app",{"type":39,"value":4585}," als Name des \"Hauptcontainers\", damit Traefik den Datenverkehr dorthin leitet",{"type":26,"tag":46,"props":4587,"children":4588},{},[4589,4595],{"type":26,"tag":108,"props":4590,"children":4592},{"className":4591},[],[4593],{"type":39,"value":4594},"\u003Cstack_name>",{"type":39,"value":4596}," (der Name des Compose-Projekts) in der Subdomain",{"type":26,"tag":130,"props":4598,"children":4601},{"code":4599,"filename":4600,"language":238,"meta":7,"className":239,"style":7},"services:\n  app:\n    image: traefik/whoami\n","(1) whoami/docker-compose.yaml",[4602],{"type":26,"tag":108,"props":4603,"children":4604},{"__ignoreMap":7},[4605,4616,4628],{"type":26,"tag":140,"props":4606,"children":4607},{"class":142,"line":143},[4608,4612],{"type":26,"tag":140,"props":4609,"children":4610},{"style":249},[4611],{"type":39,"value":2978},{"type":26,"tag":140,"props":4613,"children":4614},{"style":255},[4615],{"type":39,"value":258},{"type":26,"tag":140,"props":4617,"children":4618},{"class":142,"line":261},[4619,4624],{"type":26,"tag":140,"props":4620,"children":4621},{"style":249},[4622],{"type":39,"value":4623},"  app",{"type":26,"tag":140,"props":4625,"children":4626},{"style":255},[4627],{"type":39,"value":258},{"type":26,"tag":140,"props":4629,"children":4630},{"class":142,"line":275},[4631,4635,4639],{"type":26,"tag":140,"props":4632,"children":4633},{"style":249},[4634],{"type":39,"value":3001},{"type":26,"tag":140,"props":4636,"children":4637},{"style":255},[4638],{"type":39,"value":323},{"type":26,"tag":140,"props":4640,"children":4641},{"style":152},[4642],{"type":39,"value":4186},{"type":26,"tag":3494,"props":4644,"children":4645},{},[],{"type":26,"tag":35,"props":4647,"children":4648},{},[4649],{"type":39,"value":4650},"Nun konfigurieren wir Traefik, um \"die Magie\" wirken zu lassen:",{"type":26,"tag":130,"props":4652,"children":4655},{"code":4653,"filename":4654,"language":238,"meta":7,"className":239,"style":7},"volumes:\n  letsencrypt:\n    \nservices:\n  traefik:\n    container_name: traefik\n    restart: always\n    image: traefik:3\n    network_mode: host\n    command:\n      - --certificatesresolvers.letsencrypt.acme.httpchallenge=true\n      - --certificatesresolvers.letsencrypt.acme.email=\u003Cyour_email_here>\n      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json\n      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web\n\n      - --entrypoints.web.address=:80\n      - --entrypoints.websecure.address=:443\n      \n      - --entrypoints.web.http.redirections.entrypoint.to=websecure\n      - --entrypoints.web.http.redirections.entrypoint.scheme=https\n      - --entrypoints.websecure.http.tls.certresolver=letsencrypt\n\n      - --providers.docker\n      - --providers.docker.defaultrule=Host(`{{ trimPrefix `app-` .Name }}.example.com`)\n      - --providers.docker.constraints=Label(`com.docker.compose.service`,`app`)\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock:ro\n      - /letsencrypt:/letsencrypt\n","(2) traefik/docker-compose.yaml",[4656],{"type":26,"tag":108,"props":4657,"children":4658},{"__ignoreMap":7},[4659,4670,4682,4689,4700,4712,4729,4745,4761,4778,4789,4801,4813,4825,4837,4844,4856,4868,4876,4888,4900,4912,4919,4931,4943,4955,4966,4978],{"type":26,"tag":140,"props":4660,"children":4661},{"class":142,"line":143},[4662,4666],{"type":26,"tag":140,"props":4663,"children":4664},{"style":249},[4665],{"type":39,"value":2935},{"type":26,"tag":140,"props":4667,"children":4668},{"style":255},[4669],{"type":39,"value":258},{"type":26,"tag":140,"props":4671,"children":4672},{"class":142,"line":261},[4673,4678],{"type":26,"tag":140,"props":4674,"children":4675},{"style":249},[4676],{"type":39,"value":4677},"  letsencrypt",{"type":26,"tag":140,"props":4679,"children":4680},{"style":255},[4681],{"type":39,"value":258},{"type":26,"tag":140,"props":4683,"children":4684},{"class":142,"line":275},[4685],{"type":26,"tag":140,"props":4686,"children":4687},{"style":255},[4688],{"type":39,"value":921},{"type":26,"tag":140,"props":4690,"children":4691},{"class":142,"line":285},[4692,4696],{"type":26,"tag":140,"props":4693,"children":4694},{"style":249},[4695],{"type":39,"value":2978},{"type":26,"tag":140,"props":4697,"children":4698},{"style":255},[4699],{"type":39,"value":258},{"type":26,"tag":140,"props":4701,"children":4702},{"class":142,"line":298},[4703,4708],{"type":26,"tag":140,"props":4704,"children":4705},{"style":249},[4706],{"type":39,"value":4707},"  traefik",{"type":26,"tag":140,"props":4709,"children":4710},{"style":255},[4711],{"type":39,"value":258},{"type":26,"tag":140,"props":4713,"children":4714},{"class":142,"line":232},[4715,4720,4724],{"type":26,"tag":140,"props":4716,"children":4717},{"style":249},[4718],{"type":39,"value":4719},"    container_name",{"type":26,"tag":140,"props":4721,"children":4722},{"style":255},[4723],{"type":39,"value":323},{"type":26,"tag":140,"props":4725,"children":4726},{"style":152},[4727],{"type":39,"value":4728},"traefik\n",{"type":26,"tag":140,"props":4730,"children":4731},{"class":142,"line":331},[4732,4736,4740],{"type":26,"tag":140,"props":4733,"children":4734},{"style":249},[4735],{"type":39,"value":3018},{"type":26,"tag":140,"props":4737,"children":4738},{"style":255},[4739],{"type":39,"value":323},{"type":26,"tag":140,"props":4741,"children":4742},{"style":152},[4743],{"type":39,"value":4744},"always\n",{"type":26,"tag":140,"props":4746,"children":4747},{"class":142,"line":355},[4748,4752,4756],{"type":26,"tag":140,"props":4749,"children":4750},{"style":249},[4751],{"type":39,"value":3001},{"type":26,"tag":140,"props":4753,"children":4754},{"style":255},[4755],{"type":39,"value":323},{"type":26,"tag":140,"props":4757,"children":4758},{"style":152},[4759],{"type":39,"value":4760},"traefik:3\n",{"type":26,"tag":140,"props":4762,"children":4763},{"class":142,"line":372},[4764,4769,4773],{"type":26,"tag":140,"props":4765,"children":4766},{"style":249},[4767],{"type":39,"value":4768},"    network_mode",{"type":26,"tag":140,"props":4770,"children":4771},{"style":255},[4772],{"type":39,"value":323},{"type":26,"tag":140,"props":4774,"children":4775},{"style":152},[4776],{"type":39,"value":4777},"host\n",{"type":26,"tag":140,"props":4779,"children":4780},{"class":142,"line":385},[4781,4785],{"type":26,"tag":140,"props":4782,"children":4783},{"style":249},[4784],{"type":39,"value":3119},{"type":26,"tag":140,"props":4786,"children":4787},{"style":255},[4788],{"type":39,"value":258},{"type":26,"tag":140,"props":4790,"children":4791},{"class":142,"line":399},[4792,4796],{"type":26,"tag":140,"props":4793,"children":4794},{"style":255},[4795],{"type":39,"value":391},{"type":26,"tag":140,"props":4797,"children":4798},{"style":152},[4799],{"type":39,"value":4800},"--certificatesresolvers.letsencrypt.acme.httpchallenge=true\n",{"type":26,"tag":140,"props":4802,"children":4803},{"class":142,"line":412},[4804,4808],{"type":26,"tag":140,"props":4805,"children":4806},{"style":255},[4807],{"type":39,"value":391},{"type":26,"tag":140,"props":4809,"children":4810},{"style":152},[4811],{"type":39,"value":4812},"--certificatesresolvers.letsencrypt.acme.email=\u003Cyour_email_here>\n",{"type":26,"tag":140,"props":4814,"children":4815},{"class":142,"line":425},[4816,4820],{"type":26,"tag":140,"props":4817,"children":4818},{"style":255},[4819],{"type":39,"value":391},{"type":26,"tag":140,"props":4821,"children":4822},{"style":152},[4823],{"type":39,"value":4824},"--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json\n",{"type":26,"tag":140,"props":4826,"children":4827},{"class":142,"line":233},[4828,4832],{"type":26,"tag":140,"props":4829,"children":4830},{"style":255},[4831],{"type":39,"value":391},{"type":26,"tag":140,"props":4833,"children":4834},{"style":152},[4835],{"type":39,"value":4836},"--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web\n",{"type":26,"tag":140,"props":4838,"children":4839},{"class":142,"line":234},[4840],{"type":26,"tag":140,"props":4841,"children":4842},{"emptyLinePlaceholder":279},[4843],{"type":39,"value":282},{"type":26,"tag":140,"props":4845,"children":4846},{"class":142,"line":235},[4847,4851],{"type":26,"tag":140,"props":4848,"children":4849},{"style":255},[4850],{"type":39,"value":391},{"type":26,"tag":140,"props":4852,"children":4853},{"style":152},[4854],{"type":39,"value":4855},"--entrypoints.web.address=:80\n",{"type":26,"tag":140,"props":4857,"children":4858},{"class":142,"line":236},[4859,4863],{"type":26,"tag":140,"props":4860,"children":4861},{"style":255},[4862],{"type":39,"value":391},{"type":26,"tag":140,"props":4864,"children":4865},{"style":152},[4866],{"type":39,"value":4867},"--entrypoints.websecure.address=:443\n",{"type":26,"tag":140,"props":4869,"children":4870},{"class":142,"line":237},[4871],{"type":26,"tag":140,"props":4872,"children":4873},{"style":255},[4874],{"type":39,"value":4875},"      \n",{"type":26,"tag":140,"props":4877,"children":4878},{"class":142,"line":915},[4879,4883],{"type":26,"tag":140,"props":4880,"children":4881},{"style":255},[4882],{"type":39,"value":391},{"type":26,"tag":140,"props":4884,"children":4885},{"style":152},[4886],{"type":39,"value":4887},"--entrypoints.web.http.redirections.entrypoint.to=websecure\n",{"type":26,"tag":140,"props":4889,"children":4890},{"class":142,"line":621},[4891,4895],{"type":26,"tag":140,"props":4892,"children":4893},{"style":255},[4894],{"type":39,"value":391},{"type":26,"tag":140,"props":4896,"children":4897},{"style":152},[4898],{"type":39,"value":4899},"--entrypoints.web.http.redirections.entrypoint.scheme=https\n",{"type":26,"tag":140,"props":4901,"children":4902},{"class":142,"line":622},[4903,4907],{"type":26,"tag":140,"props":4904,"children":4905},{"style":255},[4906],{"type":39,"value":391},{"type":26,"tag":140,"props":4908,"children":4909},{"style":152},[4910],{"type":39,"value":4911},"--entrypoints.websecure.http.tls.certresolver=letsencrypt\n",{"type":26,"tag":140,"props":4913,"children":4914},{"class":142,"line":623},[4915],{"type":26,"tag":140,"props":4916,"children":4917},{"emptyLinePlaceholder":279},[4918],{"type":39,"value":282},{"type":26,"tag":140,"props":4920,"children":4921},{"class":142,"line":624},[4922,4926],{"type":26,"tag":140,"props":4923,"children":4924},{"style":255},[4925],{"type":39,"value":391},{"type":26,"tag":140,"props":4927,"children":4928},{"style":152},[4929],{"type":39,"value":4930},"--providers.docker\n",{"type":26,"tag":140,"props":4932,"children":4933},{"class":142,"line":996},[4934,4938],{"type":26,"tag":140,"props":4935,"children":4936},{"style":255},[4937],{"type":39,"value":391},{"type":26,"tag":140,"props":4939,"children":4940},{"style":152},[4941],{"type":39,"value":4942},"--providers.docker.defaultrule=Host(`{{ trimPrefix `app-` .Name }}.example.com`)\n",{"type":26,"tag":140,"props":4944,"children":4945},{"class":142,"line":1004},[4946,4950],{"type":26,"tag":140,"props":4947,"children":4948},{"style":255},[4949],{"type":39,"value":391},{"type":26,"tag":140,"props":4951,"children":4952},{"style":152},[4953],{"type":39,"value":4954},"--providers.docker.constraints=Label(`com.docker.compose.service`,`app`)\n",{"type":26,"tag":140,"props":4956,"children":4957},{"class":142,"line":1022},[4958,4962],{"type":26,"tag":140,"props":4959,"children":4960},{"style":249},[4961],{"type":39,"value":3035},{"type":26,"tag":140,"props":4963,"children":4964},{"style":255},[4965],{"type":39,"value":258},{"type":26,"tag":140,"props":4967,"children":4968},{"class":142,"line":625},[4969,4973],{"type":26,"tag":140,"props":4970,"children":4971},{"style":255},[4972],{"type":39,"value":391},{"type":26,"tag":140,"props":4974,"children":4975},{"style":152},[4976],{"type":39,"value":4977},"/var/run/docker.sock:/var/run/docker.sock:ro\n",{"type":26,"tag":140,"props":4979,"children":4980},{"class":142,"line":626},[4981,4985],{"type":26,"tag":140,"props":4982,"children":4983},{"style":255},[4984],{"type":39,"value":391},{"type":26,"tag":140,"props":4986,"children":4987},{"style":152},[4988],{"type":39,"value":4989},"/letsencrypt:/letsencrypt\n",{"type":26,"tag":35,"props":4991,"children":4992},{},[4993],{"type":39,"value":4994},"Erklären wir das ein wenig:",{"type":26,"tag":42,"props":4996,"children":4997},{},[4998,5011,5016,5021,5026],{"type":26,"tag":46,"props":4999,"children":5000},{},[5001,5003,5009],{"type":39,"value":5002},"Wir konfigurieren einen ",{"type":26,"tag":52,"props":5004,"children":5006},{"href":5005},"https://letsencrypt.org/",[5007],{"type":39,"value":5008},"Let's Encrypt",{"type":39,"value":5010}," Certificates Resolver (11-14)",{"type":26,"tag":46,"props":5012,"children":5013},{},[5014],{"type":39,"value":5015},"Wir hören auf Port 80 und 443 (16-17)",{"type":26,"tag":46,"props":5017,"children":5018},{},[5019],{"type":39,"value":5020},"Wir leiten den gesamten HTTP-Verkehr auf HTTPS um (19-20)",{"type":26,"tag":46,"props":5022,"children":5023},{},[5024],{"type":39,"value":5025},"Und binden den konfigurierten Certificates Resolver daran (21)",{"type":26,"tag":46,"props":5027,"children":5028},{},[5029],{"type":39,"value":5030},"Wir richten den Docker-Provider ein (23-25)",{"type":26,"tag":216,"props":5032,"children":5034},{"id":5033},"erklärung-für-die-zeilen-24-25",[5035],{"type":39,"value":5036},"Erklärung für die Zeilen 24-25",{"type":26,"tag":130,"props":5038,"children":5040},{"code":5039},"--providers.docker.defaultrule=Host(`{{ trimPrefix 'app-'.Name }}.example.com`)\n",[5041],{"type":26,"tag":108,"props":5042,"children":5043},{"__ignoreMap":7},[5044],{"type":39,"value":5039},{"type":26,"tag":2653,"props":5046,"children":5047},{},[5048,5081],{"type":26,"tag":46,"props":5049,"children":5050},{},[5051,5057,5059,5065,5067,5072,5074,5080],{"type":26,"tag":108,"props":5052,"children":5054},{"className":5053},[],[5055],{"type":39,"value":5056},".Name",{"type":39,"value":5058}," wird automatisch als ",{"type":26,"tag":108,"props":5060,"children":5062},{"className":5061},[],[5063],{"type":39,"value":5064},"\u003Cservice-name>-\u003Cstack_name>",{"type":39,"value":5066}," generiert. Für dein ",{"type":26,"tag":108,"props":5068,"children":5070},{"className":5069},[],[5071],{"type":39,"value":4280},{"type":39,"value":5073},"-Beispiel wäre das also ",{"type":26,"tag":108,"props":5075,"children":5077},{"className":5076},[],[5078],{"type":39,"value":5079},"app-whoami",{"type":39,"value":2773},{"type":26,"tag":46,"props":5082,"children":5083},{},[5084,5090,5092,5097],{"type":26,"tag":108,"props":5085,"children":5087},{"className":5086},[],[5088],{"type":39,"value":5089},"trimPrefix 'app-'.Name",{"type":39,"value":5091}," ergibt ",{"type":26,"tag":108,"props":5093,"children":5095},{"className":5094},[],[5096],{"type":39,"value":4280},{"type":39,"value":2773},{"type":26,"tag":5099,"props":5100,"children":5101},"br",{},[],{"type":26,"tag":130,"props":5103,"children":5104},{"code":4954},[5105],{"type":26,"tag":108,"props":5106,"children":5107},{"__ignoreMap":7},[5108],{"type":39,"value":4954},{"type":26,"tag":35,"props":5110,"children":5111},{},[5112,5114,5119,5121,5127,5129,5135],{"type":39,"value":5113},"Alle Dienste sollten standardmäßig verfügbar sein, aber sie sollten gefiltert werden, sodass nur ",{"type":26,"tag":108,"props":5115,"children":5117},{"className":5116},[],[5118],{"type":39,"value":4583},{"type":39,"value":5120},"-Dienste berücksichtigt werden. Das Label ",{"type":26,"tag":108,"props":5122,"children":5124},{"className":5123},[],[5125],{"type":39,"value":5126},"com.docker.compose.service",{"type":39,"value":5128}," wird von ",{"type":26,"tag":108,"props":5130,"children":5132},{"className":5131},[],[5133],{"type":39,"value":5134},"docker-compose",{"type":39,"value":5136}," automatisch zu allen Containern hinzugefügt.",{"type":26,"tag":96,"props":5138,"children":5140},{"id":5139},"bonus-konfiguration",[5141],{"type":39,"value":5142},"Bonus-Konfiguration",{"type":26,"tag":35,"props":5144,"children":5145},{},[5146],{"type":39,"value":5147},"Wir können diese Konfiguration noch weiter verfeinern.",{"type":26,"tag":216,"props":5149,"children":5151},{"id":5150},"andere-dienste-im-stack-verfügbar-machen",[5152],{"type":39,"value":5153},"Andere Dienste im Stack verfügbar machen",{"type":26,"tag":35,"props":5155,"children":5156},{},[5157],{"type":39,"value":5158},"Manchmal möchte man mehr als nur den App-Container nach außen hin öffnen.",{"type":26,"tag":35,"props":5160,"children":5161},{},[5162,5164,5169],{"type":39,"value":5163},"Die aktuelle Konfiguration leitet den Datenverkehr nur an unsere ",{"type":26,"tag":108,"props":5165,"children":5167},{"className":5166},[],[5168],{"type":39,"value":4583},{"type":39,"value":5170},"-Dienste weiter.\nUm weiterhin die Standard-Konfigurationsmethode nutzen zu können, müssen wir diese wieder aktivieren:",{"type":26,"tag":130,"props":5172,"children":5174},{"code":5173},"--providers.docker.constraints=Label(`com.docker.compose.service`,`app`) || Label(`traefik.enable`, `true`)\n",[5175],{"type":26,"tag":108,"props":5176,"children":5177},{"__ignoreMap":7},[5178],{"type":39,"value":5173},{"type":26,"tag":216,"props":5180,"children":5182},{"id":5181},"stack-name-weicht-vom-verzeichnisnamen-ab",[5183],{"type":39,"value":5184},"Stack-Name weicht vom Verzeichnisnamen ab",{"type":26,"tag":35,"props":5186,"children":5187},{},[5188,5190,5195],{"type":39,"value":5189},"Beim Deployment der Stacks wird der Name basierend auf dem Verzeichnisnamen generiert, in dem sich die ",{"type":26,"tag":108,"props":5191,"children":5193},{"className":5192},[],[5194],{"type":39,"value":4417},{"type":39,"value":5196}," Datei befindet.\nWir können den Namen auf verschiedene Arten ändern, aber hier ist die einfachste:",{"type":26,"tag":130,"props":5198,"children":5202},{"code":5199,"filename":5200,"highlights":5201,"language":238,"meta":7,"className":239,"style":7},"name: whoami # Projektname manuell setzen\nservices:\n  app:\n    image: traefik/whoami\n","whoami-example/docker-compose.yaml",[143],[5203],{"type":26,"tag":108,"props":5204,"children":5205},{"__ignoreMap":7},[5206,5227,5238,5249],{"type":26,"tag":140,"props":5207,"children":5209},{"class":5208,"line":143},[142,312],[5210,5214,5218,5222],{"type":26,"tag":140,"props":5211,"children":5212},{"style":249},[5213],{"type":39,"value":772},{"type":26,"tag":140,"props":5215,"children":5216},{"style":255},[5217],{"type":39,"value":323},{"type":26,"tag":140,"props":5219,"children":5220},{"style":152},[5221],{"type":39,"value":4280},{"type":26,"tag":140,"props":5223,"children":5224},{"style":2833},[5225],{"type":39,"value":5226}," # Projektname manuell setzen\n",{"type":26,"tag":140,"props":5228,"children":5229},{"class":142,"line":261},[5230,5234],{"type":26,"tag":140,"props":5231,"children":5232},{"style":249},[5233],{"type":39,"value":2978},{"type":26,"tag":140,"props":5235,"children":5236},{"style":255},[5237],{"type":39,"value":258},{"type":26,"tag":140,"props":5239,"children":5240},{"class":142,"line":275},[5241,5245],{"type":26,"tag":140,"props":5242,"children":5243},{"style":249},[5244],{"type":39,"value":4623},{"type":26,"tag":140,"props":5246,"children":5247},{"style":255},[5248],{"type":39,"value":258},{"type":26,"tag":140,"props":5250,"children":5251},{"class":142,"line":285},[5252,5256,5260],{"type":26,"tag":140,"props":5253,"children":5254},{"style":249},[5255],{"type":39,"value":3001},{"type":26,"tag":140,"props":5257,"children":5258},{"style":255},[5259],{"type":39,"value":323},{"type":26,"tag":140,"props":5261,"children":5262},{"style":152},[5263],{"type":39,"value":4186},{"type":26,"tag":2428,"props":5265,"children":5266},{},[5267],{"type":39,"value":2432},{"title":7,"searchDepth":261,"depth":261,"links":5269},[5270,5271,5274],{"id":4344,"depth":261,"text":4347},{"id":4440,"depth":261,"text":4443,"children":5272},[5273],{"id":5033,"depth":275,"text":5036},{"id":5139,"depth":261,"text":5142,"children":5275},[5276,5277],{"id":5150,"depth":275,"text":5153},{"id":5181,"depth":275,"text":5184},{"_path":2474,"_dir":2475,"_draft":6,"_partial":6,"_locale":7,"slug":10,"teams":5279,"primaryTeam":2478,"firstName":2479,"lastName":2480,"prefixTitle":7,"suffixTitle":2481,"education":5280,"role":5282,"workingSince":2492,"inTheCompanySince":2493,"techSkills":5283,"skills":5297,"projects":5307,"contactDetails":5312,"_image":2564,"image":2565,"_id":2566,"_type":2567,"title":2568,"_source":2475,"_file":2569,"_stem":2570,"_extension":2567},[2477,2478],[5281],[2484,2485,2486],[2488,2489,2490,2491],[5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296],{"name":2496,"level":2497,"icon":2498},{"name":2500,"level":2497},{"name":2502,"level":2497,"icon":2503},{"name":2505,"level":2497,"icon":2506},{"name":2508,"level":2497,"icon":2509},{"name":2511,"level":2497},{"name":2513,"level":2497,"icon":2514},{"name":2516,"level":2497,"icon":2517},{"name":2519,"level":2520,"icon":2521},{"name":2523,"level":2520,"icon":2524},{"name":2526,"level":2520},{"name":2528,"level":2520,"icon":2529},{"name":2531,"level":2520,"icon":2532},[5298,5299,5300,5301,5302,5303,5304,5305,5306],{"name":113,"level":2497},{"name":2536,"level":2497},{"name":2478,"level":2497},{"name":2539,"level":2497},{"name":2541,"level":2497},{"name":2543,"level":2520},{"name":2545,"level":2520},{"name":2547,"level":2520},{"name":2549,"level":2520},[5308,5310,5311],{"project":2552,"position":5309},[2554,2555],{"project":2557,"position":2555},{"project":2559,"position":2555},{"eMail":2561,"phone":2562,"visibility":2563},1782284045365]