Explorar o código

update Dockerfile example (#1520)

Masen Furer hai 1 ano
pai
achega
95b28fd02a

+ 2 - 0
docker-example/.dockerignore

@@ -0,0 +1,2 @@
+.web
+__pycache__/*

+ 4 - 0
docker-example/Caddy.Dockerfile

@@ -0,0 +1,4 @@
+FROM library/caddy
+
+COPY --from=local/reflex-app /app/.web/_static /srv
+ADD Caddyfile /etc/caddy/Caddyfile

+ 18 - 0
docker-example/Caddyfile

@@ -0,0 +1,18 @@
+{$DOMAIN}
+
+encode gzip
+
+@backend_routes path /event/* /upload /ping
+handle @backend_routes {
+	reverse_proxy app:8000
+}
+
+route {
+	try_files {path} {path}.html
+	file_server {
+		root /srv
+		pass_thru
+	}
+	# proxy dynamic routes to nextjs server
+	reverse_proxy app:3000
+}

+ 24 - 35
docker-example/Dockerfile

@@ -1,49 +1,38 @@
-FROM python:3.11-slim as base
+# Stage 1: init
+FROM python:3.11 as init
 
-RUN adduser --disabled-password reflex
-
-
-FROM base as build
+# Pass `--build-arg API_URL=http://app.example.com:8000` during build
+ARG API_URL
 
+# Copy local context to `/app` inside container (see .dockerignore)
 WORKDIR /app
-ENV VIRTUAL_ENV=/app/venv
-RUN python3 -m venv $VIRTUAL_ENV
-ENV PATH="$VIRTUAL_ENV/bin:$PATH"
-
 COPY . .
 
-RUN pip install wheel \
-    && pip install -r requirements.txt
-
-
-FROM base as runtime
-
-RUN apt-get update && apt-get install -y \
-    curl \
-    && curl -fsSL https://deb.nodesource.com/setup_19.x | bash - \
-    && apt-get update && apt-get install -y \
-    nodejs \
-    unzip \
-    && rm -rf /var/lib/apt/lists/*
-
-ENV PATH="/app/venv/bin:$PATH"
+# Reflex will install bun, nvm, and node to `$HOME/.reflex` (/app/.reflex)
+ENV HOME=/app
 
+# Create virtualenv which will be copied into final container
+ENV VIRTUAL_ENV=/app/.venv
+ENV PATH="$VIRTUAL_ENV/bin:$PATH"
+RUN python3 -m venv $VIRTUAL_ENV
 
-FROM runtime as init
+# Install app requirements and reflex inside virtualenv
+RUN pip install -r requirements.txt
 
-WORKDIR /app
-ENV BUN_INSTALL="/app/.bun"
-COPY --from=build /app/ /app/
+# Deploy templates and prepare app
 RUN reflex init
 
+# Export static copy of frontend to /app/.web/_static (and pre-install frontend packages)
+RUN reflex export --frontend-only --no-zip
 
-FROM runtime
 
-COPY --chown=reflex --from=init /app/ /app/
-USER reflex
+# Stage 2: copy artifacts into slim image 
+FROM python:3.11-slim
+ARG API_URL
 WORKDIR /app
+RUN adduser --disabled-password --home /app reflex
+COPY --chown=reflex --from=init /app /app
+USER reflex
+ENV PATH="/app/.venv/bin:$PATH" API_URL=$API_URL
 
-CMD ["reflex", "run" , "--env", "prod"]
-
-EXPOSE 3000
-EXPOSE 8000
+CMD reflex db migrate && reflex run --env prod

+ 46 - 17
docker-example/README.md

@@ -1,37 +1,66 @@
-# Reflex Container Image Build
+# Reflex Docker Container
 
 This example describes how to create and use a container image for Reflex with your own code.
 
 ## Update Requirements
 
-The `requirements.txt` includes the reflex package which is need to install Reflex framework. If you use additional packages in your project you have add this in the `requirements.txt` first. Copy the `Dockerfile` and the `requirements.txt` file in your project folder.
+The `requirements.txt` includes the reflex package which is needed to install
+Reflex framework. If you use additional packages in your project you have to add
+this in the `requirements.txt` first. Copy the `Dockerfile`, `.dockerignore` and
+the `requirements.txt` file in your project folder.
 
-## Customize Reflex Config
+## Build Reflex Container Image
+
+To build your container image run the following command:
 
-The `rxconfig.py` includes the configuration of your Reflex service. Edit the file like the following configuration. If you want to use a custom database you can set the endpoint in this file. Ensure that `api_url` points to the publicly accessible hostname where the container will be running.
+```bash
+docker build -t reflex-app:latest . --build-arg API_URL=http://app.example.com:8000
+```
 
-```python
-import reflex as rx
+Ensure that `API_URL` is set to the publicly accessible hostname or IP where the app
+will be hosted.
 
-config = rx.Config(
-    app_name="app",
-    api_url="http://app.example.com:8000",
-    db_url="sqlite:///reflex.db",
-)
+## Start Container Service
+
+Finally, you can start your Reflex container service as follows:
+
+```bash
+docker run -p 3000:3000 -p 8000:8000 --name app reflex-app:latest
 ```
 
-## Build Reflex Container Image
+It may take a few seconds for the service to become available.
 
-To build your container image run the following command:
+# Production Service with Docker Compose and Caddy
+
+An example production deployment uses automatic TLS with Caddy serving static files
+for the frontend and proxying requests to both the frontend and backend.
+
+Copy `compose.yaml`, `Caddy.Dockerfile` and `Caddyfile` to your project directory. The production
+build leverages the same `Dockerfile` described above.
+
+## Customize `Caddyfile`
+
+If the app uses additional backend API routes, those should be added to the
+`@backend_routes` path matcher to ensure they are forwarded to the backend.
+
+## Build Reflex Production Service
+
+During build, set `DOMAIN` environment variable to the domain where the app will
+be hosted!  (Do not include http or https, it will always use https)
 
 ```bash
-docker build -t reflex-project:latest .
+DOMAIN=example.com docker compose build
 ```
 
-## Start Container Service
+This will build both the `app` service from the existing `Dockerfile` and the `webserver`
+service via `Caddy.Dockerfile` that copies the `Caddyfile` and static frontend export
+from the `app` service into the container.
 
-Finally, you can start your Reflex container service as follows:
+## Run Reflex Production Service
 
 ```bash
-docker run -d -p 3000:3000 -p 8000:8000 --name app reflex-project:latest
+DOMAIN=example.com docker compose up
 ```
+
+The app should be available at the specified domain via HTTPS. Certificate
+provisioning will occur automatically and may take a few minutes.

+ 21 - 0
docker-example/compose.yaml

@@ -0,0 +1,21 @@
+# During build and run, set environment DOMAIN pointing
+# to publicly accessible domain where app will be hosted
+services:
+  app:
+    image: local/reflex-app
+    build:
+      context: .
+      args:
+        API_URL: https://${DOMAIN:-localhost}
+
+  webserver:
+    environment:
+      DOMAIN: ${DOMAIN:-localhost}
+    ports:
+      - 443:443
+      - 80:80  # for acme-challenge via HTTP
+    build:
+      context: .
+      dockerfile: Caddy.Dockerfile
+    depends_on:
+      - app