MicProtocol / Dockerfile
Benaah's picture
Upload Dockerfile with huggingface_hub
8996192 verified
Raw History Blame Contribute Delete
5.57 kB
# ═══════════════════════════════════════════════════════════════
# MicProtocol β€” Hugging Face Space (Docker SDK) all-in-one image
# Single container running the core stack behind nginx on APP_PORT
# (HF maps the public domain to this port). Postgres, Redis,
# Meilisearch, mic-realtime, API + BullMQ workers, Web and Admin
# all run as processes launched by deploy/start.sh.
# NOTE: The full integrations suite (Formbricks, Cal.com, Chatwoot,
# Documenso, Listmonk, Umami, Pretix, MinIO, LiveKit, Coturn, Mailhog)
# cannot fit in a single free HF cpu-basic container (16 GB RAM).
# They are omitted here; deploy them elsewhere if needed.
# ═══════════════════════════════════════════════════════════════
# ─── Stage 0: mic-realtime (Erlang/OTP) release ────────────────
# Use Debian-based erlang so the release is glibc-compatible with the
# node:20-slim runner (a rebar3 release is self-contained; no Erlang
# system packages needed at runtime).
FROM erlang:27 AS realtime-build
WORKDIR /opt/mic-realtime
RUN apt-get update && apt-get install -y --no-install-recommends \
git make g++ openssl libssl-dev curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL -o /usr/local/bin/rebar3 https://s3.amazonaws.com/rebar3/rebar3 \
&& chmod +x /usr/local/bin/rebar3
COPY services/mic-realtime/rebar.config ./
RUN rebar3 get-deps || true
COPY services/mic-realtime/src ./src
COPY services/mic-realtime/config ./config
COPY services/mic-realtime/include ./include
RUN rebar3 compile && rebar3 release
# ─── Stage 1: Python clip-scoring venv ─────────────────────────
FROM node:20-slim AS python-build
RUN apt-get update && apt-get install -y --no-install-recommends python3 && rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY services/clip-scorer/ /app/services/clip-scorer/
ENV PATH="/opt/venv/bin:$PATH"
RUN uv venv --python /usr/bin/python3 /opt/venv \
&& VIRTUAL_ENV=/opt/venv uv pip install --index-url https://download.pytorch.org/whl/cpu "torch>=2.0.0" "torchvision>=0.15.0" \
&& VIRTUAL_ENV=/opt/venv uv pip install "open-clip-torch>=2.20.0" "transformers>=4.30.0" "Pillow>=10.0.0" "soundfile>=0.12.0" "pyloudnorm>=0.1.0" "numpy>=1.24.0"
# ─── Stage 2: Builder (install deps + prisma generate + web + admin builds) ─
# shared-types and api are pre-built locally (nest build needs >4GB heap,
# which exceeds HF free-tier container limits). Web and admin build fine on HF.
FROM node:20-slim AS builder
WORKDIR /app
RUN npm install -g pnpm@10.30.3
COPY . .
RUN pnpm install --frozen-lockfile
# Generate Prisma client (API needs it at runtime)
RUN cd apps/api && npx prisma generate
# Build Web and Admin on HF (these complete successfully)
RUN DOCKER_BUILD=true pnpm --filter @micprotocol/web build
RUN DOCKER_BUILD=true pnpm --filter @micprotocol/admin build
# Prune to production deps for a smaller runner image
RUN CI=true pnpm install --prod --frozen-lockfile
# ─── Stage 3: Runner (all-in-one) ──────────────────────────────
FROM node:20-slim AS runner
WORKDIR /app
ENV NODE_ENV=production \
APP_PORT=7860 \
API_PORT=4000 WEB_PORT=3000 ADMIN_PORT=3006 \
MIC_REALTIME_PORT=4001 \
POSTGRES_PORT=5432 REDIS_PORT=6379 MEILISEARCH_PORT=7700
# System services: postgres, redis, nginx, python, tini
# (No Erlang packages needed β€” mic-realtime release is self-contained.)
RUN apt-get update && apt-get install -y --no-install-recommends \
postgresql postgresql-contrib redis-server \
ca-certificates curl wget gnupg tini netcat-openbsd python3 \
openssl libpq5 libssl3 \
nginx \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/run/postgresql /var/log/nginx /var/lib/nginx/body
# Meilisearch binary
COPY --from=getmeili/meilisearch:v1.9.0 /bin/meilisearch /usr/local/bin/meilisearch
# mic-realtime release (self-contained, ERTS included)
COPY --from=realtime-build /opt/mic-realtime/_build /opt/mic-realtime/_build
COPY services/mic-realtime/config /opt/mic-realtime/config
# Python venv + clip-scorer source + HF cache
COPY --from=python-build --chown=root:root /opt/venv /opt/venv
COPY --from=python-build /app/services/clip-scorer /app/services/clip-scorer
ENV PATH="/opt/venv/bin:$PATH" HF_HOME=/app/.hf-cache
# Built application artifacts from builder
COPY --from=builder --chown=root:root /app /app
# Restructure Next.js standalone output so start.sh paths work:
# standalone puts server.js under apps/web/.next/standalone/apps/web/,
# but start.sh expects apps/web/server.js with .next/static and public
# alongside it.
RUN cp -r apps/web/.next/standalone/apps/web/. apps/web/ \
&& cp -r apps/admin/.next/standalone/apps/admin/. apps/admin/ \
&& rm -rf apps/web/.next/standalone apps/admin/.next/standalone
# Nginx config: single public port -> path-based routing
COPY deploy/nginx.conf /etc/nginx/nginx.conf
RUN sed -i "s/__APP_PORT__/${APP_PORT}/" /etc/nginx/nginx.conf
# Startup script
COPY deploy/start.sh /app/start.sh
RUN chmod +x /app/start.sh \
&& chown -R postgres:postgres /var/run/postgresql /var/lib/postgresql
EXPOSE 7860
ENTRYPOINT ["tini", "--"]
CMD ["/app/start.sh"]