Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
895150e
feat: docker entry point and celery config
prokopis3 Sep 22, 2025
17a70b4
feat(db): enhance Firebase and Redis configurations for production an…
prokopis3 Sep 22, 2025
080403e
chore(config): update fly.toml and requirements for improved process …
prokopis3 Sep 22, 2025
d8dcec6
feat(redis): enhance Redis connection handling and add stream message…
prokopis3 Sep 22, 2025
135c2e1
feat(server): This commit introduces significant updates to the appli…
prokopis3 Sep 22, 2025
3f6c221
feat(celery): enhance environment variable loading and add Windows-sp…
prokopis3 Sep 22, 2025
04f36b3
feat(docker): upgrade base image to Python 3.12 and optimize Dockerfi…
prokopis3 Sep 22, 2025
1e20740
The variable chunk_size is used but not defined in this function. It …
prokopis3 Sep 22, 2025
568b224
The response parameter is declared but not used properly. The functio…
prokopis3 Sep 22, 2025
c735661
The parentheses around the ternary expression create a tuple instead …
prokopis3 Sep 22, 2025
9abf3ca
The boolean logic is unclear due to operator precedence. The conditio…
prokopis3 Sep 22, 2025
a598e37
Potential fix for code scanning alert no. 7: Information exposure thr…
prokopis3 Sep 23, 2025
8ab13c0
XADD path: missing await and wrong API surface.
prokopis3 Sep 23, 2025
f9bf6ba
XREAD path: flatten args and support both clients.
prokopis3 Sep 23, 2025
24f49e9
fix(server): Health endpoint: mask internal errors and silence ARG001.
prokopis3 Sep 23, 2025
8a87c33
fix(dockerfile): Builder stage lacks build deps; wheels may fail to b…
prokopis3 Sep 23, 2025
9b156e8
Potential fix for code scanning alert no. 8: Information exposure thr…
prokopis3 Sep 23, 2025
6e7b285
fix(redis): XADD path: missing required “*” ID and wrong method prefe…
prokopis3 Sep 23, 2025
cbe9a7e
fix(docker-entrypoint): add process management and signal handling
prokopis3 Sep 23, 2025
0a642a4
feat(storage): implement S3 multipart upload and streaming capabilities
prokopis3 Sep 23, 2025
368e4d9
refactor(utils): improve task status response and error handling
prokopis3 Sep 23, 2025
b3db86d
fix(redisCache): enhance connection handling and URL parsing
prokopis3 Sep 23, 2025
0fd2460
refactor(api): enhance error handling and type safety in streaming fu…
prokopis3 Sep 23, 2025
4d7cb33
fix(job): improve SSE message formatting and error handling
prokopis3 Sep 23, 2025
fcfe675
chore(Dockerfile): update entry point and simplify CMD
prokopis3 Sep 23, 2025
dca97c9
chore(fly.toml): update service configuration and add VNC security
prokopis3 Sep 23, 2025
2c22595
refactor(celery_app): update Redis connection handling
prokopis3 Sep 23, 2025
cf444ea
chore(build): Enhance build process with UV and refine Dockerfile
prokopis3 Sep 23, 2025
c2656b0
chore(gitignore): add regions.md to .gitignore
prokopis3 Sep 23, 2025
f0c4abf
refactor(storage): replace get_s3_client with S3ClientManager in list…
prokopis3 Sep 23, 2025
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ env/
.vscode/

/*.env

/*regions.md
255 changes: 135 additions & 120 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,150 +1,165 @@
# Use an official Python runtime as a base image
FROM python:3.10-slim AS build
# Build stage with UV
FROM ghcr.io/astral-sh/uv:0.8.22 AS uv

# Set environment variables to production
# Builder stage
FROM python:3.12-slim AS builder

# Set build-time environment variables
ENV PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_DEFAULT_TIMEOUT=100 \
DEBIAN_FRONTEND=noninteractive \
UV_COMPILE_BYTECODE=1 \
UV_NO_INSTALLER_METADATA=1 \
UV_LINK_MODE=copy

ARG APP_HOME=/app
WORKDIR ${APP_HOME}

# Install build dependencies
COPY requirements.txt .
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
curl \
gcc \
g++ \
python3-dev \
pkg-config \
libjpeg-dev \
cmake \
&& rm -rf /var/lib/apt/lists/*

# Use UV to build wheels
RUN --mount=from=uv,source=/uv,target=/bin/uv \
--mount=type=cache,target=/root/.cache/uv \
uv pip install --system -r requirements.txt

# Final stage
FROM python:3.12-slim

# Metadata
LABEL maintainer="Prokopis Antoniadis" \
description="🔥🕷️ Crawl4AI: LLM Web Crawler & scraper" \
version="0.1.0"

# Set environment variables
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
PYTHON_ENV=production
PYTHON_ENV=production \
UV_LINK_MODE=copy \
DISPLAY=:99

# Set build arguments
ARG APP_HOME=/app
ARG PYTHON_VERSION=3.12
ARG INSTALL_TYPE=default
ARG ENABLE_GPU=false
ARG TARGETARCH


# Add Maintainer Info
LABEL maintainer="Prokopis Antoniadis"
LABEL description="🔥🕷️ Crawl4AI: LLM Web Crawler & scraper"
LABEL version="1.0"

# RUN apt-get update && apt-get install -y --no-install-recommends \
# build-essential \
# curl \
# wget \
# gnupg \
# cmake \
# pkg-config \
# python3-dev \
# libjpeg-dev \
# supervisor \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/*

# Install minimal system dependencies for Playwright and Python
RUN apt-get update -y && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \

# Install UV in final stage
COPY --from=uv /uv /usr/local/bin/uv
RUN chmod +x /usr/local/bin/uv

WORKDIR ${APP_HOME}

# Install system dependencies in a single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
fonts-liberation \
ca-certificates \
lsof \
# Add build dependencies for madoka
build-essential \
curl \
gcc \
g++ \
python3-dev \
Comment thread
prokopis3 marked this conversation as resolved.
pkg-config \
libjpeg-dev \
cmake \
wget \
gnupg \
supervisor \
# Playwright system dependencies
libglib2.0-0 \
libnss3 \
libnspr4 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libdbus-1-3 \
libxcb1 \
libxkbcommon0 \
libx11-6 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libdrm2 \
libgbm1 \
libxss1 \
libpango-1.0-0 \
libcairo2 \
libasound2 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libatspi2.0-0 \
libxcursor1 \
libxss1 \
libgtk-3-0 \
xvfb \
x11vnc \
git \
curl fonts-liberation ca-certificates lsof \
&& git clone https://github.com/novnc/noVNC /opt/noVNC \
&& git clone https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# RUN apt-get update && apt-get dist-upgrade -y \
# && rm -rf /var/lib/apt/lists/*

# RUN if [ "$ENABLE_GPU" = "true" ] && [ "$TARGETARCH" = "amd64" ] ; then \
# apt-get update && apt-get install -y --no-install-recommends \
# nvidia-cuda-toolkit \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/* ; \
# else \
# echo "Skipping NVIDIA CUDA Toolkit installation (unsupported platform or GPU disabled)"; \
# fi

# RUN if [ "$TARGETARCH" = "arm64" ]; then \
# echo "🦾 Installing ARM-specific optimizations"; \
# apt-get update && apt-get install -y --no-install-recommends \
# libopenblas-dev \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/*; \
# elif [ "$TARGETARCH" = "amd64" ]; then \
# echo "🖥️ Installing AMD64-specific optimizations"; \
# apt-get update && apt-get install -y --no-install-recommends \
# libomp-dev \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/*; \
# else \
# echo "Skipping platform-specific optimizations (unsupported platform)"; \
# fi

# Create a non-root user and group
# RUN groupadd -r appuser && useradd --no-log-init -r -g appuser appuser

# Create and set permissions for appuser home directory
# RUN mkdir -p /home/appuser && chown -R appuser:appuser /home/appuser

# Set the working directory inside the container
WORKDIR ${APP_HOME}

# Copy the requirements file and install Python dependencies
# Copy supervisor config first (might need root later, but okay for now)
# COPY supervisord.conf .

COPY requirements.txt .
COPY config.yml .

RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir playwright

RUN pip install --no-cache-dir --upgrade pip && \
python -c "import crawl4ai; print('✅ crawl4ai is ready to rock!')" && \
# Add sudo for X11 management
&& git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
&& git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean \
Comment on lines +109 to +111

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

❓ Verification inconclusive

Unpinned git clones for noVNC/websockify reduce reproducibility.

Pin to a commit/tag to avoid supply‑chain drift.

Apply:

-    && git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
-    && git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
+    && git clone --depth 1 --branch v1.5.0 https://github.com/novnc/noVNC /opt/noVNC \
+    && git clone --depth 1 --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \

Pin noVNC and websockify to specific release tags for reproducibility
Update your Dockerfile’s git clones to use the latest stable tags:

-    && git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
-    && git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
+    && git clone --depth 1 --branch v1.5.0 https://github.com/novnc/noVNC /opt/noVNC \
+    && git clone --depth 1 --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \

These tags correspond to the latest stable releases (noVNC v1.5.0 (github.com); websockify v0.12.0 (repositorystats.com)), ensuring build reproducibility and preventing supply-chain drift.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
&& git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
&& git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean \
&& git clone --depth 1 --branch v1.5.0 https://github.com/novnc/noVNC /opt/noVNC \
&& git clone --depth 1 --branch v0.12.0 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean \
🤖 Prompt for AI Agents
In Dockerfile around lines 91-93, the git clones for noVNC and websockify use
floating HEADs which breaks reproducibility; update the clone commands to fetch
specific release tags (noVNC v1.5.0 and websockify v0.12.0) by using git clone
--depth 1 --branch v1.5.0 for https://github.com/novnc/noVNC into /opt/noVNC and
git clone --depth 1 --branch v0.12.0 for https://github.com/novnc/websockify
into /opt/noVNC/utils/websockify (or clone then checkout the tag), keeping the
same destinations and preserving cleanup steps.

Comment thread
prokopis3 marked this conversation as resolved.
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/cache/apt/*

Comment on lines +63 to +114

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Final stage installs build toolchains it shouldn’t need.

If wheels are built, avoid re‑installing heavy build deps here. Also set DEBIAN_FRONTEND in this stage.

Apply:

-RUN apt-get update && apt-get install -y --no-install-recommends \
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && apt-get install -y --no-install-recommends \
     fonts-liberation \
     ca-certificates \
     lsof \
-    # Add build dependencies for madoka
-    build-essential \
+    # runtime-only deps below
     curl \
     wget \
     gnupg \
-    cmake \
-    gcc \
-    g++ \
-    pkg-config \
-    python3-dev \
-    libjpeg-dev \
     supervisor \

If some wheels can’t be built, move those specific build deps back to the builder, not here.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Install system dependencies in a single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
fonts-liberation \
ca-certificates \
lsof \
# Add build dependencies for madoka
build-essential \
curl \
wget \
gnupg \
cmake \
gcc \
g++ \
pkg-config \
python3-dev \
libjpeg-dev \
supervisor \
libnss3 \
# Playwright system dependencies
libglib2.0-0 \
libnss3 \
libnspr4 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libdbus-1-3 \
libxcb1 \
libxkbcommon0 \
libx11-6 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libdrm2 \
libgbm1 \
libxss1 \
libpango-1.0-0 \
libcairo2 \
libasound2 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libatspi2.0-0 \
libxcursor1 \
libxss1 \
libgtk-3-0 \
xvfb \
x11vnc \
git \
curl fonts-liberation ca-certificates lsof \
&& git clone https://github.com/novnc/noVNC /opt/noVNC \
&& git clone https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# RUN apt-get update && apt-get dist-upgrade -y \
# && rm -rf /var/lib/apt/lists/*
# RUN if [ "$ENABLE_GPU" = "true" ] && [ "$TARGETARCH" = "amd64" ] ; then \
# apt-get update && apt-get install -y --no-install-recommends \
# nvidia-cuda-toolkit \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/* ; \
# else \
# echo "Skipping NVIDIA CUDA Toolkit installation (unsupported platform or GPU disabled)"; \
# fi
# RUN if [ "$TARGETARCH" = "arm64" ]; then \
# echo "🦾 Installing ARM-specific optimizations"; \
# apt-get update && apt-get install -y --no-install-recommends \
# libopenblas-dev \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/*; \
# elif [ "$TARGETARCH" = "amd64" ]; then \
# echo "🖥️ Installing AMD64-specific optimizations"; \
# apt-get update && apt-get install -y --no-install-recommends \
# libomp-dev \
# && apt-get clean \
# && rm -rf /var/lib/apt/lists/*; \
# else \
# echo "Skipping platform-specific optimizations (unsupported platform)"; \
# fi
# Create a non-root user and group
# RUN groupadd -r appuser && useradd --no-log-init -r -g appuser appuser
# Create and set permissions for appuser home directory
# RUN mkdir -p /home/appuser && chown -R appuser:appuser /home/appuser
# Set the working directory inside the container
WORKDIR ${APP_HOME}
# Copy the requirements file and install Python dependencies
# Copy supervisor config first (might need root later, but okay for now)
# COPY supervisord.conf .
COPY requirements.txt .
COPY config.yml .
RUN pip install --no-cache-dir -r requirements.txt && \
pip install --no-cache-dir playwright
RUN pip install --no-cache-dir --upgrade pip && \
python -c "import crawl4ai; print('✅ crawl4ai is ready to rock!')" && \
python -c "from playwright.sync_api import sync_playwright; print('✅ Playwright is feeling dramatic!')"
# RUN crawl4ai-setup
# https://playwright.dev/docs/browsers
# Install only the required Playwright browser (Chromium)
RUN playwright install chromium
# RUN playwright install --with-deps
# Add sudo for X11 management
&& git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
&& git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/cache/apt/*
# Install system dependencies in a single layer
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
fonts-liberation \
ca-certificates \
lsof \
# runtime-only deps below
curl \
wget \
gnupg \
supervisor \
libnss3 \
# Playwright system dependencies
libglib2.0-0 \
libnss3 \
libnspr4 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libdbus-1-3 \
libxcb1 \
libxkbcommon0 \
libx11-6 \
libxcomposite1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libgbm1 \
libpango-1.0-0 \
libcairo2 \
libasound2 \
libatspi2.0-0 \
libxcursor1 \
libxss1 \
libgtk-3-0 \
xvfb \
x11vnc \
git \
# Add sudo for X11 management
&& git clone --depth 1 https://github.com/novnc/noVNC /opt/noVNC \
&& git clone --depth 1 https://github.com/novnc/websockify /opt/noVNC/utils/websockify \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/cache/apt/*
🤖 Prompt for AI Agents
In Dockerfile around lines 44-96, the final stage is installing heavy build
toolchains and missing DEBIAN_FRONTEND; remove build-only packages
(build-essential, gcc, g++, cmake, pkg-config, python3-dev, libjpeg-dev) from
this RUN and keep only runtime deps and playwrigh‑related libs; add
DEBIAN_FRONTEND=noninteractive to the RUN env for apt operations; move any
build-only packages required to build wheels into the builder stage (or a
separate build image) so that only minimal runtime packages remain in the final
image; if specific wheels fail to build in the builder, add those few build deps
back into the builder stage only, not the final stage, and keep apt-get
update/install/clean/rm -rf in a single chained RUN as currently done.

# Create non-root user
RUN groupadd -r appuser && \
useradd --no-log-init -r -g appuser appuser && \
mkdir -p /home/appuser/.cache /ms-playwright && \
chown -R appuser:appuser /home/appuser /ms-playwright ${APP_HOME}

# Install Python dependencies using UV
# COPY --from=builder /app/wheels /wheels

# Copy dependencies and install
COPY --from=builder ${APP_HOME}/requirements.txt .
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system -r requirements.txt && \
uv pip install --system playwright && \
playwright install --with-deps chromium
Comment thread
prokopis3 marked this conversation as resolved.

# Verify installations
RUN python -c "import crawl4ai; print('✅ crawl4ai is ready to rock!')" && \
python -c "from playwright.sync_api import sync_playwright; print('✅ Playwright is feeling dramatic!')"

# Copy application code
COPY --chown=appuser:appuser . .
COPY --chown=appuser:appuser config.yml .

# RUN crawl4ai-setup

# https://playwright.dev/docs/browsers
# Install only the required Playwright browser (Chromium)
RUN playwright install chromium

# RUN playwright install --with-deps
# Set display environment variable
# ENV DISPLAY=:99

# Run diagnostics
RUN crawl4ai-doctor
Comment thread
prokopis3 marked this conversation as resolved.

# RUN mkdir -p /home/appuser/.cache/ms-playwright \
# && cp -r /root/.cache/ms-playwright/chromium-* /home/appuser/.cache/ms-playwright/ \
# && chown -R appuser:appuser /home/appuser/.cache/ms-playwright
# Expose ports
EXPOSE 8000 9222 6080

# Copy the application code into the container
COPY . .
# Change ownership of the application directory to the non-root user
# RUN chown -R appuser:appuser ${APP_HOME}
# Healthcheck dont need, fly io do this for us
# HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
# CMD curl -f http://localhost:8000/health || exit 1

# Switch to the non-root user before starting the application
# USER appuser
# Copy and set permissions for the entrypoint script
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh && \
chown root:root /usr/local/bin/docker-entrypoint.sh && \
ls -la /usr/local/bin/docker-entrypoint.sh # Verify permissions

# # Install only the required Playwright browser (Chromium)
# RUN playwright install chromium
# Switch to non-root user
USER appuser

# Expose the port your FastAPI app will run on
EXPOSE 8000 9222 6080
# Set the entrypoint
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

# Command to run the application
# CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000", "--ws", "websockets"]
# CMD ["sh", "-c", "Xvfb :99 -screen 0 1280x720x24 & export DISPLAY=:99 && uvicorn server:app --host 0.0.0.0 --port 8000 --ws websockets"]
CMD ["sh", "-c", "Xvfb :99 -screen 0 1280x720x24 & x11vnc -display :99 -nopw -forever -shared -rfbport 5900 -quiet & /opt/noVNC/utils/websockify/run 6080 localhost:5900 --web /opt/noVNC & uvicorn server:app --host 0.0.0.0 --port 8000 --ws websockets"]
# Start the application using supervisord
# CMD ["supervisord", "-c", "supervisord.conf"]
# Start application
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000", "--ws", "websockets"]
Loading