diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1c9fb40 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12 +WORKDIR /app + + +# install python dependencies + +COPY requirements.txt requirements.txt + +RUN pip3 install --no-cache-dir -r requirements.txt + +COPY lobby/ lobby/ + +## add finalization arguments + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 CMD curl -f -X GET http://localhost:1717/health + +EXPOSE 1717 + +CMD [ "python3", "lobby/main.py", "prod"] diff --git a/README.md b/README.md index 8d90286..27ba3b1 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,30 @@ # The Lob(b)y Server Everybody Asked For! More to come here... + + +## Deploy with docker compose + +You need a running docker service and docker compose installed + + +Then build the image: + +```bash +docker build -t obpf-lobby . +``` + +Now you can run the docker compose file. + +```bash +docker compose up -d +``` +Note: the port is 1717 to proxy it through something like nginx. + + +Other common docker compose comands include: +```bash +docker compose down # stop all containers +docker compose ps # get details about running containers +docker compose logs -f # see the logs of all containers (-f watches them) +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0531fd4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3.8" +name: "obpf-lobby" +services: + flask: + container_name: obpf-lobby + image: obpf-lobby:latest + ports: + - "1717:1717" + volumes: + - "./files/:/app/files/" diff --git a/lobby/main.py b/lobby/main.py index f28c7df..8df5b04 100644 --- a/lobby/main.py +++ b/lobby/main.py @@ -1,4 +1,5 @@ import os.path +import sys import time import typing from dataclasses import dataclass @@ -81,6 +82,11 @@ def from_id(cls, id_: str) -> Self: return cls(id_, user.username) +@app.route("/health", methods=["GET"]) +def health_check(): + return create_ok_response({}) + + @app.route("/lobbies", methods=["GET"]) def lobby_list(): @dataclass @@ -198,4 +204,11 @@ class RegisterRequest(JsonSchemaMixin): return create_response(HTTPStatus.CREATED, {"id": new_user.id}) -app.run(debug=True) +# this runs, when you launch this file manually, otherwise flask imports this file and ignores this +if __name__ == "__main__": + print(sys.argv) + if len(sys.argv) >= 2 and sys.argv[1] == "prod": + from waitress import serve + serve(app, host="0.0.0.0", port=1717) + else: + app.run(debug=True) diff --git a/requirements.txt b/requirements.txt index fc526d2..c31d378 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,4 +23,5 @@ setuptools==69.0.3 six==1.16.0 SQLAlchemy==2.0.25 typing_extensions==4.9.0 +waitress==2.1.2 Werkzeug==3.0.1