docker mode: allow username override

This commit is contained in:
GitHub Copilot
2026-01-29 19:46:46 +00:00
parent 64f2a8a3be
commit 6845fe45b7
4 changed files with 41 additions and 0 deletions
+9
View File
@@ -107,6 +107,15 @@ When a container starts with either label, it automatically appears in the dashb
Containers that only specify `webterm-theme` are still included and use the default auto command. Containers that only specify `webterm-theme` are still included and use the default auto command.
**Environment Variables:**
- `WEBTERM_DOCKER_USERNAME` - Set to run Docker exec sessions as a specific user (default: root)
- `WEBTERM_DOCKER_AUTO_COMMAND` - Override the default `auto` command (default: `tmux new-session -As webterm`)
Example: Start containers and exec into them as `developer` user:
```bash
WEBTERM_DOCKER_USERNAME=developer webterm --docker-watch
```
Example docker-compose.yaml: Example docker-compose.yaml:
```yaml ```yaml
+3
View File
@@ -43,6 +43,7 @@ DA_PARTIAL_PATTERN = re.compile(rb"\x1b(?:\[(?:\?[\d;]*)?)?$")
class DockerExecSpec: class DockerExecSpec:
container: str container: str
command: list[str] command: list[str]
user: str | None = None
class DockerExecSession(Session): class DockerExecSession(Session):
@@ -162,6 +163,8 @@ class DockerExecSession(Session):
"Tty": True, "Tty": True,
"Cmd": self.exec_spec.command, "Cmd": self.exec_spec.command,
} }
if self.exec_spec.user:
payload["User"] = self.exec_spec.user
response = self._request_json( response = self._request_json(
"POST", f"/containers/{self.exec_spec.container}/exec", payload "POST", f"/containers/{self.exec_spec.container}/exec", payload
) )
+3
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import asyncio import asyncio
import logging import logging
import os
import shlex import shlex
import sys import sys
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@@ -137,9 +138,11 @@ class SessionManager:
log.warning("Sorry, webterm does not currently support terminals on Windows") log.warning("Sorry, webterm does not currently support terminals on Windows")
return None return None
if app.command == AUTO_COMMAND_SENTINEL: if app.command == AUTO_COMMAND_SENTINEL:
docker_user = os.environ.get("WEBTERM_DOCKER_USERNAME")
exec_spec = DockerExecSpec( exec_spec = DockerExecSpec(
container=app.name, container=app.name,
command=shlex.split(_get_auto_command()), command=shlex.split(_get_auto_command()),
user=docker_user,
) )
session_process = DockerExecSession(self.poller, session_id, exec_spec) session_process = DockerExecSession(self.poller, session_id, exec_spec)
else: else:
+26
View File
@@ -214,6 +214,32 @@ class TestSessionManager:
assert result is not None assert result is not None
assert isinstance(result, DockerExecSession) assert isinstance(result, DockerExecSession)
assert result.exec_spec.user is None
async def test_new_docker_exec_session_with_user(self, mock_poller, mock_path, monkeypatch):
from webterm.docker_exec_session import DockerExecSession
monkeypatch.setenv("WEBTERM_DOCKER_USERNAME", "testuser")
app = App(
name="my-container",
slug="my-container",
path="./",
command=AUTO_COMMAND_SENTINEL,
terminal=True,
)
manager = SessionManager(mock_poller, mock_path, [app])
with patch.object(DockerExecSession, "open", new_callable=AsyncMock):
result = await manager.new_session(
"my-container",
SessionID("test-session"),
RouteKey("test-route"),
)
assert result is not None
assert isinstance(result, DockerExecSession)
assert result.exec_spec.user == "testuser"
class TestSessionManagerRoutes: class TestSessionManagerRoutes: