Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
340006ff37 | ||
|
|
86fcdfde27 | ||
|
|
e0b5e05cce | ||
|
|
9f25457b24 | ||
|
|
9895017385 | ||
|
|
7c2b9fb3f4 |
No files matched your search
@@ -1,4 +1,4 @@
|
||||
# Keep the Python version in sync with Dockerfile.dev
|
||||
# Keep the Python version in sync with the production Dockerfile
|
||||
FROM python:3.15-slim-trixie
|
||||
|
||||
ARG USERNAME=dev
|
||||
@@ -7,17 +7,21 @@ ARG USER_GID=$USER_UID
|
||||
|
||||
# git + openssh-client: git over the host's forwarded SSH agent
|
||||
# gcc, libc-dev, libpq-dev: build psycopg2 from requirements.txt
|
||||
# postgresql-client, wait-for-it: scripts/db-setup.sh, scripts/psql.sh
|
||||
# postgresql-client, wait-for-it: database scripts
|
||||
# curl, ca-certificates: Claude Code installer
|
||||
# vim: personal preferences
|
||||
# vim, bash-completion: personal preferences
|
||||
RUN apt-get -y update && \
|
||||
apt-get install --no-install-recommends -y \
|
||||
git openssh-client make curl ca-certificates sudo \
|
||||
gcc libc-dev libpq-dev \
|
||||
postgresql-client wait-for-it \
|
||||
vim && \
|
||||
vim bash-completion && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Load bash-completion in every interactive shell (e.g. `make <TAB>`). Not in
|
||||
# ~/.bashrc, since the home dir is a volume (see devcontainer.json).
|
||||
RUN echo '. /usr/share/bash-completion/bash_completion' >> /etc/bash.bashrc
|
||||
|
||||
RUN groupadd --gid $USER_GID $USERNAME && \
|
||||
useradd --uid $USER_UID --gid $USER_GID -m -s /bin/bash $USERNAME && \
|
||||
echo "$USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME && \
|
||||
|
||||
@@ -9,8 +9,6 @@ services:
|
||||
- home:/home/dev
|
||||
environment:
|
||||
- PYTHONPATH=/workspaces/max
|
||||
- FLASK_APP=max.app
|
||||
- FLASK_ENV=development
|
||||
- PGSQL_HOST=postgresql
|
||||
- PGSQL_PORT=5432
|
||||
- PGSQL_USER=max
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
// Bind mounts are resolved by the host's daemon, so they need host paths:
|
||||
// use ${LOCAL_WORKSPACE_FOLDER} instead of paths inside this container.
|
||||
"remoteEnv": {
|
||||
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
|
||||
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}",
|
||||
"LANG": "C.UTF-8"
|
||||
},
|
||||
"postCreateCommand": "pip install -U pip && pip install -U -r requirements.txt -r requirements-dev.txt",
|
||||
"forwardPorts": [
|
||||
8000
|
||||
8757
|
||||
]
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
*.pyc
|
||||
log/
|
||||
+1
-3
@@ -12,11 +12,9 @@ RUN mkdir log
|
||||
|
||||
ENV PYTHONPATH=/app/
|
||||
ENV FLASK_APP=max.app
|
||||
ENV FLASK_ENV=production
|
||||
|
||||
COPY max/ ./max
|
||||
COPY scripts/entrypoint.sh .
|
||||
COPY scripts/db-setup.sh .
|
||||
COPY scripts/prod/ .
|
||||
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["gunicorn", "-w", "1", "-b", "0.0.0.0:8000", "max.app:app"]
|
||||
@@ -1,21 +0,0 @@
|
||||
FROM python:3.15-slim-trixie
|
||||
|
||||
RUN apt -y update && apt -y upgrade && \
|
||||
apt install --no-install-recommends -y wait-for-it lsb-release wget gnupg2 gcc libpq-dev libc-dev vim postgresql-client && apt clean all
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
COPY requirements-dev.txt .
|
||||
RUN pip install -U -r requirements.txt -r requirements-dev.txt
|
||||
|
||||
RUN mkdir log
|
||||
|
||||
ENV PYTHONPATH=/app/
|
||||
ENV FLASK_APP=max.app
|
||||
ENV FLASK_ENV=development
|
||||
|
||||
COPY scripts/* ./
|
||||
|
||||
ENTRYPOINT ["./entrypoint-dev.sh"]
|
||||
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]
|
||||
@@ -1,36 +1,21 @@
|
||||
# DEVELOPMENT SERVER
|
||||
# DEV
|
||||
seed-dev: clear-dev
|
||||
FLASK_APP=max.app FLASK_DEBUG=1 scripts/dev/seed-db.sh
|
||||
|
||||
seed-dev:
|
||||
scripts/entrypoint-dev.sh
|
||||
clear-dev:
|
||||
scripts/dev/clear-db.sh
|
||||
|
||||
build-dev:
|
||||
docker build -t max:dev -f Dockerfile.dev .
|
||||
run-dev:
|
||||
FLASK_APP=max.app FLASK_DEBUG=1 flask run --host 0.0.0.0 --port 8757
|
||||
|
||||
run-dev: | build-dev
|
||||
# bash -c "trap 'docker-compose -f dc.dev.yml down' EXIT; MAX_COMMAND=\"flask run --host 0.0.0.0 --port 8000\" docker-compose -f dc.dev.yml up --build"
|
||||
MAX_COMMAND="flask run --host 0.0.0.0 --port 8000" docker-compose -f dc.dev.yml up
|
||||
run-dev-as-prod:
|
||||
mkdir -p log
|
||||
FLASK_APP=max.app LOG_DIR=log gunicorn -w 1 -b 0.0.0.0:8757 max.app:app
|
||||
|
||||
run-bash: | build-dev
|
||||
MAX_COMMAND="sleep infinity" docker-compose -f dc.dev.yml up -d
|
||||
docker-compose -f dc.dev.yml exec max "./entrypoint-dev.sh"
|
||||
docker-compose -f dc.dev.yml exec max chown -R $$(id -u $${USER}):$$(id -g $${USER}) /app
|
||||
docker-compose -f dc.dev.yml exec -u $$(id -u $${USER}):$$(id -g $${USER}) max bash || true
|
||||
docker-compose -f dc.dev.yml down
|
||||
|
||||
run-bash-root: | build-dev
|
||||
MAX_COMMAND="sleep infinity" docker-compose -f dc.dev.yml up -d
|
||||
docker-compose -f dc.dev.yml exec max "./entrypoint-dev.sh"
|
||||
docker-compose -f dc.dev.yml exec max bash || true
|
||||
docker-compose -f dc.dev.yml down
|
||||
|
||||
stop-dev:
|
||||
docker-compose -f dc.dev.yml down
|
||||
|
||||
run-cleanup: | build-dev
|
||||
docker run -ti -v `pwd`/max:/app/max --entrypoint="" max-dev ./cleanup.sh
|
||||
run-cleanup:
|
||||
scripts/dev/cleanup.sh
|
||||
|
||||
# PROD
|
||||
|
||||
build-prod:
|
||||
docker build -t max:$(shell cat VERSION) .
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<script>
|
||||
function test() {
|
||||
$.post("http://localhost:8000/user/1/toggle-enabled", null, function () {
|
||||
$.post("http://localhost:8757/user/1/toggle-enabled", null, function () {
|
||||
console.log("success", arguments);
|
||||
});
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<button onclick="test()">Change</button>
|
||||
|
||||
<form action="http://localhost:8000/user/1/toggle-enabled" method="post">
|
||||
<form action="http://localhost:8757/user/1/toggle-enabled" method="post">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
services:
|
||||
max:
|
||||
image: max:dev
|
||||
volumes:
|
||||
- ./max:/app/max
|
||||
depends_on:
|
||||
- postgresql
|
||||
command: $MAX_COMMAND
|
||||
ports:
|
||||
- 8000:8000/tcp
|
||||
environment:
|
||||
- PGSQL_HOST=postgresql
|
||||
- PGSQL_USER=max
|
||||
- PGSQL_PASSWORD=max
|
||||
- PGSQL_NAME=max
|
||||
networks:
|
||||
- postgresql
|
||||
postgresql:
|
||||
image: postgres:18.6
|
||||
environment:
|
||||
- POSTGRES_USER=max
|
||||
- POSTGRES_PASSWORD=max
|
||||
- POSTGRES_DB=max
|
||||
networks:
|
||||
- postgresql
|
||||
networks:
|
||||
postgresql:
|
||||
+1
-37
@@ -1,8 +1,5 @@
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from logging.config import dictConfig
|
||||
|
||||
from flask import Flask
|
||||
from werkzeug.routing import Rule as WerkzeugRule
|
||||
@@ -11,6 +8,7 @@ from .auth import AuthMiddleware, init as init_auth
|
||||
from .cli import register_cli
|
||||
from .csrf import CsrfMiddleware
|
||||
from .db import database
|
||||
from .log import init_logging
|
||||
from .middlewares import (
|
||||
ExceptionMiddleware,
|
||||
I18NMiddleware,
|
||||
@@ -27,40 +25,6 @@ class Rule(WerkzeugRule):
|
||||
super().__init__(*args, **kwargs) # do not set methods
|
||||
|
||||
|
||||
def init_logging(app):
|
||||
dictConfig(
|
||||
{
|
||||
"version": 1,
|
||||
"formatters": {
|
||||
"default": {"format": "[%(asctime)s] [%(levelname)s]: %(message)s"}
|
||||
},
|
||||
"handlers": {
|
||||
"wsgi": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": "ext://flask.logging.wsgi_errors_stream",
|
||||
"formatter": "default",
|
||||
},
|
||||
"stdout": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": sys.stdout,
|
||||
"formatter": "default",
|
||||
},
|
||||
"file": {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"filename": "/app/log/max.log",
|
||||
"formatter": "default",
|
||||
"maxBytes": 1024 * 1024,
|
||||
"backupCount": 5,
|
||||
},
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["stdout", "file"]},
|
||||
"gunicorn": {"level": "INFO", "handlers": ["stdout", "file"]},
|
||||
}
|
||||
)
|
||||
logger = logging.getLogger(app.name)
|
||||
logger.setLevel(logging.DEBUG if app.debug else logging.INFO)
|
||||
|
||||
|
||||
def main():
|
||||
app = Flask(__name__)
|
||||
init_logging(app)
|
||||
|
||||
@@ -10,7 +10,7 @@ from max.views import redirect
|
||||
from .auth import logout
|
||||
|
||||
|
||||
DEBUG_DEFAULT_LOGIN = True
|
||||
DEBUG_DEFAULT_LOGIN = False
|
||||
|
||||
|
||||
class AuthMiddleware(BaseMiddleware):
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from logging.config import dictConfig
|
||||
|
||||
|
||||
def init_logging(app):
|
||||
handlers = {
|
||||
"stdout": {
|
||||
"class": "logging.StreamHandler",
|
||||
"stream": sys.stdout,
|
||||
"formatter": "default",
|
||||
},
|
||||
}
|
||||
active_handlers = ["stdout"]
|
||||
if not app.debug:
|
||||
handlers["file"] = {
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"filename": os.path.join(os.environ.get("LOG_DIR", "/app/log"), "max.log"),
|
||||
"formatter": "default",
|
||||
"maxBytes": 1024 * 1024,
|
||||
"backupCount": 5,
|
||||
}
|
||||
active_handlers.append("file")
|
||||
|
||||
dictConfig(
|
||||
{
|
||||
"version": 1,
|
||||
"formatters": {
|
||||
"default": {"format": "[%(asctime)s] [%(levelname)s]: %(message)s"}
|
||||
},
|
||||
"handlers": handlers,
|
||||
"root": {"level": "INFO", "handlers": active_handlers},
|
||||
"gunicorn": {"level": "INFO", "handlers": active_handlers},
|
||||
}
|
||||
)
|
||||
logger = logging.getLogger(app.name)
|
||||
logger.setLevel(logging.DEBUG if app.debug else logging.INFO)
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
printf "Black:\n"
|
||||
black max/
|
||||
printf "\nIsort:\n"
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PGPASSWORD="$PGSQL_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$PGSQL_HOST" -p "$PGSQL_PORT" -U "$PGSQL_USER" -d "$PGSQL_NAME" \
|
||||
-c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
||||
@@ -1,2 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PGPASSWORD="$PGSQL_PASSWORD" psql -h "$PGSQL_HOST" -p "$PGSQL_PORT" -U "$PGSQL_USER" -d "$PGSQL_NAME"
|
||||
@@ -1,11 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
source "$(dirname "$0")/db-setup.sh"
|
||||
source ../prod/db-setup.sh
|
||||
|
||||
flask add-domain finn.st
|
||||
flask add-domain stutzenste.in
|
||||
flask reset-admin admin@finn.st admin
|
||||
|
||||
exec "$@"
|
||||
@@ -15,6 +15,6 @@ wait-for-it --timeout=15 "$PGSQL_HOST:$PGSQL_PORT"
|
||||
|
||||
# Create schema in postgresql
|
||||
export PGPASSWORD="$PGSQL_PASSWORD"
|
||||
psql -1 -h "$PGSQL_HOST" -p "$PGSQL_PORT" -U "$PGSQL_USER" -d "$PGSQL_NAME" -f max/db/schema.sql
|
||||
psql -1 -v ON_ERROR_STOP=1 -h "$PGSQL_HOST" -p "$PGSQL_PORT" -U "$PGSQL_USER" -d "$PGSQL_NAME" -f "$(dirname "${BASH_SOURCE[0]}")/schema.sql"
|
||||
|
||||
echo "end db setup"
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
export FLASK_ENV=production
|
||||
gunicorn -w 1 -b 0.0.0.0:8000 max.app:app
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
flask run --host 0.0.0.0 --port 8000
|
||||
File renamed without changes.
Reference in new issue
Block a user