-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDockerfile.integrated
More file actions
100 lines (85 loc) · 4.03 KB
/
Copy pathDockerfile.integrated
File metadata and controls
100 lines (85 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Integrated WebATM image: bundles the BlueSky simulator so the container can
# run `bluesky --headless` itself, and ships the server lifecycle controls +
# live log-streaming UI. Build with:
#
# docker build -f Dockerfile.integrated -t webatm-integrated .
#
# The default `Dockerfile` is intentionally left untouched so the standard
# image is unaffected by this variant.
FROM debian:bookworm-slim
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
git \
curl \
ca-certificates \
procps \
fonts-dejavu-core \
fonts-liberation \
fontconfig \
&& rm -rf /var/lib/apt/lists/*
# Install uv for fast Python package management
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Create application user and set working directory
RUN useradd -m -s /bin/bash webatm
USER webatm
WORKDIR /home/webatm
# Project virtual environment. uv manages it from pyproject.toml + uv.lock and
# provisions the CPython interpreter required by `requires-python` automatically.
ENV VIRTUAL_ENV="/home/webatm/.local/webatm-venv"
ENV UV_PROJECT_ENVIRONMENT="$VIRTUAL_ENV"
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# Install the locked production dependencies for the core webatm stack (flask,
# gunicorn, ...). Copying only the lock metadata first keeps this
# layer cached across source changes; --no-install-project skips building the
# app itself (run from PYTHONPATH below), --no-dev drops dev tooling, and
# --extra prod pulls in gunicorn. The integrated package and the
# bundled BlueSky simulator are installed separately below.
COPY --chown=webatm:webatm pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project --extra prod
# Install Node.js for TypeScript build
USER root
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/*
# Copy sources (core package, frontend, and the integrated package)
USER webatm
WORKDIR /home/webatm
COPY --chown=webatm:webatm WebATM/ ./WebATM/
COPY --chown=webatm:webatm frontend/ ./frontend/
COPY --chown=webatm:webatm WebATM-integrated/ ./WebATM-integrated/
# Build the frontend WITH integrated features enabled; output lands in
# WebATM/static/dist/. The frontend/ directory is build-only.
WORKDIR /home/webatm/frontend
RUN npm ci && npm run build:integrated
WORKDIR /home/webatm
RUN rm -rf frontend
# Install the integrated package, which also pulls the BlueSky simulator from
# its (public) git source. The core `webatm` package is provided on PYTHONPATH
# below rather than installed, so it is not a declared dependency.
RUN uv pip install ./WebATM-integrated
COPY --chown=webatm:webatm WebATM.py ./
COPY --chown=webatm:webatm script/wsgi_integrated.py ./
# Expose web server port
EXPOSE 8082
# Integrated build defaults: enable the extensions, run BlueSky locally.
# WEBATM_THREADS sizes the gthread pool (see CMD): under Socket.IO each
# connected browser holds one worker thread for the life of its connection, so
# this is effectively the cap on concurrent clients. 4 suits a single user;
# raise it for many concurrent viewers (the demo-deploy stack uses 16).
ENV WEB_HOST=0.0.0.0 \
WEB_PORT=8082 \
WEBATM_INTEGRATED=1 \
WEBATM_THREADS=4 \
BLUESKY_SERVER_HOST=localhost
# Add current directory to Python path so the WebATM package can be found
ENV PYTHONPATH="/home/webatm"
# Start WebATM with gunicorn using a THREADED worker: the integrated build
# reads a blocking subprocess pipe in a background thread.
# --threads is read from WEBATM_THREADS so the concurrency cap can be raised at
# `docker run` time (-e WEBATM_THREADS=16) without overriding this whole CMD.
# Shell form so WEB_HOST / WEB_PORT / WEBATM_THREADS env vars are honored; exec
# keeps gunicorn as PID 1 so it receives signals directly and can reap the
# bluesky group.
CMD ["sh", "-c", "exec gunicorn --worker-class gthread --threads ${WEBATM_THREADS:-4} -w 1 --bind ${WEB_HOST:-0.0.0.0}:${WEB_PORT:-8082} wsgi_integrated:app"]