Compare commits
4 Commits
d4ca53c46f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
11efb6f09c
|
|||
|
ba04fb7c53
|
|||
|
eb08788f7a
|
|||
|
c7d5b98507
|
@@ -33,9 +33,13 @@ jobs:
|
|||||||
tag_num="${tag}-${tag_num}"
|
tag_num="${tag}-${tag_num}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
repo=$GITHUB_REPOSITORY
|
||||||
|
repo=${repo#*/}
|
||||||
|
repo=$(echo $repo | tr '[:upper:]' '[:lower:]')
|
||||||
|
echo "container=$repo"
|
||||||
|
|
||||||
docker build -t nathanwoodburn:$tag_num .
|
docker build -t $repo:$tag_num .
|
||||||
docker tag nathanwoodburn:$tag_num git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag_num
|
docker tag $repo:$tag_num git.woodburn.au/nathanwoodburn/$repo:$tag_num
|
||||||
docker push git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag_num
|
docker push git.woodburn.au/nathanwoodburn/$repo:$tag_num
|
||||||
docker tag nathanwoodburn:$tag_num git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag
|
docker tag $repo:$tag_num git.woodburn.au/nathanwoodburn/$repo:$tag
|
||||||
docker push git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag
|
docker push git.woodburn.au/nathanwoodburn/$repo:$tag
|
||||||
|
|||||||
34
Dockerfile
34
Dockerfile
@@ -1,17 +1,31 @@
|
|||||||
FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder
|
FROM --platform=$BUILDPLATFORM python:3.13-alpine
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
# Install curl for healthcheck
|
||||||
|
RUN apk add --no-cache curl
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt /app
|
# Install dependencies
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
python3 -m pip install -r requirements.txt
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||||
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||||
|
uv sync --locked --no-install-project
|
||||||
|
|
||||||
COPY . /app
|
# Copy the project into the image
|
||||||
|
ADD . /app
|
||||||
|
|
||||||
# Optionally mount /data to store the data
|
# Sync the project
|
||||||
# VOLUME /data
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
|
uv sync --locked
|
||||||
|
|
||||||
ENTRYPOINT ["python3"]
|
# Add mount point for data volume
|
||||||
|
ENV BASE_DIR=/data
|
||||||
|
VOLUME /data
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
|
||||||
|
ENTRYPOINT ["uv", "run"]
|
||||||
CMD ["main.py"]
|
CMD ["main.py"]
|
||||||
|
|
||||||
FROM builder as dev-envs
|
|
||||||
24
README.md
24
README.md
@@ -2,17 +2,31 @@
|
|||||||
|
|
||||||
Python3 website template including git actions
|
Python3 website template including git actions
|
||||||
|
|
||||||
# Development
|
## Requirements
|
||||||
1. Install requirements
|
- UV
|
||||||
|
|
||||||
|
## Development
|
||||||
|
1. Install project requirements
|
||||||
```bash
|
```bash
|
||||||
python3 -m pip install -r requirements.txt
|
uv sync
|
||||||
```
|
```
|
||||||
2. Run the dev server
|
2. Run the dev server
|
||||||
```bash
|
```bash
|
||||||
python3 server.py
|
uv run python3 server.py
|
||||||
|
```
|
||||||
|
3. Alternatively use the virtual environment
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
```
|
||||||
|
You can exit the environment with `deactivate`
|
||||||
|
|
||||||
|
For best development setup, you should install the git hook for pre-commit
|
||||||
|
```bash
|
||||||
|
uv run pre-commit install
|
||||||
```
|
```
|
||||||
|
|
||||||
# Production
|
|
||||||
|
## Production
|
||||||
Run using the main.py file
|
Run using the main.py file
|
||||||
```bash
|
```bash
|
||||||
python3 main.py
|
python3 main.py
|
||||||
|
|||||||
18
main.py
18
main.py
@@ -1,5 +1,3 @@
|
|||||||
from flask import Flask
|
|
||||||
from server import app
|
|
||||||
import server
|
import server
|
||||||
from gunicorn.app.base import BaseApplication
|
from gunicorn.app.base import BaseApplication
|
||||||
import os
|
import os
|
||||||
@@ -21,22 +19,20 @@ class GunicornApp(BaseApplication):
|
|||||||
return self.application
|
return self.application
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
dotenv.load_dotenv()
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
workers = os.getenv('WORKERS', 1)
|
workers = os.getenv("WORKERS", 1)
|
||||||
threads = os.getenv('THREADS', 2)
|
threads = os.getenv("THREADS", 2)
|
||||||
workers = int(workers)
|
workers = int(workers)
|
||||||
threads = int(threads)
|
threads = int(threads)
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
'bind': '0.0.0.0:5000',
|
"bind": "0.0.0.0:5000",
|
||||||
'workers': workers,
|
"workers": workers,
|
||||||
'threads': threads,
|
"threads": threads,
|
||||||
}
|
}
|
||||||
|
|
||||||
gunicorn_app = GunicornApp(server.app, options)
|
gunicorn_app = GunicornApp(server.app, options)
|
||||||
print(f'Starting server with {workers} workers and {threads} threads', flush=True)
|
print(f"Starting server with {workers} workers and {threads} threads", flush=True)
|
||||||
gunicorn_app.run()
|
gunicorn_app.run()
|
||||||
|
|||||||
16
server.py
16
server.py
@@ -1,9 +1,6 @@
|
|||||||
from functools import cache
|
|
||||||
import json
|
|
||||||
from flask import (
|
from flask import (
|
||||||
Flask,
|
Flask,
|
||||||
make_response,
|
make_response,
|
||||||
redirect,
|
|
||||||
request,
|
request,
|
||||||
jsonify,
|
jsonify,
|
||||||
render_template,
|
render_template,
|
||||||
@@ -11,7 +8,6 @@ from flask import (
|
|||||||
send_file,
|
send_file,
|
||||||
)
|
)
|
||||||
import os
|
import os
|
||||||
import json
|
|
||||||
import requests
|
import requests
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import dotenv
|
import dotenv
|
||||||
@@ -26,6 +22,7 @@ def find(name, path):
|
|||||||
if name in files:
|
if name in files:
|
||||||
return os.path.join(root, name)
|
return os.path.join(root, name)
|
||||||
|
|
||||||
|
|
||||||
# Assets routes
|
# Assets routes
|
||||||
@app.route("/assets/<path:path>")
|
@app.route("/assets/<path:path>")
|
||||||
def send_assets(path):
|
def send_assets(path):
|
||||||
@@ -74,17 +71,13 @@ def wellknown(path):
|
|||||||
# region Main routes
|
# region Main routes
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
# Get current time in the format "dd MMM YYYY hh:mm AM/PM"
|
|
||||||
# current_datetime = datetime.now().strftime("%d %b %Y %I:%M %p")
|
|
||||||
# return render_template("index.html", datetime=current_datetime)
|
|
||||||
|
|
||||||
# Print the IP address of the requester
|
# Print the IP address of the requester
|
||||||
print(f"Request from IP: {request.remote_addr}")
|
print(f"Request from IP: {request.remote_addr}")
|
||||||
# And the headers
|
# And the headers
|
||||||
print(f"Request headers: {request.headers}")
|
print(f"Request headers: {request.headers}")
|
||||||
|
# Get current time in the format "dd MMM YYYY hh:mm AM/PM"
|
||||||
|
current_datetime = datetime.now().strftime("%d %b %Y %I:%M %p")
|
||||||
# return redirect("https://ya.c.woodburn.au")
|
return render_template("index.html", datetime=current_datetime)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<path:path>")
|
@app.route("/<path:path>")
|
||||||
@@ -116,6 +109,7 @@ def catch_all(path: str):
|
|||||||
|
|
||||||
api_requests = 0
|
api_requests = 0
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/v1/data", methods=["GET"])
|
@app.route("/api/v1/data", methods=["GET"])
|
||||||
def api_data():
|
def api_data():
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user