Skip to content

Commit 71f4cd3

Browse files
committed
feat(docker): add Docker relay driver
Add DockerDriver for deploying chatmail relays via Docker Compose inside LXC containers (Docker-in-LXC with security.nesting). Features: - Pull pre-built images from GHCR (--source ghcr:TAG) - Inject local builds - Healthcheck polling / log streaming - SSH forwarding into Docker containers (for test compatibility) - DNS zone extraction and PowerDNS loading - security.privileged fenced behind CI=true CLI subcommands: deploy, pull, logs, ps, shell
1 parent cb3315a commit 71f4cd3

5 files changed

Lines changed: 872 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## [Unreleased]
4+
5+
### Features
6+
7+
- Docker deployment via GHCR pull, host image inject, or local tarball
8+
9+
### CI
10+
11+
- ci: `lxc-test` reusable workflow: support `cmlxc_ref` input to test
12+
feature branches; split cache restore/save.
13+
314
## [0.14.7] - 2026-05-11
415

516
### CI

README.md

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ Each `deploy-*` invocation initialises the driver's source in the
8181
builder (wipe-and-reclone).
8282

8383

84+
**Deploy via Docker Compose** (runs chatmail inside Docker-in-LXC):
85+
86+
# Pull a pre-built image directly from GHCR
87+
cmlxc docker deploy --source ghcr:main dk0
88+
cmlxc docker deploy --source ghcr:sha-ce05b26 dk0
89+
90+
# Load a local image tarball
91+
cmlxc docker deploy --image ./chatmail.tar dk0
92+
93+
# Inject a locally-built image from the host Docker daemon
94+
cmlxc docker deploy --source docker:chatmail-relay:latest dk0
95+
96+
Pull a newer image into an already-deployed relay:
97+
98+
cmlxc docker pull dk0
99+
cmlxc docker pull dk0 --tag sha-ce05b26
100+
101+
Inspect running services and logs:
102+
103+
cmlxc docker ps dk0
104+
cmlxc docker logs dk0
105+
cmlxc docker logs dk0 -f
106+
107+
SSH into a Docker service (auto-configured by ``cmlxc``):
108+
109+
ssh chatmail@dk0.localchat
110+
111+
84112
**Run integration tests** inside the builder:
85113

86114
cmlxc test-mini cm0
@@ -167,13 +195,14 @@ the host only needs `cmlxc` itself.
167195

168196
**Relay containers** (e.g. `cm0-localchat`, `mad1-localchat`) --
169197
ephemeral containers that receive a deployed chatmail service.
170-
Each relay is locked to a single deployment driver (`cmdeploy` or
171-
`madmail`); switching requires destroying and re-creating the container.
198+
Each relay is locked to a single deployment driver (`cmdeploy`,
199+
`madmail`, or `docker`); switching requires destroying and re-creating
200+
the container.
172201

173202

174203
### Deployment drivers
175204

176-
Drivers live in `driver_cmdeploy.py` and `driver_madmail.py`.
205+
Drivers live in `driver_cmdeploy.py`, `driver_madmail.py`, and `driver_docker.py`.
177206
Each driver module exports its CLI subcommand metadata,
178207
builder init, and deploy orchestration.
179208
`cli.py` generates the `deploy-*` subcommands from a `DRIVER_BY_NAME` mapping.
@@ -187,6 +216,45 @@ builder init, and deploy orchestration.
187216
pushes it via SCP and runs `madmail install --simple --ip <IP>`.
188217
No DNS entries are needed.
189218

219+
- **docker** -- deploys chatmail via Docker Compose inside a Docker-in-LXC
220+
relay container (`security.nesting=true`), either directly pulled from GHCR or
221+
injected from a host docker instance. Docker is installed inside the relay
222+
automatically; no host Docker installation is required.
223+
224+
#### Docker subcommands
225+
226+
- `docker deploy RELAY` -- deploy chatmail into a relay container via
227+
Docker Compose. Three image sources are supported:
228+
- `--source ghcr:TAG` -- pull a pre-built image from GHCR directly
229+
into the relay. No builder container is involved.
230+
- `--source docker:TAG` -- pipe a locally-built image from the host
231+
Docker daemon into the relay via `docker save | docker load`.
232+
- `--image PATH` -- load a pre-exported image tarball.
233+
A docker-compose.yaml is fetched from
234+
[chatmail/docker](https://github.com/chatmail/docker) unless
235+
`--compose URL` overrides the source.
236+
237+
- `docker pull RELAY` -- pull a newer image from GHCR into an already
238+
deployed relay without a full redeploy. Use `--tag` to specify the
239+
image tag (default: `main`).
240+
241+
- `docker ps RELAY` -- list running Docker Compose services in a relay.
242+
243+
- `docker logs RELAY` -- show Docker Compose logs (last 100 lines).
244+
Pass `-f` to follow in real time.
245+
246+
- `docker shell RELAY [SERVICE]` -- open an interactive shell inside
247+
the named Compose service (default: `chatmail`).
248+
249+
#### SSH into Docker services
250+
251+
For Docker-deployed relays, `cmlxc` auto-generates SSH config entries for
252+
each running Compose service. After any deploy or `cmlxc status`, you can:
253+
254+
ssh chatmail@dk0.localchat
255+
256+
This uses `ProxyCommand` to run `docker exec` inside the LXC container.
257+
190258

191259
## Releasing
192260

src/cmlxc/driver_cmdeploy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
CMDEPLOY = "cmdeploy"
1414

1515

16-
def run_cmdeploy_pytest(driver, second_domain=None):
16+
def run_test_cmdeploy(driver, second_domain=None):
1717
"""Run the cmdeploy pytest suite via incus exec on the builder.
1818
1919
Shared by CmdeployDriver and DockerDriver.
@@ -131,7 +131,7 @@ def run_tests(self, second_domain=None):
131131
write_ini(
132132
self.bld_ct, self.ct, domain, disable_ipv6=self.ct.is_ipv6_disabled
133133
)
134-
return run_cmdeploy_pytest(self, second_domain)
134+
return run_test_cmdeploy(self, second_domain)
135135

136136
def deploy(self, source=None):
137137
"""Deploy chatmail services to a single relay via cmdeploy."""

0 commit comments

Comments
 (0)