Skip to content

Move Docker Compose adjustments into the model

When tuning a TeskaLabs LogMan.io deployment, you sometimes start from a docker-compose.yaml, change values until the stack behaves as you want, then need those same changes in /Site/model.yaml so they survive the next Apply and are not overwritten.

Workflow

  1. Adjust the compose file (or a copy) and confirm the containers run correctly.
  2. Diff against what you had before and list only what you changed. Ignore identities Maestro always injects (see below).
  3. Translate each change into the model under services.<service-id> using a descriptor: block (service-wide or under one instance). Use version: when you only need a different image tag from the version file.
  4. Apply the model from the Library and roll out (gov.sh up or Apply button in the UI).

What you usually do not put in the model

Maestro / ASAB Remote Control generates these for you. Copying them into the model is redundant and can fight the generator:

  • container_name, hostname
  • labels such as instance_id, node_id, service_id, com.teskalabs.asab.*
  • environment entries that identify the instance (INSTANCE_ID, NODE_ID, SERVICE_ID) unless your descriptor explicitly expects an override
  • The standard hosts mount {{SITE}}/hosts:/etc/hosts:ro (comes from the projection layer)

Keep overrides for your tuning: extra env vars, extra mounts, resource limits, health checks, image tag, and similar.

Example: ZooKeeper memory and JVM heap

Suppose after testing you want a higher memory limit and matching JVM heap for ZooKeeper. In compose you might have arrived at something like this:

  zookeeper-1:
    command:
    - zkServer.sh
    - start-foreground
    container_name: zookeeper-1
    deploy:
      resources:
        limits:
          memory: 2g             <--------------------------------------- change here
    entrypoint:
    - /bin/bash
    - -e
    - /confro/zkstart.sh
    environment:
      INSTANCE_ID: zookeeper-1
      JVMFLAGS: -Xms1g -Xmx1g    <--------------------------------------- change here
      NODE_ID: fu01
      SERVICE_ID: zookeeper
      ZK_SERVER_HEAP: '2000'
      ZOO_MY_ID: '1'
    healthcheck:
      interval: 60s
      retries: 5
      start_period: 30s
      test:
      - CMD-SHELL
      - echo ruok | nc 127.0.0.1 2181 || exit -1
      - 'echo srvr | nc 127.0.0.1 2181 | grep ''^Mode: '' || exit -1'
      timeout: 10s
    hostname: zookeeper-1
    image: library/zookeeper:3.9
    labels:
      com.teskalabs.asab.fdigest: 48810a467d869a736c17a88dc2211d186c23d108c35b5b8d12767f730f0f85ff
      com.teskalabs.asab.maestro: managed
      com.teskalabs.asab.version: '3.9'
      instance_id: zookeeper-1
      node_id: node1
      service_id: zookeeper
    logging:
      driver: syslog
      options:
        syslog-address: udp://localhost:9911
        syslog-facility: daemon
        syslog-format: rfc5424
        tag: instance_id=zookeeper-1,service_id=zookeeper,node_id=fu01

In model.yaml, express the same intent under the zookeeper service using descriptor. This example applies to all instances of zookeeper service:

services:
  zookeeper:
    descriptor:
      environment:
        JVMFLAGS: "-Xms1g -Xmx1g"
      deploy:
        resources:
          limits:
            memory: 2g
    instances:
      1:
        node: node1
      2:
        node: node2
      3:
        node: node3

The projected compose service name will still be zookeeper-1, zookeeper-2, and so on; you configure by service id (zookeeper) and instance number, not by the final container name.

Example: extra bind mount on lmio-watcher

You added a read-only folder so the watcher can scan a custom library path:

in docker-compose.yaml:

  lmio-watcher-1:
    volumes:
      - /opt/custom/library:/library-custom:ro

in model.yaml:

services:
  lmio-watcher:
    instances:
      1:
        node: node1
        descriptor:
          volumes:
            - "/data/custom/library:/library-custom:ro"

New volumes entries are merged with the descriptor according to the merge algorithm (lists are combined). If your change replaces a volume the descriptor already defines, coordinate with the exact entry from the descriptor file so the merge does what you expect.

Example: version instead of full descriptor.image

Compose shows a concrete tag:

in docker-compose.yaml:

  lmio-watcher-1:
    image: docker.teskalabs.com/lmio/lmio-watcher:v26.12-beta4

If the only change is which tag to run, set version in the model (see Versions) instead of duplicating the full image name:

in model.yaml:

services:
  lmio-watcher:
    instances: fu01
    version: v26.12-beta4

Use descriptor.image only when you must point to an image the version file does not cover.