docker: inject config files into containers via extra_configs

Add an `extra_configs` field (list of {target, content}) to the docker
node/template/appliance schemas. For each entry GNS3 writes `content` to a
file in the node working directory and bind-mounts it read-only at `target`
inside the container.

This lets a NOS appliance seed its startup config without rebuilding the
image: XRd points XR_FIRST_BOOT_CONFIG at an injected /firstboot.cfg, FRR at
/etc/frr/frr.conf, etc. The bind is a single-file mount applied at create
time, so it works for both the generic init.sh path and vendor nodes that
skip init.sh (console_type=docker_exec). Entries are only injected when
present, so ordinary nodes are unaffected.

The content can't go through `environment` (it is line-delimited, one var per
line), hence a dedicated field -- the same plumbing shape as extra_volumes.
This commit is contained in:
YueGuobin committed 2026-08-13 23:33:34 +08:00
1 parent 2bee34031c
commit 08e37a4509
7 files changed
+98 -3

No files matched your search

@@ -16,7 +16,7 @@
from . import Category, TemplateBase
from ...common import ConsoleType, AuxType, CustomAdapter
from ...common import ConsoleType, AuxType, CustomAdapter, ExtraConfig
from pydantic import Field
from typing import Optional, List
@@ -49,6 +49,7 @@ class DockerTemplate(TemplateBase):
)
extra_hosts: Optional[str] = Field("", description="Docker extra hosts (added to /etc/hosts)")
extra_volumes: Optional[List] = Field([], description="Additional directories to make persistent")
extra_configs: Optional[List[ExtraConfig]] = Field(default_factory=list, description="Configuration files injected into the container (bind-mounted read-only)")
memory: Optional[int] = Field(0, ge=0, description="Maximum amount of memory the container can use in MB")
cpus: Optional[float] = Field(0, ge=0, description="Maximum amount of CPU resources the container can use")
custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters")