FROM node:24-alpine AS frontend-builder WORKDIR /frontend COPY ./frontend/package.json ./frontend/yarn.lock ./ RUN yarn install --frozen-lockfile COPY ./frontend/ ./ RUN yarn build FROM python:3.14-slim #################################################################### # ARG and ENV #################################################################### ARG USER_ID=1000 ARG GROUP_ID=1000 ARG USER_NAME=oxpanel ARG GROUP_NAME=oxpanel ARG NODE_VERSION=24 ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ LANG=C.UTF-8 \ LC_ALL=C.UTF-8 \ UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ USER_DIR="/app" #################################################################### # System dependencies #################################################################### #RUN apt update && apt install -y gcc graphviz graphviz-dev pkg-config libpq-dev g++ supervisor RUN apt-get update && apt-get install -y \ ca-certificates \ curl \ gnupg \ inotify-tools \ && rm -rf /var/lib/apt/lists/* RUN mkdir -p /etc/apt/keyrings \ && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_VERSION}.x nodistro main" \ > /etc/apt/sources.list.d/nodesource.list \ && apt-get update \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* # install yarn RUN npm install -g yarn #################################################################### # Setup app dependencies and switch user #################################################################### RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv export --no-dev --locked --format requirements-txt | uv pip install --system -r - #################################################################### # User and Group #################################################################### RUN mkdir -p ${USER_DIR} \ && groupadd --gid ${GROUP_ID} ${USER_NAME} \ && useradd -m -d ${USER_DIR} -u ${USER_ID} -g ${GROUP_ID} -o -s /bin/bash ${USER_NAME} USER ${USER_NAME} WORKDIR ${USER_DIR} #################################################################### # Runtime #################################################################### COPY --from=frontend-builder --chown=${USER_ID}:${GROUP_ID} /frontend/dist ${USER_DIR}/app/static/frontend # we used sqlite, so we need access to the host files and mount volumes from the host ... #COPY --chown=${USER_ID}:${GROUP_ID} ./app ${APP_DIR} RUN python manage.py collectstatic --noinput #RUN mkdir -p ~/.ipython/profile_default/ #RUN echo "c.InteractiveShellApp.extensions = ['autoreload']\nc.InteractiveShellApp.exec_lines = ['%autoreload 2']" > ~/.ipython/profile_default/ipython_config.py EXPOSE 8000 #CMD bash -c "sleep 2 && python manage.py collectstatic --noinput && python manage.py migrate && uvicorn oxpanel.asgi:application --workers 5 --host 0.0.0.0 --port 8000 --lifespan off --loop asyncio --ws websockets" CMD ["uvicorn", "oxpanel.asgi:application", "--config", "uvicorn_config.py"]