patchesStrategicMerge

• For similar examples, refer to the Kustomize documentation on patchesstrategicmerge.

• Example files are available in the Kompozit GitHub repository.

This patching method is based on the Strategic Merge Patch from Kubernetes. Kompozit internally uses the deepmerge module to apply these patches. Unlike patchesJSON6902, patchesStrategicMerge allows you to define your patch in a separate file, making it easier to customize your configurations.

For example, the patch file overlay/public_wordpress/docker-compose-traefik-patch.yml might look like this:

```
services:
  traefik:
    command:
      - "--log.level=INFO"
      - "--api.insecure=false"
      - "--api.dashboard=false"
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--global.sendAnonymousUsage=false"
      - "--global.checkNewVersion=false"
      # ---------------------------------- ACME --------------------------------------------
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=5"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=${MY_PROVIDER}"
      - "--certificatesresolvers.letsencrypt.acme.email=mail@mail.com"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.disablePropagationCheck=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      # -------------------------------- ENTRYPOINT -----------------------------------------
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      # -------------------------------- PROXY -----------------------------------------
      - "--entryPoints.web.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
      - "--entryPoints.web.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
      - "--entryPoints.websecure.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
      - "--entryPoints.websecure.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
      - "--entryPoints.web.forwardedHeaders.insecure=false"
      - "--entryPoints.web.proxyProtocol.insecure=false"
      - "--entryPoints.websecure.forwardedHeaders.insecure=false"
      - "--entryPoints.websecure.proxyProtocol.insecure=false"
      # -------------------------------- PLUGINS -----------------------------------------
      - --experimental.plugins.fail2ban.modulename=github.com/juitde/traefik-plugin-fail2ban
      - --experimental.plugins.fail2ban.version=v0.2.0
      - --experimental.plugins.fail2ban.modulename=github.com/Paxxs/traefik-get-real-ip
      - --experimental.plugins.fail2ban.version=v1.0.2
    labels:
      - com.centurylinklabs.watchtower.enable=true
      - traefik.enable=true
      - traefik.docker.network=traefik_public
      - traefik.http.routers.api.tls=true
      - traefik.http.routers.api.entryPoints=websecure
      - traefik.http.routers.api.service=api@internal
      - traefik.http.routers.api.tls.certresolver=letsencrypt
      - traefik.http.routers.api.rule=Host(`${MY_DOMAIN}`)
```

Result After Applying the Patch

$ kompozit -b overlay/public_wordpress/
---
networks:
  public:
    attachable: true
    internal: false
  private:
    attachable: true
    internal: true
volumes:
  acme: null
services:
  traefik:
    image: traefik:latest
    hostname: traefik
    container_name: traefik
    restart: unless-stopped
    environment:
      DUCKDNS_TOKEN: ${DUCKDNS_TOKEN}
      CLOUDFLARE_DNS_API_TOKEN: ${CLOUDFLARE_DNS_API_TOKEN}
    ports:
    - 80:80/tcp
    - 443:443/tcp
    networks:
    - public
    - private
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - acme:/letsencrypt
    command:
    - --log.level=INFO
    - --api.insecure=false
    - --api.dashboard=false
    - --providers.docker=true
    - --providers.docker.exposedByDefault=false
    - --global.sendAnonymousUsage=false
    - --global.checkNewVersion=false
    - --certificatesresolvers.letsencrypt.acme.dnschallenge=true
    - --certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=5
    - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=${MY_PROVIDER}
    - --certificatesresolvers.letsencrypt.acme.email=mail@mail.com
    - --certificatesresolvers.letsencrypt.acme.dnschallenge.disablePropagationCheck=true
    - --certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53
    - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    - --entrypoints.web.address=:80
    - --entrypoints.web.http.redirections.entrypoint.to=websecure
    - --entrypoints.web.http.redirections.entrypoint.scheme=https
    - --entrypoints.websecure.address=:443
    - --entryPoints.web.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
    - --entryPoints.web.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
    - --entryPoints.websecure.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
    - --entryPoints.websecure.proxyProtocol.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7
    - --entryPoints.web.forwardedHeaders.insecure=false
    - --entryPoints.web.proxyProtocol.insecure=false
    - --entryPoints.websecure.forwardedHeaders.insecure=false
    - --entryPoints.websecure.proxyProtocol.insecure=false
    - --experimental.plugins.fail2ban.modulename=github.com/juitde/traefik-plugin-fail2ban
    - --experimental.plugins.fail2ban.version=v0.2.0
    - --experimental.plugins.fail2ban.modulename=github.com/Paxxs/traefik-get-real-ip
    - --experimental.plugins.fail2ban.version=v1.0.2
    labels:
    - com.centurylinklabs.watchtower.enable=true
    - traefik.enable=true
    - traefik.docker.network=traefik_public
    - traefik.http.routers.api.tls=true
    - traefik.http.routers.api.entryPoints=websecure
    - traefik.http.routers.api.service=api@internal
    - traefik.http.routers.api.tls.certresolver=letsencrypt
    - traefik.http.routers.api.rule=Host(`${MY_DOMAIN}`)

Caveat

To determine which patch file should be applied to which specific resource, the patch file name must match the resource file name in the base configuration. For instance, if your base resource file is named docker-compose-traefik.yml, the corresponding patch file should be named docker-compose-traefik-patch.yml.

The matching logic can be summarized as:

if resource_base_file == patch_base_file.replace("-patch", ""):
    patch_data = load_yaml(patch["path"])
    resource_data = CUSTOM_MERGER.merge(resource_data, patch_data)

Last updated