app.Dockerfile 1.6 KB

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