From 59aade557e0ba24dccdc5a550957ece56364d141 Mon Sep 17 00:00:00 2001 From: ElektrikSpark Date: Sat, 11 May 2024 08:34:53 +0000 Subject: [PATCH] fastapi docker, fly.io deployment --- apps/fastapi/.dockerignore | 37 ++++++++++++++++++++ apps/fastapi/.env.example | 8 +++++ apps/fastapi/.vercelignore | 2 -- apps/fastapi/Dockerfile | 51 +++++++++++++++++++++++++++ apps/fastapi/README.Docker.md | 22 ++++++++++++ apps/fastapi/api/config.py | 1 + apps/fastapi/api/endpoints/v1/api.py | 2 +- apps/fastapi/api/main.py | 6 ++-- apps/fastapi/compose.yaml | 52 ++++++++++++++++++++++++++++ apps/fastapi/fly.toml | 25 +++++++++++++ 10 files changed, 199 insertions(+), 7 deletions(-) create mode 100644 apps/fastapi/.dockerignore create mode 100644 apps/fastapi/.env.example delete mode 100644 apps/fastapi/.vercelignore create mode 100644 apps/fastapi/Dockerfile create mode 100644 apps/fastapi/README.Docker.md create mode 100644 apps/fastapi/compose.yaml create mode 100644 apps/fastapi/fly.toml diff --git a/apps/fastapi/.dockerignore b/apps/fastapi/.dockerignore new file mode 100644 index 0000000..ad31828 --- /dev/null +++ b/apps/fastapi/.dockerignore @@ -0,0 +1,37 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +**/.DS_Store +**/__pycache__ +**/.venv +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/bin +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md + +# ruff +.ruff_cache/ diff --git a/apps/fastapi/.env.example b/apps/fastapi/.env.example new file mode 100644 index 0000000..dace838 --- /dev/null +++ b/apps/fastapi/.env.example @@ -0,0 +1,8 @@ +# Auth +JWT_SECRET="" + +# OpenAI +OPENAI_API_KEY="" + +# Anthropic +ANTHROPIC_API_KEY="" diff --git a/apps/fastapi/.vercelignore b/apps/fastapi/.vercelignore deleted file mode 100644 index f74c781..0000000 --- a/apps/fastapi/.vercelignore +++ /dev/null @@ -1,2 +0,0 @@ -.next -node_modules diff --git a/apps/fastapi/Dockerfile b/apps/fastapi/Dockerfile new file mode 100644 index 0000000..d44fa7d --- /dev/null +++ b/apps/fastapi/Dockerfile @@ -0,0 +1,51 @@ +# syntax=docker/dockerfile:1 + +# Comments are provided throughout this file to help you get started. +# If you need more help, visit the Dockerfile reference guide at +# https://docs.docker.com/go/dockerfile-reference/ + +# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 + +ARG PYTHON_VERSION=3.12.2 +FROM python:${PYTHON_VERSION}-slim as base + +# Prevents Python from writing pyc files. +ENV PYTHONDONTWRITEBYTECODE=1 + +# Keeps Python from buffering stdout and stderr to avoid situations where +# the application crashes without emitting any logs due to buffering. +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/go/dockerfile-user-best-practices/ +ARG UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + appuser + +# Download dependencies as a separate step to take advantage of Docker's caching. +# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds. +# Leverage a bind mount to requirements.txt to avoid having to copy them into +# into this layer. +RUN --mount=type=cache,target=/root/.cache/pip \ + --mount=type=bind,source=requirements.txt,target=requirements.txt \ + python -m pip install -r requirements.txt + +# Switch to the non-privileged user to run the application. +USER appuser + +# Copy the source code into the container. +COPY ./api /app/api + +# Expose the port that the application listens on. +EXPOSE 8000 + +# Run the application. +CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/apps/fastapi/README.Docker.md b/apps/fastapi/README.Docker.md new file mode 100644 index 0000000..6dae561 --- /dev/null +++ b/apps/fastapi/README.Docker.md @@ -0,0 +1,22 @@ +### Building and running your application + +When you're ready, start your application by running: +`docker compose up --build`. + +Your application will be available at http://localhost:8000. + +### Deploying your application to the cloud + +First, build your image, e.g.: `docker build -t myapp .`. +If your cloud uses a different CPU architecture than your development +machine (e.g., you are on a Mac M1 and your cloud provider is amd64), +you'll want to build the image for that platform, e.g.: +`docker build --platform=linux/amd64 -t myapp .`. + +Then, push it to your registry, e.g. `docker push myregistry.com/myapp`. + +Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/) +docs for more detail on building and pushing. + +### References +* [Docker's Python guide](https://docs.docker.com/language/python/) \ No newline at end of file diff --git a/apps/fastapi/api/config.py b/apps/fastapi/api/config.py index 2c89023..189437e 100644 --- a/apps/fastapi/api/config.py +++ b/apps/fastapi/api/config.py @@ -14,6 +14,7 @@ class Settings(BaseSettings): PROJECT_NAME: str = "FastAPI App" PROJECT_DESCRIPTION: str = "A simple FastAPI app" + ENVIRONMENT: str = os.getenv("ENVIRONMENT", "development") JWT_SECRET: str = os.getenv("JWT_SECRET") ANTHROPIC_API_KEY: str = os.getenv("ANTHROPIC_API_KEY") OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY") diff --git a/apps/fastapi/api/endpoints/v1/api.py b/apps/fastapi/api/endpoints/v1/api.py index 31e6c31..3e3f22d 100644 --- a/apps/fastapi/api/endpoints/v1/api.py +++ b/apps/fastapi/api/endpoints/v1/api.py @@ -1,6 +1,6 @@ from fastapi import APIRouter -from api.endpoints.v1 import health, upload +from api.endpoints.v1.routers import health, upload api_router = APIRouter() diff --git a/apps/fastapi/api/main.py b/apps/fastapi/api/main.py index 49700dc..9a5f0b1 100644 --- a/apps/fastapi/api/main.py +++ b/apps/fastapi/api/main.py @@ -1,12 +1,11 @@ import logging -import os from fastapi import APIRouter, FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.routing import APIRoute from api.config import settings -from api.endpoints.v1 import api_router +from api.endpoints.v1.api import api_router info_router = APIRouter() @@ -39,9 +38,8 @@ def get_application(): ) origins = ["https://app.getwellchart.com"] - environment = os.getenv("VERCEL_ENV", "development") - if environment in ["development"]: + if settings.ENVIRONMENT == "development": logger = logging.getLogger("uvicorn") logger.warning("Running in development mode - allowing CORS for all origins") _app.add_middleware( diff --git a/apps/fastapi/compose.yaml b/apps/fastapi/compose.yaml new file mode 100644 index 0000000..5cf3c38 --- /dev/null +++ b/apps/fastapi/compose.yaml @@ -0,0 +1,52 @@ +# Comments are provided throughout this file to help you get started. +# If you need more help, visit the Docker compose reference guide at +# https://docs.docker.com/go/compose-spec-reference/ + +# Here the instructions define your application as a service called "server". +# This service is built from the Dockerfile in the current directory. +# You can add other services your application may depend on here, such as a +# database or a cache. For examples, see the Awesome Compose repository: +# https://github.com/docker/awesome-compose +services: + server: + build: + context: . + ports: + - 8000:8000 + volumes: + - ./api:/app/api + env_file: + - .env +# The commented out section below is an example of how to define a PostgreSQL +# database that your application can use. `depends_on` tells Docker Compose to +# start the database before your application. The `db-data` volume persists the +# database data between container restarts. The `db-password` secret is used +# to set the database password. You must create `db/password.txt` and add +# a password of your choosing to it before running `docker compose up`. +# depends_on: +# db: +# condition: service_healthy +# db: +# image: postgres +# restart: always +# user: postgres +# secrets: +# - db-password +# volumes: +# - db-data:/var/lib/postgresql/data +# environment: +# - POSTGRES_DB=example +# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password +# expose: +# - 5432 +# healthcheck: +# test: [ "CMD", "pg_isready" ] +# interval: 10s +# timeout: 5s +# retries: 5 +# volumes: +# db-data: +# secrets: +# db-password: +# file: db/password.txt + diff --git a/apps/fastapi/fly.toml b/apps/fastapi/fly.toml new file mode 100644 index 0000000..9d67661 --- /dev/null +++ b/apps/fastapi/fly.toml @@ -0,0 +1,25 @@ +# fly.toml app configuration file generated for wellchart-fastapi on 2024-05-11T03:18:23-05:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = 'wellchart-fastapi' +primary_region = 'ord' + +[build] + +[http_service] + internal_port = 8000 + force_https = true + auto_stop_machines = true + auto_start_machines = true + min_machines_running = 0 + processes = ['app'] + +[[vm]] + memory = '1gb' + cpu_kind = 'shared' + cpus = 1 + +[env] + ENVIRONMENT = 'production'