Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ COPY --chmod=0755 --from=uv_source /usr/local/bin/uv /usr/local/bin/uvx /usr/loc

WORKDIR /opt/hermes

RUN groupadd --gid 1000 hermes && \
useradd --uid 1000 --gid 1000 --shell /bin/bash --create-home hermes && \
chown -R hermes:hermes /opt/hermes
RUN mkdir -p /opt/data && chown hermes:hermes /opt/data

USER hermes:hermes

# ---------- Layer-cached dependency install ----------
# Copy only package manifests first so npm install + Playwright are cached
# unless the lockfiles themselves change.
Expand Down
23 changes: 14 additions & 9 deletions tools/environments/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,22 +618,27 @@ def _storage_opt_supported() -> bool:
def cleanup(self):
"""Stop and remove the container. Bind-mount dirs persist if persistent=True."""
if self._container_id:
container_id = self._container_id
try:
# Stop in background so cleanup doesn't block
stop_cmd = (
f"(timeout 60 {self._docker_exe} stop {self._container_id} || "
f"{self._docker_exe} rm -f {self._container_id}) >/dev/null 2>&1 &"
# Stop in background so cleanup doesn't block.
# Use list-form subprocess to avoid shell injection risk.
subprocess.Popen(
[self._docker_exe, "stop", container_id],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
subprocess.Popen(stop_cmd, shell=True)
except Exception as e:
logger.warning("Failed to stop container %s: %s", self._container_id, e)
logger.warning("Failed to stop container %s: %s", container_id, e)

if not self._persistent:
# Also schedule removal (stop only leaves it as stopped)
# Schedule removal after stop completes.
try:
subprocess.Popen(
f"sleep 3 && {self._docker_exe} rm -f {self._container_id} >/dev/null 2>&1 &",
shell=True,
[self._docker_exe, "rm", "-f", container_id],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
except Exception:
pass
Expand Down
Loading