소스 검색

Include app.Dockerfile for deploying to container hosting platform (#2784)

Masen Furer 1 년 전
부모
커밋
e4c32e3edf
3개의 변경된 파일73개의 추가작업 그리고 2개의 파일을 삭제
  1. 1 1
      docker-example/Dockerfile
  2. 15 1
      docker-example/README.md
  3. 57 0
      docker-example/app.Dockerfile

+ 1 - 1
docker-example/Dockerfile

@@ -11,7 +11,7 @@ RUN pip install -r requirements.txt
 # Deploy templates and prepare app
 RUN reflex init
 
-# Download all npm dependencies and compile and frontend
+# Download all npm dependencies and compile frontend
 RUN reflex export --frontend-only --no-zip
 
 # Needed until Reflex properly passes SIGTERM on backend.

+ 15 - 1
docker-example/README.md

@@ -116,4 +116,18 @@ to deploy these services if they are not in active use.
 
 ```bash
 DOMAIN=example.com docker compose -f compose.yaml -f compose.prod.yaml -f compose.tools.yaml up -d
-```
+```
+
+# Container Hosting
+
+Most container hosting services automatically terminate TLS and expect the app
+to be listening on a single port (typically `$PORT`).
+
+To host a Reflex app on one of these platforms, like Google Cloud Run, Render,
+Railway, etc, use `app.Dockerfile` to build a single image containing a reverse
+proxy that will serve that frontend as static files and proxy requests to the
+backend for specific endpoints.
+
+If the chosen platform does not support buildx and thus heredoc, you can copy
+the Caddyfile configuration into a separate Caddyfile in the root of the
+project.

+ 57 - 0
docker-example/app.Dockerfile

@@ -0,0 +1,57 @@
+# This Dockerfile is used to deploy a single-container Reflex app instance
+# to services like Render, Railway, Heroku, GCP, and others.
+
+# It uses a reverse proxy to serve the frontend statically and proxy to backend
+# from a single exposed port, expecting TLS termination to be handled at the
+# edge by the given platform.
+FROM python:3.11
+
+# If the service expects a different port, provide it here (f.e Render expects port 10000)
+ARG PORT=8080
+# Only set for local/direct access. When TLS is used, the API_URL is assumed to be the same as the frontend.
+ARG API_URL
+ENV PORT=$PORT API_URL=${API_URL:-http://localhost:$PORT}
+
+# Install Caddy server inside image
+RUN apt-get update -y && apt-get install -y caddy && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /app
+
+# Create a simple Caddyfile to serve as reverse proxy
+RUN cat > Caddyfile <<EOF
+:{\$PORT}
+
+encode gzip
+
+@backend_routes path /_event/* /ping /_upload /_upload/*
+handle @backend_routes {
+	reverse_proxy localhost:8000
+}
+
+root * /srv
+route {
+	try_files {path} {path}/ /404.html
+	file_server
+}
+EOF
+
+# Copy local context to `/app` inside container (see .dockerignore)
+COPY . .
+
+# Install app requirements and reflex in the container
+RUN pip install -r requirements.txt
+
+# Deploy templates and prepare app
+RUN reflex init
+
+# Download all npm dependencies and compile frontend
+RUN reflex export --frontend-only --no-zip && mv .web/_static/* /srv/ && rm -rf .web
+
+# Needed until Reflex properly passes SIGTERM on backend.
+STOPSIGNAL SIGKILL
+
+EXPOSE $PORT
+
+# Apply migrations before starting the backend.
+CMD [ -d alembic ] && reflex db migrate; \
+    caddy start && reflex run --env prod --backend-only --loglevel debug