Files
Das-OS/srcpkgs/deployer/files/python/deployer/kinds/docker.py
T
dasandClaude Sonnet 5.5 62b8b98086 Fix pale Wi-Fi/Bluetooth tray icons, das-panel-icon help, publisher and deployer (0.9.5)
- Light theme uses Papirus-Light: the panel icons of Papirus are #dfdfdf,
  made for dark panels (xsettings, theme index, login screen).
- das-panel-icon help/-h/--help print usage instead of setting an icon;
  unknown options are rejected.
- New packages publisher (publish) and deployer (deploy) on the desktop
  image: config in ~/.config/<name>/ (neutral example copied on first run),
  history in ~/.local/state/<name>/.
- das-theme 0.3.0, das-settings 0.6.0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 14:44:36 +02:00

69 lines
2.7 KiB
Python

"""docker: compose project in ~/app/docker/<app>, .env linked from configs/docker/<app>.env."""
from __future__ import annotations
import shlex
from pathlib import Path, PurePosixPath
from .. import remote
from ..config import App, Config
from .base import Kind, Plan, health_extra, register
_UP = r'''
cd "$DEST" || exit 1
if [ ! -e Makefile ] && [ ! -L Makefile ] && [ -f "$APPROOT/docker/Makefile" ] && [ "$(dirname "$DEST")" = "$APPROOT/docker" ]; then
ln -s "$APPROOT/docker/Makefile" Makefile && echo "linked Makefile"
fi
docker compose config -q || exit 1
if [ "$RESTART" = 1 ]; then docker compose up -d --build --remove-orphans; else docker compose build; fi
'''
_HEALTH = r'''
cd "$DEST" || exit 1
start=$SECONDS; end=$((SECONDS + TIMEOUT))
while :; do
ps=$(docker compose ps -a --format '{{.Name}} {{.State}} {{.Health}}')
bad=$(echo "$ps" | awk '$2=="exited" || $2=="dead" || $3=="unhealthy"')
if [ -n "$bad" ]; then echo "$ps"; docker compose logs --tail 30; exit 1; fi
wait=$(echo "$ps" | awk 'NF && ($2!="running" || ($3!="" && $3!="healthy"))')
if [ -z "$wait" ] && [ $SECONDS -ge $((start + 6)) ]; then echo "$ps"; exit 0; fi
[ $SECONDS -lt $end ] || { echo "$ps"; echo "not ready after ${TIMEOUT}s"; exit 1; }
sleep 3
done
'''
@register
class Docker(Kind):
name = "docker"
protected = (".env", "data", "Makefile")
def config_items(self, plan: Plan) -> list[tuple[str, str]]:
app = PurePosixPath(plan.dest).name
root = f"{plan.cfg.server.configs_root}/docker"
return [(".env", f"{root}/{app}.env")] + [(n, f"{root}/{app}/{n}") for n in plan.app.configs]
def local_config(self, plan: Plan, name: str) -> Path:
p = plan.app.src_path / name
if name == ".env" and not p.exists():
return plan.app.src_path / ".env.example"
return p
def install(self, plan: Plan, log) -> None:
remote.run(plan.server, _UP, log, DEST=plan.dest, APPROOT=plan.cfg.server.app_root,
RESTART=int(plan.opts.restart))
def health(self, plan: Plan, log) -> bool:
try:
remote.run(plan.server, _HEALTH, log, DEST=plan.dest, TIMEOUT=plan.app.health_timeout)
except remote.RemoteError:
return False
return health_extra(plan, log)
def status_script(self) -> str:
return ('cd "$DEST" 2>/dev/null || { echo missing; exit; }; '
't=$(docker compose ps -a -q 2>/dev/null | wc -l); r=$(docker compose ps -q --status running 2>/dev/null | wc -l); '
'[ "$t" -gt 0 ] && echo "running $r/$t" || echo stopped')
def logs_command(self, cfg: Config, app: App, dest: str) -> str:
return f"cd {shlex.quote(dest)} && docker compose logs -f --tail=100"