Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Containerize #23

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 <your-package-list-here>
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer.env
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -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"
}
41 changes: 41 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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:
5 changes: 5 additions & 0 deletions .devcontainer/postCreate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

pip install --user -r requirements.txt
cd tally
python manage.py migrate
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.md
.venv
.vscode
.github
.devcontainer
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}\\tally\\manage.py",
"program": "${workspaceFolder}/tally/manage.py",
"args": [
"runserver"
],
Expand Down
72 changes: 72 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 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 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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
<i>Dummy text</i>
To run this project, you will need to add the following environment variables to your .env file
Expand Down
24 changes: 24 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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:
15 changes: 15 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

if [ "$1" = "gunicorn" ]
then
echo "Waiting for postgres..."

while ! nc -z $DB_HOST $DB_PORT; do
sleep 0.1
done

echo "PostgreSQL started"
python ./manage.py migrate --noinput
fi

exec "$@"
9 changes: 9 additions & 0 deletions prod.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
DEBUG=0
SECRET_KEY=change_me
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
Binary file modified requirements.txt
Binary file not shown.
18 changes: 14 additions & 4 deletions tally/tally/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []

Expand Down Expand Up @@ -82,10 +82,14 @@

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
'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))
}
}
}


# Password validation
Expand Down Expand Up @@ -124,6 +128,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

Expand Down
4 changes: 3 additions & 1 deletion tally/tally/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)