From 5a5b27d285c71d5faeba1b4f80c9820f5d020e0c Mon Sep 17 00:00:00 2001 From: BalconyJH Date: Sat, 21 Dec 2024 16:15:15 +0800 Subject: [PATCH] :green_heart: Update docker build and remove obsolete dockerfile. --- .dockerignore | 18 +- docker/Dockerfile | 133 ++++++++++++--- docker/Dockerfile_browser | 10 -- docker/Dockerfile_tuna | 9 - docker/Dockerfile_with_frontend | 220 ++++++++++++++++++++----- docker/Dockerfile_with_frontend_sentry | 50 ------ 6 files changed, 301 insertions(+), 139 deletions(-) delete mode 100644 docker/Dockerfile_browser delete mode 100644 docker/Dockerfile_tuna delete mode 100644 docker/Dockerfile_with_frontend_sentry diff --git a/.dockerignore b/.dockerignore index d5427d2..4db2154 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,19 +1,21 @@ *.ini -*.yaml +#*.yaml *.yml *.md -*.json -*.toml +#*.json *.xml tests node_modules -admin-frontend +#admin-frontend data* htmlcov docker dist docs -.* - -!pyproject.toml -!README.md +/LICENSE +/.editorconfig +/.gitattributes +/.prettierignore +/.prettierrc +/.devcontainer/ +/.github/ diff --git a/docker/Dockerfile b/docker/Dockerfile index eafb22e..058fe23 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,33 +1,118 @@ # syntax=docker/dockerfile:1.10 -FROM python:3.12-slim-bookworm AS builder -COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +FROM python:3.12-slim AS metadata-stage -ENV UV_COMPILE_BYTECODE=1 +WORKDIR /tmp + +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHONUNBUFFERED=1 \ + TZ=Asia/Shanghai + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + python3-pip \ + git \ + && pip install toml \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY ./pyproject.toml ./ + +RUN echo "πŸ“‹ Collecting metadata..." && \ + export CREATED_DATE="$(date -u '+%Y-%m-%d %H:%M:%S UTC')" && \ + export PYPROJECT_NAME=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["name"])') && \ + export DESCRIPTION=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["description"])') && \ + export AUTHOR=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["authors"][0]["name"])') && \ + echo "⏰ Created Date: $CREATED_DATE" && \ + echo "πŸ“ Project Name: $PYPROJECT_NAME" && \ + echo "πŸ“„ Description: $DESCRIPTION" && \ + echo "πŸ‘€ Author: $AUTHOR" && \ + echo "$CREATED_DATE" > /tmp/CREATED_DATE && \ + echo "$PYPROJECT_NAME" > /tmp/PYPROJECT_NAME && \ + echo "$DESCRIPTION" > /tmp/DESCRIPTION && \ + echo "$AUTHOR" > /tmp/AUTHOR + + +RUN --mount=type=bind,source=./.git/,target=/tmp/.git/ \ + echo "🏷️ Checking version information..." && \ + VERSION=$(git describe --tags --exact-match 2>/dev/null || git rev-parse --short HEAD || echo "unknown") && \ + echo "πŸ“Œ Version: $VERSION" && \ + echo "$VERSION" > /tmp/VERSION + +LABEL org.opencontainers.image.created="$(cat /tmp/CREATED_DATE)" \ + org.opencontainers.image.authors="$(cat /tmp/AUTHOR)" \ + org.opencontainers.image.description="$(cat /tmp/DESCRIPTION)" \ + org.opencontainers.image.name="$(cat /tmp/PYPROJECT_NAME)" \ + org.opencontainers.image.version="$(cat /tmp/VERSION)" + +FROM python:3.12-slim AS production WORKDIR /app -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 sync --frozen --no-install-project --no-editable -ADD . /app/ +#ENV UV_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ +ENV DEBIAN_FRONTEND=noninteractive \ + UV_COMPILE_BYTECODE=1 \ + UV_SYSTEM_PYTHON=true \ + PYTHONUNBUFFERED=1 \ + UV_LINK_MODE=copy \ + TZ=Asia/Shanghai -RUN --mount=type=cache,target=/var/cache/apt \ - --mount=type=cache,target=/var/lib/apt \ - apt-get update && apt-get install -y xvfb fonts-noto-color-emoji fonts-unifont \ - libfontconfig1 libfreetype6 xfonts-scalable fonts-liberation \ - fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf \ - fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 \ - libcairo2 libcups2 libdbus-1-3 libdrm2 libegl1 libgbm1 libglib2.0-0 libgtk-3-0 \ - libnspr4 libnss3 libpango-1.0-0 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ - libxdamage1 libxext6 libxfixes3 libxrandr2 libxshmfence1 vim +RUN echo "πŸ“¦ Installing system dependencies..." && \ +# --mount=type=cache,target=/var/cache/apt \ +# --mount=type=cache,target=/var/lib/apt \ + apt-get update && apt-get install -y --no-install-recommends \ + curl \ + xvfb \ + fonts-noto-color-emoji fonts-unifont \ + libfontconfig1 libfreetype6 xfonts-scalable \ + fonts-liberation fonts-ipafont-gothic \ + fonts-wqy-zenhei fonts-tlwg-loma-otf \ + vim && \ + echo "πŸ” Verifying Python installation..." && \ + if PYTHON_VERSION=$(python3 --version 2>&1); then \ + echo "βœ… ${PYTHON_VERSION} installed successfully"; \ + else \ + echo "❌ Python installation failed" && exit 1; \ + fi && \ + fc-cache -fv && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + echo "βœ… System dependencies installed successfully" -RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --no-dev --frozen --no-editable --extra=docker +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +RUN echo "πŸ” Verifying uv installation..." && \ + if UV_VERSION=$(uv --version 2>&1); then \ + echo "βœ… uv version ${UV_VERSION} installed successfully"; \ + else \ + echo "❌ uv installation failed" && exit 1; \ + fi -RUN uv run playwright install chromium &&\ - mv docker.env.prod .env.prod && \ - nb adapter install nonebot-adapter-red && \ - nb adapter install nonebot-adapter-qq +COPY ./pyproject.toml ./uv.lock ./ -CMD ["uv", "run", "nb", "run"] +RUN echo "πŸ“¦ Installing bison dependencies..." && \ + uv pip install --extra=docker --requirement pyproject.toml --no-cache && \ + echo "βœ… Dependencies installed successfully" && \ + echo "🧹 Cleaning up uv..." && \ + rm -rf /bin/uv /bin/uvx && \ + rm -rf /root/.cache/ && \ + rm -rf /root/.uv && \ + echo "βœ… UV cleanup completed" + +COPY --from=metadata-stage /tmp/VERSION /app/VERSION +COPY . . + +RUN echo "🎭 Installing Playwright..." && \ + playwright install --with-deps chromium && \ + rm -rf /var/lib/apt/lists/* /tmp/* && \ + mv docker.env.prod .env.prod && \ + echo "βœ… Playwright installed successfully" + +EXPOSE 8080 + +RUN echo '#!/bin/bash\n\ +echo "πŸ“Œ Current bison Version: $(cat /app/VERSION)"\n\ +echo "πŸš€ Starting backend service..."\n\ +nb run' > /app/start.sh && \ + chmod +x /app/start.sh + +CMD ["/app/start.sh"] diff --git a/docker/Dockerfile_browser b/docker/Dockerfile_browser deleted file mode 100644 index 0a7ef7b..0000000 --- a/docker/Dockerfile_browser +++ /dev/null @@ -1,10 +0,0 @@ -FROM python:3.11 -RUN apt-get update && apt-get install -y fonts-wqy-microhei chromium nano -RUN python3 -m pip config set global.index-url https://mirrors.aliyun.com/pypi/simple -RUN python3 -m pip install poetry && poetry config virtualenvs.create false -WORKDIR /app -COPY ./README.md ./pyproject.toml ./poetry.lock* /app/ -RUN poetry install --only=main,docker -ENV BISON_BROWSER=local:/usr/bin/chromium -ADD src /app/src -ENV HOST=0.0.0.0 diff --git a/docker/Dockerfile_tuna b/docker/Dockerfile_tuna deleted file mode 100644 index d83bd3f..0000000 --- a/docker/Dockerfile_tuna +++ /dev/null @@ -1,9 +0,0 @@ -FROM python:3.11 -RUN python3 -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple -RUN python3 -m pip install poetry && poetry config virtualenvs.create false -WORKDIR /app -COPY ./README.md ./pyproject.toml ./poetry.lock* /app/ -RUN poetry install --only=main,docker -ADD src /app/src -ENV HOST=0.0.0.0 -CMD ["nb", "run"] diff --git a/docker/Dockerfile_with_frontend b/docker/Dockerfile_with_frontend index df761da..60da38e 100644 --- a/docker/Dockerfile_with_frontend +++ b/docker/Dockerfile_with_frontend @@ -1,49 +1,193 @@ # syntax=docker/dockerfile:1.10 -FROM python:3.11-slim-bullseye AS base +FROM python:3.12-slim AS metadata-stage -FROM base AS builder +WORKDIR /tmp -ENV PYTHONFAULTHANDLER=1 \ - PYTHONUNBUFFERED=1 \ - PYTHONHASHSEED=random \ - PIP_NO_CACHE_DIR=off \ - PIP_DISABLE_PIP_VERSION_CHECK=on \ - PIP_DEFAULT_TIMEOUT=100 \ - POETRY_NO_INTERACTION=1 \ - POETRY_VIRTUALENVS_CREATE=false \ - PATH="$PATH:/runtime/bin" \ - # Versions: - POETRY_VERSION=1.7.1 -RUN apt-get update && apt-get install -y build-essential unzip wget python-dev git -RUN pip install "poetry==$POETRY_VERSION" +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHONUNBUFFERED=1 \ + TZ=Asia/Shanghai -WORKDIR /src +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + python3-pip \ + git \ + && pip install toml \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* -COPY README.md pyproject.toml poetry.lock /src/ +COPY ./pyproject.toml ./ -RUN poetry export --only=main,docker --without-hashes --no-interaction --no-ansi -f requirements.txt -o requirements.txt -RUN pip install --prefix=/runtime --force-reinstall -r requirements.txt +RUN echo "πŸ“‹ Collecting metadata..." && \ + export CREATED_DATE="$(date -u '+%Y-%m-%d %H:%M:%S UTC')" && \ + export PYPROJECT_NAME=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["name"])') && \ + export DESCRIPTION=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["description"])') && \ + export AUTHOR=$(python3 -c 'import toml; print(toml.load("pyproject.toml")["project"]["authors"][0]["name"])') && \ + echo "⏰ Created Date: $CREATED_DATE" && \ + echo "πŸ“ Project Name: $PYPROJECT_NAME" && \ + echo "πŸ“„ Description: $DESCRIPTION" && \ + echo "πŸ‘€ Author: $AUTHOR" && \ + echo "$CREATED_DATE" > /tmp/CREATED_DATE && \ + echo "$PYPROJECT_NAME" > /tmp/PYPROJECT_NAME && \ + echo "$DESCRIPTION" > /tmp/DESCRIPTION && \ + echo "$AUTHOR" > /tmp/AUTHOR -FROM base AS runtime + +RUN --mount=type=bind,source=./.git/,target=/tmp/.git/ \ + echo "🏷️ Checking version information..." && \ + VERSION=$(git describe --tags --exact-match 2>/dev/null || git rev-parse --short HEAD || echo "unknown") && \ + echo "πŸ“Œ Version: $VERSION" && \ + echo "$VERSION" > /tmp/VERSION + +LABEL org.opencontainers.image.created="$(cat /tmp/CREATED_DATE)" \ + org.opencontainers.image.authors="$(cat /tmp/AUTHOR)" \ + org.opencontainers.image.description="$(cat /tmp/DESCRIPTION)" \ + org.opencontainers.image.name="$(cat /tmp/PYPROJECT_NAME)" \ + org.opencontainers.image.version="$(cat /tmp/VERSION)" + +FROM node:20-slim AS frontend-stage + +WORKDIR /tmp/admin-frontend + +ENV TZ=Asia/Shanghai \ + PNPM_HOME="/pnpm" \ + PATH="$PNPM_HOME:$PATH" + +COPY ./admin-frontend/package.json ./admin-frontend/pnpm-lock.yaml ./ + +RUN corepack enable && \ + corepack prepare pnpm@9.15.1 --activate && \ + echo "πŸ”” Verifying Node.js installation..." && \ + if NODE_VERSION=$(node --version 2>&1); then \ + echo "βœ… Node.js version ${NODE_VERSION} installed successfully"; \ + else \ + echo "❌ Node.js installation failed" && exit 1; \ + fi && \ + echo "πŸ”” Verifying pnpm installation..." && \ + if PNPM_VERSION=$(pnpm --version 2>&1); then \ + echo "βœ… pnpm version ${PNPM_VERSION} installed successfully"; \ + else \ + echo "❌ pnpm installation failed" && exit 1; \ + fi + +RUN pnpm install --frozen-lockfile + +COPY ./admin-frontend . +RUN mkdir -p ../nonebot_bison/admin_page/dist + +RUN echo "πŸ—οΈ Starting frontend build..." && \ + pnpm run build && \ + echo "βœ… Frontend build completed" + +FROM python:3.12-slim AS production WORKDIR /app -RUN --mount=type=cache,target=/var/cache/apt \ - --mount=type=cache,target=/var/lib/apt \ - apt-get update && apt-get install -y xvfb fonts-noto-color-emoji ttf-unifont \ - libfontconfig1 libfreetype6 xfonts-cyrillic xfonts-scalable fonts-liberation \ - fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf \ - fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 \ - libcairo2 libcups2 libdbus-1-3 libdrm2 libegl1 libgbm1 libglib2.0-0 libgtk-3-0 \ - libnspr4 libnss3 libpango-1.0-0 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ - libxdamage1 libxext6 libxfixes3 libxrandr2 libxshmfence1 nano -COPY --from=builder /runtime /usr/local -ADD . /app/ -RUN pip install -e . && playwright install chromium -RUN mv docker.env.prod .env.prod && \ - nb adapter install nonebot-adapter-red && \ - nb adapter install nonebot-adapter-qq -ENV HOST=0.0.0.0 -CMD ["nb", "run"] +#ENV UV_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ +ENV DEBIAN_FRONTEND=noninteractive \ + UV_COMPILE_BYTECODE=1 \ + UV_SYSTEM_PYTHON=true \ + PYTHONUNBUFFERED=1 \ + UV_LINK_MODE=copy \ + TZ=Asia/Shanghai \ + SHELL="/bin/bash" \ + PNPM_HOME="/pnpm" \ + PATH="/pnpm:${PATH}" -# vim: ft=dockerfile +RUN echo "πŸ“¦ Installing system dependencies..." && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + xvfb \ + fonts-noto-color-emoji \ + fonts-unifont \ + libfontconfig1 \ + libfreetype6 \ + xfonts-scalable \ + fonts-liberation \ + fonts-ipafont-gothic \ + fonts-wqy-zenhei \ + fonts-tlwg-loma-otf && \ + mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ + apt-get install -y nodejs && \ + echo "πŸ”” Verifying Node.js installation..." && \ + if NODE_VERSION=$(node --version 2>&1); then \ + echo "βœ… Node.js version ${NODE_VERSION} installed successfully"; \ + else \ + echo "❌ Node.js installation failed" && exit 1; \ + fi && \ + mkdir -p "${PNPM_HOME}" && \ + npm install -g pnpm@9.15.1 && \ + # ι’„δΈ‹θ½½ pnpm εŒ…εˆ°ε…¨ε±€ε­˜ε‚¨ + curl -fsSL https://registry.npmjs.org/pnpm/-/pnpm-9.15.1.tgz -o /tmp/pnpm.tgz && \ + mkdir -p /root/.local/share/pnpm/store/v3 && \ + pnpm store add /tmp/pnpm.tgz && \ + rm /tmp/pnpm.tgz && \ + echo "πŸ”” Verifying pnpm installation..." && \ + if PNPM_VERSION=$(pnpm --version 2>&1); then \ + echo "βœ… pnpm version ${PNPM_VERSION} installed successfully"; \ + else \ + echo "❌ pnpm installation failed" && exit 1; \ + fi && \ + fc-cache -fv && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + echo "βœ… System dependencies installed successfully" + + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +RUN echo "πŸ”” Verifying uv installation..." && \ + if UV_VERSION=$(uv --version 2>&1); then \ + echo "βœ… uv version ${UV_VERSION} installed successfully"; \ + else \ + echo "❌ uv installation failed" && exit 1; \ + fi + +COPY ./pyproject.toml ./uv.lock ./ + +RUN echo "πŸ“¦ Installing bison dependencies..." && \ + uv pip install --extra=docker --requirement pyproject.toml --no-cache && \ + echo "βœ… Dependencies installed successfully" && \ + echo "πŸ”” Cleaning up uv..." && \ + rm -rf /bin/uv /bin/uvx && \ + rm -rf /root/.cache/ && \ + rm -rf /root/.uv && \ + echo "βœ… UV cleanup completed" + +COPY --from=metadata-stage /tmp/VERSION /app/VERSION +COPY . . +COPY --from=frontend-stage /tmp/nonebot_bison/admin_page/dist ./dist +COPY --from=frontend-stage /tmp/admin-frontend/package.json ./ +COPY --from=frontend-stage /tmp/admin-frontend/pnpm-lock.yaml ./ + + +#RUN echo "πŸ“¦ Installing frontend dependencies..." && \ +# cd /app/admin-frontend && \ +# SHELL="/bin/bash" pnpm install --offline --prod --frozen-lockfile && \ +# rm -rf /root/.cache/ && \ +# echo "βœ… Frontend dependencies installed successfully" +RUN echo "πŸ“¦ Installing frontend dependencies..." && \ + cd /app/admin-frontend && \ + SHELL="/bin/bash" pnpm install --prod --frozen-lockfile --no-verify-store-integrity && \ + rm -rf /root/.cache/ /root/.local/share/pnpm/store/v3/* /root/.pnpm-store && \ + echo "βœ… Frontend dependencies installed successfully" + + +RUN echo "🎭 Installing Playwright..." && \ + playwright install --with-deps chromium && \ + rm -rf /var/lib/apt/lists/* /tmp/* && \ + mv docker.env.prod .env.prod && \ + echo "βœ… Playwright installed successfully" + +EXPOSE 3000 8080 + +RUN echo '#!/bin/bash' > /app/start.sh && \ + echo 'echo "πŸ“Œ Current bison Version: $(cat /app/VERSION)"' >> /app/start.sh && \ + echo 'echo "πŸš€ Starting backend service..."' >> /app/start.sh && \ + echo 'nb run &' >> /app/start.sh && \ + echo 'echo "πŸš€ Starting frontend service..."' >> /app/start.sh && \ + echo 'cd /app/admin-frontend && SHELL=/bin/bash exec pnpm start' >> /app/start.sh && \ + chmod +x /app/start.sh + +CMD ["/app/start.sh"] diff --git a/docker/Dockerfile_with_frontend_sentry b/docker/Dockerfile_with_frontend_sentry deleted file mode 100644 index 3545069..0000000 --- a/docker/Dockerfile_with_frontend_sentry +++ /dev/null @@ -1,50 +0,0 @@ -# syntax=docker/dockerfile:1.10 -FROM python:3.11-slim-bullseye AS base - -FROM base AS builder - -ENV PYTHONFAULTHANDLER=1 \ - PYTHONUNBUFFERED=1 \ - PYTHONHASHSEED=random \ - PIP_NO_CACHE_DIR=off \ - PIP_DISABLE_PIP_VERSION_CHECK=on \ - PIP_DEFAULT_TIMEOUT=100 \ - POETRY_NO_INTERACTION=1 \ - POETRY_VIRTUALENVS_CREATE=false \ - PATH="$PATH:/runtime/bin" \ - # Versions: - POETRY_VERSION=1.7.1 -RUN apt-get update && apt-get install -y build-essential unzip wget python3-dev git -RUN pip install "poetry==$POETRY_VERSION" - -WORKDIR /src - -COPY pyproject.toml poetry.lock /src/ - -RUN poetry export --only=main,docker --without-hashes --no-interaction --no-ansi -f requirements.txt -o requirements.txt -RUN pip install --prefix=/runtime --force-reinstall -r requirements.txt - -FROM base AS runtime - -WORKDIR /app -RUN --mount=type=cache,target=/var/cache/apt \ - --mount=type=cache,target=/var/lib/apt \ - apt-get update && apt-get install -y xvfb fonts-noto-color-emoji ttf-unifont \ - libfontconfig1 libfreetype6 xfonts-cyrillic xfonts-scalable fonts-liberation \ - fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf \ - fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 \ - libcairo2 libcups2 libdbus-1-3 libdrm2 libegl1 libgbm1 libglib2.0-0 libgtk-3-0 \ - libnspr4 libnss3 libpango-1.0-0 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ - libxdamage1 libxext6 libxfixes3 libxrandr2 libxshmfence1 nano - -COPY --from=builder /runtime /usr/local -ADD . /app/ -RUN pip install -e . && playwright install chromium -RUN mv docker.env.prod .env.prod && \ - nb adapter install nonebot-adapter-red && \ - nb adapter install nonebot-adapter-qq && \ - nb plugin install nonebot-plugin-sentry -ENV HOST=0.0.0.0 -CMD ["nb", "run"] - -# vim: ft=dockerfile