From 53a3372e5f8bf2ddcaa0a90d012a50fbf2402fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borek=20Po=C5=BE=C3=A1r?= Date: Mon, 2 Oct 2023 11:13:53 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Pokus=20o=20dockerizaci,=20zat=C3=ADm=20(sn?= =?UTF-8?q?ad)=20ekvivalentn=C3=AD=20lok=C3=A1ln=C3=AD=20instalaci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 36 ++++++++++++++++++++++++++++++++++++ docker-compose.yml | 25 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c385c34f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM python:3.9.18-slim-bullseye + +# set work directory +WORKDIR /usr/src + +# set environment variables +ENV PIP_DISABLE_PIP_VERSION_CHECK 1 +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +# install dependencies +RUN apt-get update && apt-get install -y \ + libpq-dev \ + gcc \ + locales \ + imagemagick +RUN pip install --upgrade pip +COPY ./requirements.txt . +COPY ./constraints.txt . +RUN pip install -r requirements.txt + +# allow correct locales +RUN sed -i '/cs_CZ.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen +ENV LANG cs_CZ.UTF-8 \ + LANGUAGE en_US:en \ + LC_ALL cs_CZ.UTF-8 + +# copy project +COPY . . + +# create test data +RUN ./manage.py testdata +RUN ./manage.py loaddata data/* + # make/sync_prod_flatpages && \ + # ./manage.py load_org_permissions deploy_v2/admin_org_prava.json \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..72851cd8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,25 @@ + +# TODO: +# - [ ] Pořídit vhodný django settings.py pro docker, aby to používalo postgress +services: + web: + build: . + command: python manage.py runserver 0.0.0.0:8000 + volumes: + - .:/usr/src + ports: + - 8000:8000 + # env_file: + # - ./.env.dev + +# db: +# image: postgres:13-bullseye +# volumes: +# - postgres_data:/var/lib/postgresql/data/ +# environment: +# - POSTGRES_USER=hello_django +# - POSTGRES_PASSWORD=hello_django +# - POSTGRES_DB=hello_django_dev + +# volumes: +# postgres_data: \ No newline at end of file -- 2.39.5 From 1937f3a4c995fda982e1942f3a9f48b3f6e78ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borek=20Po=C5=BE=C3=A1r?= Date: Mon, 2 Oct 2023 13:27:39 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Docker=20p=C5=99esv=C4=9Bd=C4=8Den,=20aby?= =?UTF-8?q?=20pou=C5=BE=C3=ADval=20Postgres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vyrobeno nové `mamweb/settings_docker.py` jako kříženec mezi `_local` a `_test`. Úměrně tomu upraveno `mamweb/settings.py`, aby ho používalo při volání z kontejneru.`docker_entrypoint.sh` počká na start konejneru s Postgresem, zkontroluje existenci testdat (případně je vygeneruje) a spustí command specifikovaný v compose, tedy spustí webserver. --- Dockerfile | 20 +++---- docker-compose.yml | 28 +++++---- docker_entrypoint.sh | 19 +++++++ mamweb/settings.py | 3 + mamweb/settings_docker.py | 117 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 25 deletions(-) create mode 100755 docker_entrypoint.sh create mode 100644 mamweb/settings_docker.py diff --git a/Dockerfile b/Dockerfile index c385c34f..b288c765 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM python:3.9.18-slim-bullseye # set work directory -WORKDIR /usr/src +WORKDIR /usr/mamweb-docker # set environment variables ENV PIP_DISABLE_PIP_VERSION_CHECK 1 @@ -13,7 +13,9 @@ RUN apt-get update && apt-get install -y \ libpq-dev \ gcc \ locales \ - imagemagick + imagemagick \ + netcat \ + postgresql-client RUN pip install --upgrade pip COPY ./requirements.txt . COPY ./constraints.txt . @@ -22,15 +24,13 @@ RUN pip install -r requirements.txt # allow correct locales RUN sed -i '/cs_CZ.UTF-8/s/^# //g' /etc/locale.gen && \ locale-gen -ENV LANG cs_CZ.UTF-8 \ - LANGUAGE en_US:en \ - LC_ALL cs_CZ.UTF-8 +ENV LANG cs_CZ.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL cs_CZ.UTF-8 # copy project COPY . . -# create test data -RUN ./manage.py testdata -RUN ./manage.py loaddata data/* - # make/sync_prod_flatpages && \ - # ./manage.py load_org_permissions deploy_v2/admin_org_prava.json \ No newline at end of file +# create test data once db is ready +RUN chmod +x /usr/mamweb-docker/docker_entrypoint.sh +ENTRYPOINT ["/usr/mamweb-docker/docker_entrypoint.sh"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 72851cd8..f916a735 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,25 +1,23 @@ -# TODO: -# - [ ] Pořídit vhodný django settings.py pro docker, aby to používalo postgress services: web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - - .:/usr/src + - .:/usr/mamweb-docker ports: - 8000:8000 - # env_file: - # - ./.env.dev + depends_on: + - db -# db: -# image: postgres:13-bullseye -# volumes: -# - postgres_data:/var/lib/postgresql/data/ -# environment: -# - POSTGRES_USER=hello_django -# - POSTGRES_PASSWORD=hello_django -# - POSTGRES_DB=hello_django_dev + db: + image: postgres:13-bullseye + volumes: + - postgres_data:/var/lib/postgresql/data/ + environment: + - POSTGRES_USER=mam-web + - POSTGRES_PASSWORD=RoEGG5g7&b # Random generated string corresponding with Django settings + - POSTGRES_DB=mam_docker -# volumes: -# postgres_data: \ No newline at end of file +volumes: + postgres_data: \ No newline at end of file diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh new file mode 100755 index 00000000..eb5842a3 --- /dev/null +++ b/docker_entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +echo "Waiting for Postgres..." + +while ! nc -z "db" "5432"; do + sleep 0.1 +done + +echo "PostgreSQL started" + +PGPASSWORD="RoEGG5g7&b" # Random generated, corresponds to the one in docker-compose.yml +if psql "postgresql://mam-web:$PGPASSWORD@db:5432/mam_docker" -t -c '\dt' | cut -d \| -f 2 | grep -qw "seminar_cisla"; then + echo "\nExistuje tabulka 'seminar_cisla' v db, testdata pravděpodobně byla vygenerována.\n" +else + python ./manage.py testdata + python ./manage.py loaddata data/* +fi + +exec "$@" diff --git a/mamweb/settings.py b/mamweb/settings.py index 6f5d302f..98f70f91 100644 --- a/mamweb/settings.py +++ b/mamweb/settings.py @@ -14,6 +14,9 @@ if "mamweb-test" in os.path.abspath(__file__): elif "mamweb-prod" in os.path.abspath(__file__): from .settings_prod import * +elif "mamweb-docker" in os.path.abspath(__file__): + from .settings_docker import * + else: from .settings_local import * diff --git a/mamweb/settings_docker.py b/mamweb/settings_docker.py new file mode 100644 index 00000000..913135d5 --- /dev/null +++ b/mamweb/settings_docker.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- + +import os.path + +# +# Docker nastaveni settings.py +# +# Pro vyber tohoto nastaveni muzete pouzit tez: +# DJANGO_SETTINGS_MODULE=mamweb.settings_docker ./manage.py ... +# + +# Import common settings +from .settings_common import * # zatim nutne, casem snad vyresime # noqa + +MIDDLEWARE += ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ + +INSTALLED_APPS += ( + 'debug_toolbar', + 'django_extensions', + ) + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'EZfSzeuDCycKr5ZjiCQ^45ZqFU@8Ke#YDwn9ThqerfEpu^yV#p' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True +INTERNAL_IPS = ['127.0.0.1'] + +TEMPLATES[0]['OPTIONS']['debug'] = True + +from ipaddress import ip_network +ALLOWED_HOSTS = [str(ip) for ip in ip_network('192.168.0.0/16')] +ALLOWED_HOSTS.append('127.0.0.1') +ALLOWED_HOSTS.append('localhost') + +# Database +# https://docs.djangoproject.com/en/1.7/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'mam_docker', + 'USER': 'mam-web', + 'PASSWORD': 'RoEGG5g7&b', # Random generated string corresponding with docker-compose + 'TEST': { + 'NAME': 'mam-docker-testdb', + }, + "HOST": "db", + "PORT": "5432", + }, +} + +# import os +# SERVER_EMAIL = 'mamweb-test-errors@mam.mff.cuni.cz' +# ADMINS = [ +# ('M&M ERRORs', 'mam-errors@mam.mff.cuni.cz'), +# ] + +# SECURITY: only send sensitive cookies via HTTPS +# SESSION_COOKIE_SECURE = True +# CSRF_COOKIE_SECURE = True + +# LOGGING +LOGGING = { + 'version': 1, + 'disable_existing_loggers': True, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'formatters': { + 'simple': { + 'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(message)s', + }, + }, + 'handlers': { + 'dummy': { + 'class': 'logging.NullHandler', + }, + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + }, + }, + 'loggers': { + # Vypisovani databazovych dotazu do konzole + #'django.db.backends': { + # 'level': 'DEBUG', + # 'handlers': ['console'], + # 'propagate': False, + #}, + 'werkzeug': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': True, + }, + '': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + }, +} + +# FILE_UPLOAD_PERMISSIONS = 0o440 + +# Testování e-mailů +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +SEND_EMAIL_NOTIFICATIONS = True +LOCAL_TEST_PROD = "local" -- 2.39.5 From 29d97c60a38987f2186b629392b1ebc975fc236a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borek=20Po=C5=BE=C3=A1r?= Date: Thu, 14 Dec 2023 13:43:47 +0100 Subject: [PATCH 3/4] seetings pro docker jen upravuje detaily z local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `seetings_docker` importuje `settings_local` a přepisuje jen `SECRET_KEY` a `DATABASES` --- mamweb/settings_docker.py | 86 +-------------------------------------- 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/mamweb/settings_docker.py b/mamweb/settings_docker.py index 913135d5..1f73ed5b 100644 --- a/mamweb/settings_docker.py +++ b/mamweb/settings_docker.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -import os.path - # # Docker nastaveni settings.py # @@ -12,32 +10,11 @@ import os.path # Import common settings from .settings_common import * # zatim nutne, casem snad vyresime # noqa -MIDDLEWARE += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', - ) - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ - -INSTALLED_APPS += ( - 'debug_toolbar', - 'django_extensions', - ) +from mamweb.settings_local import * # Import all the settings for local development # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'EZfSzeuDCycKr5ZjiCQ^45ZqFU@8Ke#YDwn9ThqerfEpu^yV#p' -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True -INTERNAL_IPS = ['127.0.0.1'] - -TEMPLATES[0]['OPTIONS']['debug'] = True - -from ipaddress import ip_network -ALLOWED_HOSTS = [str(ip) for ip in ip_network('192.168.0.0/16')] -ALLOWED_HOSTS.append('127.0.0.1') -ALLOWED_HOSTS.append('localhost') - # Database # https://docs.djangoproject.com/en/1.7/ref/settings/#databases @@ -54,64 +31,3 @@ DATABASES = { "PORT": "5432", }, } - -# import os -# SERVER_EMAIL = 'mamweb-test-errors@mam.mff.cuni.cz' -# ADMINS = [ -# ('M&M ERRORs', 'mam-errors@mam.mff.cuni.cz'), -# ] - -# SECURITY: only send sensitive cookies via HTTPS -# SESSION_COOKIE_SECURE = True -# CSRF_COOKIE_SECURE = True - -# LOGGING -LOGGING = { - 'version': 1, - 'disable_existing_loggers': True, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'formatters': { - 'simple': { - 'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(message)s', - }, - }, - 'handlers': { - 'dummy': { - 'class': 'logging.NullHandler', - }, - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'formatter': 'simple', - }, - }, - 'loggers': { - # Vypisovani databazovych dotazu do konzole - #'django.db.backends': { - # 'level': 'DEBUG', - # 'handlers': ['console'], - # 'propagate': False, - #}, - 'werkzeug': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': True, - }, - '': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': False, - }, - }, -} - -# FILE_UPLOAD_PERMISSIONS = 0o440 - -# Testování e-mailů -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -SEND_EMAIL_NOTIFICATIONS = True -LOCAL_TEST_PROD = "local" -- 2.39.5 From ea026fef7a54bf1385a4a5d3af0149d0de946eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Borek=20Po=C5=BE=C3=A1r?= Date: Thu, 14 Dec 2023 14:41:41 +0100 Subject: [PATCH 4/4] =?UTF-8?q?Snaha=20o=20zadokumentov=C3=A1n=C3=AD=20i?= =?UTF-8?q?=20jinde=20ne=C5=BE=20v=20PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docker.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/docker.rst diff --git a/docs/docker.rst b/docs/docker.rst new file mode 100644 index 00000000..12b48e1e --- /dev/null +++ b/docs/docker.rst @@ -0,0 +1,15 @@ +Lokální vývoj pomocí dockeru +============================ + +Přijde vám standardní zprovoznění painful? Docker comes to the rescue. Stačí mít nainstalovaný ``docker`` a spustit ``docker compose up``. + +Co se děje under the hood +------------------------- + +- ``docker-compose.yml`` specifikuje, že chceme kontejner pro web, který je závislý na kontejneru s PostgreSQL db + - ``web`` se buildí z ``Dockerfilu``, mountuje si kořen repa jako svůj volume (takže vidí změny), na konci spouští webserver a vysatvuje ho na port 8000 localhosta + - ``db`` je z ``postgres:13-bullseye`` a má nastavené nějaké parametry, svoje data ukládá jako docker volume +- ``Dockerfile`` staví ``web`` na pythonu3.9 a debianu bullseye (mělo by odpovídat gimlimu) - nainstaluje dependencies, nastaví locale a entrypoint (co se má vykonat při spouštění kontejneru) +- ``docker_entrypoint.sh`` počká na Postgres ready v ``db``, podívá se jestli jsou v něm testdata a když ne, tak je vygeneruje, pak spustí command z compose (i.e. webserver) +- ``mamweb/settings.py`` vybere django settings podle cesty (jako doteď), vybere ``mamweb/settings_docker.py``, které importuje všechno z ``mamweb/settings_local.py``, přepíše jen ``DATABASES`` a ``SECRET_KEY``, aby se jako DB Engine používal Postgres ve vedlejším kontejneru, aby se celý web choval stejně jako ``_test`` a ``_prod`` (``_local`` aktuálně používá DB Engine sqlite3, které se v něčem chová trochu rozdílně) +- kontejner ``web`` se musí nějak připojovat k postgresu v ``db``, k tomu slouží user ``mam-web``, náhodně vygenerované heslo (v ``docker-compose.yml`` a ``docker_entrypoint.sh``, musí se shodovat), db se jmenuje ``mam_docker`` -- 2.39.5