From e60c26c9330474748fdd82684e5b8847518f6b33 Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 18 Feb 2024 14:59:43 +0100 Subject: [PATCH 1/8] update pyYaml version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2ed6456..fd3a359 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ nodeenv==1.7.0 platformdirs==3.1.1 pre-commit==3.1.1 pytz==2022.7.1 -PyYAML==6.0 +PyYAML==6.0.1 sqlparse==0.4.3 tzdata==2022.7 virtualenv==20.21.0 From 772fa869e5faec02c788494b039eca551292b7cc Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 18 Feb 2024 19:59:27 +0000 Subject: [PATCH 2/8] added Dockerfile and changed database to Postgres --- .dockerignore | 5 +++ Dockerfile | 74 +++++++++++++++++++++++++++++++++++++++++ docker-entrypoint.sh | 15 +++++++++ prod.env | 10 ++++++ requirements.txt | 4 ++- tally/tally/settings.py | 16 +++++++-- tally/tally/urls.py | 4 ++- 7 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-entrypoint.sh create mode 100644 prod.env diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6d4e845 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +*.md +.venv +.vscode +.github +.devcontainer diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..33fdc6a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,74 @@ +# pull official base image +FROM python:3.11.4-slim-buster as builder + +# set work directory +WORKDIR /usr/src/app + +# set environment variables +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +# install system dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc + +# # lint +# RUN pip install --upgrade pip +# RUN pip install flake8==6.0.0 +# COPY . /usr/src/app/ +# RUN flake8 --ignore=E501,F401 . + +# install python dependencies +COPY ./requirements.txt . +RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt + + + + +# pull official base image +FROM python:3.11.4-slim-buster + +# create directory for the app user +RUN mkdir -p /home/app + +# create the app user +RUN addgroup --system app && adduser --system --group app + +# create the appropriate directories +ENV HOME=/home/app +ENV APP_HOME=/home/app/web +RUN mkdir $APP_HOME +WORKDIR $APP_HOME + +# install dependencies +RUN apt-get update && apt-get install -y --no-install-recommends netcat +COPY --from=builder /usr/src/app/wheels /wheels +COPY --from=builder /usr/src/app/requirements.txt . +RUN pip install --upgrade pip && \ + pip install --no-cache /wheels/* + + +# copy docker-entrypoint.sh +COPY ./docker-entrypoint.sh . +RUN sed -i 's/\r$//g' $APP_HOME/docker-entrypoint.sh +RUN chmod +x $APP_HOME/docker-entrypoint.sh + +# copy project +COPY ./tally/ $APP_HOME +COPY ./prod.env ./prod.env + +RUN set -a && \ + . ./prod.env && \ + python manage.py collectstatic --noinput --no-post-process + + +# chown all the files to the app user +RUN chown -R app:app $APP_HOME + +# change to the app user +USER app + +# run docker-entrypoint.sh +ENTRYPOINT ["/home/app/web/docker-entrypoint.sh"] +CMD ["gunicorn", "-b=0.0.0.0:8000", "tally.wsgi:application"] +EXPOSE 8000 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..4f2ee16 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +if [ "$DATABASE" = "postgres" ] +then + echo "Waiting for postgres..." + + while ! nc -z $SQL_HOST $SQL_PORT; do + sleep 0.1 + done + + echo "PostgreSQL started" + ./manage.py migrate --noinput +fi + +exec $@ diff --git a/prod.env b/prod.env new file mode 100644 index 0000000..e902927 --- /dev/null +++ b/prod.env @@ -0,0 +1,10 @@ +DEBUG=0 +SECRET_KEY=change_me +DJANGO_ALLOWED_HOSTS=0.0.0.0 localhost 127.0.0.1 [::1] +SQL_ENGINE=django.db.backends.postgresql +SQL_DATABASE=postgres +SQL_USER=postgres +SQL_PASSWORD=postgres +SQL_HOST=db +SQL_PORT=5432 +DATABASE=postgres \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index fd3a359..69bbef3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,13 +2,16 @@ asgiref==3.6.0 cfgv==3.3.1 distlib==0.3.6 Django==4.1.7 +django-dbsettings==1.3.0 django-filter==22.1 djangorestframework==3.14.0 filelock==3.9.1 +gunicorn==21.2.0 identify==2.5.20 importlib-metadata==6.0.0 Markdown==3.4.1 nodeenv==1.7.0 +packaging==23.2 platformdirs==3.1.1 pre-commit==3.1.1 pytz==2022.7.1 @@ -17,4 +20,3 @@ sqlparse==0.4.3 tzdata==2022.7 virtualenv==20.21.0 zipp==3.15.0 -django-dbsettings==1.3 diff --git a/tally/tally/settings.py b/tally/tally/settings.py index 547be2c..c824bfe 100644 --- a/tally/tally/settings.py +++ b/tally/tally/settings.py @@ -80,10 +80,14 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ.get('POSTGRES_NAME'), + 'USER': os.environ.get('POSTGRES_USER'), + 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), + 'HOST': 'db', + 'PORT': 5432, #default port you don't need to mention in docker-compose + } } -} # Password validation @@ -122,6 +126,12 @@ STATIC_URL = 'static/' +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = os.path.join(os.path.dirname(__file__), "../static/") + # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field diff --git a/tally/tally/urls.py b/tally/tally/urls.py index 92e5704..8dac1dd 100644 --- a/tally/tally/urls.py +++ b/tally/tally/urls.py @@ -15,13 +15,15 @@ """ from django.contrib import admin from django.urls import include, path +from django.conf.urls.static import static import products.urls as products_urls import transactions.urls as transactions_urls +import tally.settings as settings urlpatterns = [ path("admin/", admin.site.urls), path("settings/", include("dbsettings.urls")), path("products/", include((products_urls.router.urls, "products"))), path("transactions/", include((transactions_urls.router.urls, "transactions"))), -] +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file From 83cb04086428975a718ed9d189ea5724ac06787d Mon Sep 17 00:00:00 2001 From: Jules Fleuren Date: Sun, 18 Feb 2024 20:12:05 +0000 Subject: [PATCH 3/8] add psycopg2 dependency --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 69bbef3..259988e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ nodeenv==1.7.0 packaging==23.2 platformdirs==3.1.1 pre-commit==3.1.1 +psycopg2-binary==2.9.9 pytz==2022.7.1 PyYAML==6.0.1 sqlparse==0.4.3 From 9da2fb6209270bade05976254ee0db3dca992ed5 Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 20 Feb 2024 13:23:42 +0100 Subject: [PATCH 4/8] Environment variables are now actually used --- Dockerfile | 4 +--- docker-entrypoint.sh | 8 ++++---- prod.env | 13 ++++++------- tally/tally/settings.py | 14 +++++++------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index 33fdc6a..269b724 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,9 +57,7 @@ RUN chmod +x $APP_HOME/docker-entrypoint.sh COPY ./tally/ $APP_HOME COPY ./prod.env ./prod.env -RUN set -a && \ - . ./prod.env && \ - python manage.py collectstatic --noinput --no-post-process +RUN python manage.py collectstatic --noinput --no-post-process # chown all the files to the app user diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 4f2ee16..b2c5ce4 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,15 +1,15 @@ #!/bin/sh -if [ "$DATABASE" = "postgres" ] +if [ "$1" = "gunicorn" ] then echo "Waiting for postgres..." - while ! nc -z $SQL_HOST $SQL_PORT; do + while ! nc -z $DB_HOST $DB_PORT; do sleep 0.1 done echo "PostgreSQL started" - ./manage.py migrate --noinput + python ./manage.py migrate --noinput fi -exec $@ +exec "$@" diff --git a/prod.env b/prod.env index e902927..a2f6e75 100644 --- a/prod.env +++ b/prod.env @@ -1,10 +1,9 @@ DEBUG=0 SECRET_KEY=change_me DJANGO_ALLOWED_HOSTS=0.0.0.0 localhost 127.0.0.1 [::1] -SQL_ENGINE=django.db.backends.postgresql -SQL_DATABASE=postgres -SQL_USER=postgres -SQL_PASSWORD=postgres -SQL_HOST=db -SQL_PORT=5432 -DATABASE=postgres \ No newline at end of file +DB_ENGINE=django.db.backends.postgresql +DB_NAME=tally +DB_USER=postgres +DB_PASSWORD=postgres +DB_HOST=db +DB_PORT=5432 diff --git a/tally/tally/settings.py b/tally/tally/settings.py index c824bfe..5849e27 100644 --- a/tally/tally/settings.py +++ b/tally/tally/settings.py @@ -24,7 +24,7 @@ SECRET_KEY = 'django-insecure-q7jl@rw2!95&&oe=5!3^ygji+8x0&%9e^s^nr9@-0^5a@)gs=r' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.getenv('DEBUG', True) ALLOWED_HOSTS = [] @@ -80,12 +80,12 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': os.environ.get('POSTGRES_NAME'), - 'USER': os.environ.get('POSTGRES_USER'), - 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), - 'HOST': 'db', - 'PORT': 5432, #default port you don't need to mention in docker-compose + 'ENGINE': os.getenv('DB_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DB_NAME', 'tally'), + 'USER': os.getenv('DB_USER', 'postgres'), + 'PASSWORD': os.getenv('DB_PASSWORD', 'postgres'), + 'HOST': os.getenv('DB_HOST', 'db'), + 'PORT': int(os.getenv('DB_PORT', 5432)) } } From e0d9993bf590949da9aa69fbe0fa07843ec525ed Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 20 Feb 2024 12:39:44 +0000 Subject: [PATCH 5/8] added devcontainer --- .devcontainer/Dockerfile | 12 ++++++++++ .devcontainer/devcontainer.env | 9 +++++++ .devcontainer/devcontainer.json | 24 +++++++++++++++++++ .devcontainer/docker-compose.yml | 41 ++++++++++++++++++++++++++++++++ .devcontainer/postCreate.sh | 5 ++++ .vscode/launch.json | 2 +- 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.env create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml create mode 100644 .devcontainer/postCreate.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..911f982 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,12 @@ +FROM mcr.microsoft.com/devcontainers/python:1-3.11-bullseye + +ENV PYTHONUNBUFFERED 1 + +# [Optional] If your requirements rarely change, uncomment this section to add them to the image. +# COPY requirements.txt /tmp/pip-tmp/ +# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ +# && rm -rf /tmp/pip-tmp + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends diff --git a/.devcontainer/devcontainer.env b/.devcontainer/devcontainer.env new file mode 100644 index 0000000..6d60528 --- /dev/null +++ b/.devcontainer/devcontainer.env @@ -0,0 +1,9 @@ +DEBUG=0 +SECRET_KEY=dev +DJANGO_ALLOWED_HOSTS=0.0.0.0 localhost 127.0.0.1 [::1] +DB_ENGINE=django.db.backends.postgresql +DB_NAME=tally +DB_USER=postgres +DB_PASSWORD=postgres +DB_HOST=db +DB_PORT=5432 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..3eb8129 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/postgres +{ + "name": "Python 3 & PostgreSQL", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // This can be used to network with other containers or the host. + "forwardPorts": [8000, 5432, 8080], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "./.devcontainer/postCreate.sh" + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 0000000..ea1313a --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,41 @@ +version: '3.8' + +services: + app: + env_file: devcontainer.env + build: + context: .. + dockerfile: .devcontainer/Dockerfile + + volumes: + - ../..:/workspaces:cached + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + db: + image: postgres:latest + restart: unless-stopped + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_DB: tally + POSTGRES_PASSWORD: postgres + + # Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + adminer: + image: adminer + restart: unless-stopped + network_mode: service:db + +volumes: + postgres-data: diff --git a/.devcontainer/postCreate.sh b/.devcontainer/postCreate.sh new file mode 100644 index 0000000..18e1a54 --- /dev/null +++ b/.devcontainer/postCreate.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +pip install --user -r requirements.txt +cd tally +python manage.py migrate diff --git a/.vscode/launch.json b/.vscode/launch.json index 43298c2..caf336f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "Python: Django", "type": "python", "request": "launch", - "program": "${workspaceFolder}\\tally\\manage.py", + "program": "${workspaceFolder}/tally/manage.py", "args": [ "runserver" ], From b4a5e90b7ad5fe9c8df0e469013703c9dd72650a Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 20 Feb 2024 13:47:02 +0100 Subject: [PATCH 6/8] added docker-compose file --- docker-compose.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1d7fecc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.9" + +services: + web: + build: . + ports: + - "8000:8000" + env_file: + - prod.env + depends_on: + - db + + db: + image: postgres + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=tally + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + + +volumes: + postgres-data: \ No newline at end of file From e7ba96f3d489900af0cf1a9da9508d76edb944bd Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 20 Feb 2024 14:41:35 +0100 Subject: [PATCH 7/8] added devcontainer instructions to readme --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 8710cb3..a59dbdf 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ If the backend is finished, these are the features that the server has. ## Run Locally +There is also a docker devcontainer for this project. See [devcontainer](#devcontainer). + Clone the project ```bash @@ -78,6 +80,16 @@ Superuser created successfully. You can now log in into the admin panel. +## Devcontainer + +This repository has a devcontainer that has been tested in VS Code. The devcontainer will automatically install all dependencies, start a postgres container and an adminer container. On the first build of the container it will also run the migrations. + +To be able to run the devcontainer you need to have VS Code installed with the [dev containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). + +First clone the repository and open it with VS Code. Now run the following command in the VS Code command palette: `Dev Containers: Reopen in Container`. (You can open the command palette with `Ctrl+Shift+P`). + +Once everything has started succesfully you should be able to access adminer on `localhost:8080`. To be able to run and acces tally itself, you might still need to [create an admin user](#creating-an-admin-user) (first do `cd tally`). Then you can run tally by pressing `Start Debugging (F5)` or by running the command `python manage.py runserver`. You should now be able to access tally on `localhost:8000`. If you want to run the migrations, use the command `python manage.py migrate`. + ## Environment Variables (Dummy text) Dummy text To run this project, you will need to add the following environment variables to your .env file From e944baa2d32deb83ccf843dc0e1a936f68d0beed Mon Sep 17 00:00:00 2001 From: Jules Date: Tue, 20 Feb 2024 14:00:47 +0000 Subject: [PATCH 8/8] fixed requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 51b79dc..d174536 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,10 +29,10 @@ python-dotenv==1.0.1 psycopg2-binary==2.9.9 pytz==2022.7.1 PyYAML==6.0.1 -PyYAML==6.0 requests==2.31.0 sqlparse==0.4.3 tzdata==2022.7 urllib3==2.2.1 virtualenv==20.21.0 zipp==3.15.0 +django-cors-headers==4.3.1