Browse Source

Libros funcionando en producción

politica
Celestino Rey 1 year ago
parent
commit
d2c4715488
55 changed files with 1179 additions and 45 deletions
  1. +2
    -0
      Libros/.dockerignore
  2. +49
    -0
      Libros/Dockerfile
  3. +16
    -2
      Libros/K8S/Makefile
  4. +10
    -0
      Libros/K8S/env-prod-configmap.yaml
  5. +33
    -16
      Libros/K8S/libros-deployment.yaml
  6. +45
    -0
      Libros/K8S/nginx-deployment.yaml
  7. +19
    -0
      Libros/K8S/nginx-service.yaml
  8. +15
    -2
      Libros/K8S/pv-local-libros.yaml
  9. +12
    -0
      Libros/K8S/static-volume-persistentvolumeclaim.yaml
  10. +1
    -1
      Libros/K8S/verImg.sh
  11. +8
    -0
      Libros/Makefile
  12. +5
    -1
      Libros/README.md
  13. +32
    -6
      Libros/biblioteca/biblioteca/settings.py
  14. BIN
      Libros/biblioteca/datos/libros.sqlite3
  15. +14
    -14
      Libros/biblioteca/gestion/migrations/0001_initial.py
  16. +0
    -3
      Libros/biblioteca/gestion/templatetags/filtros_de_entorno.py
  17. +6
    -0
      Libros/entrypoint.sh
  18. +4
    -0
      Libros/nginx/Dockerfile
  19. +8
    -0
      Libros/nginx/Makefile
  20. +25
    -0
      Libros/nginx/nginx.conf
  21. +6
    -0
      Libros/requirements.txt
  22. +10
    -0
      django-on-docker/.env.dev
  23. +10
    -0
      django-on-docker/.env.prod
  24. +3
    -0
      django-on-docker/.env.prod.db
  25. +42
    -0
      django-on-docker/K8S/db-deployment.yaml
  26. +17
    -0
      django-on-docker/K8S/env-dev-configmap.yaml
  27. +12
    -0
      django-on-docker/K8S/postgres-data-persistentvolumeclaim.yaml
  28. +14
    -0
      django-on-docker/K8S/pv-local-hello.yaml
  29. +174
    -0
      django-on-docker/K8S/web-cm0-configmap.yaml
  30. +94
    -0
      django-on-docker/K8S/web-deployment.yaml
  31. +16
    -0
      django-on-docker/K8S/web-service.yaml
  32. +29
    -0
      django-on-docker/app/Dockerfile
  33. +74
    -0
      django-on-docker/app/Dockerfile.prod
  34. +15
    -0
      django-on-docker/app/entrypoint.prod.sh
  35. +18
    -0
      django-on-docker/app/entrypoint.sh
  36. +0
    -0
      django-on-docker/app/hello_django/__init__.py
  37. +16
    -0
      django-on-docker/app/hello_django/asgi.py
  38. +137
    -0
      django-on-docker/app/hello_django/settings.py
  39. +14
    -0
      django-on-docker/app/hello_django/urls.py
  40. +16
    -0
      django-on-docker/app/hello_django/wsgi.py
  41. +22
    -0
      django-on-docker/app/manage.py
  42. BIN
      django-on-docker/app/mediafiles/How to Install Kubernetes Cluster on Ubuntu 24.04 LTS (Step-by-Step Guide) by Hakan Bayraktar Medium.pdf
  43. +3
    -0
      django-on-docker/app/requirements.txt
  44. +0
    -0
      django-on-docker/app/upload/__init__.py
  45. +3
    -0
      django-on-docker/app/upload/admin.py
  46. +6
    -0
      django-on-docker/app/upload/apps.py
  47. +0
    -0
      django-on-docker/app/upload/migrations/__init__.py
  48. +3
    -0
      django-on-docker/app/upload/models.py
  49. +13
    -0
      django-on-docker/app/upload/templates/upload.html
  50. +3
    -0
      django-on-docker/app/upload/tests.py
  51. +15
    -0
      django-on-docker/app/upload/views.py
  52. +35
    -0
      django-on-docker/docker-compose.prod.yml
  53. +25
    -0
      django-on-docker/docker-compose.yml
  54. +4
    -0
      django-on-docker/nginx/Dockerfile
  55. +26
    -0
      django-on-docker/nginx/nginx.conf

+ 2
- 0
Libros/.dockerignore View File

@ -0,0 +1,2 @@
Dockerfile
Makefile

+ 49
- 0
Libros/Dockerfile View File

@ -0,0 +1,49 @@
# syntax=docker/dockerfile:1
FROM python:3.11.4-slim-buster
#FROM python:3.9.19-slim-bullseye
# set work directory
WORKDIR /app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# install system dependencies
RUN apt-get update && apt-get install -y sqlite3
# create directory for the app user
RUN mkdir -p /app
# create the app user
#RUN addgroup --system app && adduser --system --group app
# create the appropriate directories
ENV APP_HOME=/app
RUN mkdir -p $APP_HOME
RUN mkdir -p $APP_HOME/staticfiles
RUN mkdir -p $APP_HOME/mediafiles
WORKDIR $APP_HOME
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r /app/requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh .
# copy project
COPY . $APP_HOME
# chown all the files to the app user
#RUN chown -R app:app $APP_HOME
# change to the app user
#USER app
WORKDIR $APP_HOME/biblioteca
# run entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]

+ 16
- 2
Libros/K8S/Makefile View File

@ -1,16 +1,30 @@
export IMG_VERSION = 1.0
export ARQUITECTURA := $(shell lscpu |grep itectur | tr -d ' '| cut -f2 -d':')
export IMG_VERSION = 1.17
export IMG_NGINX_VERSION = 1.17
# limpia todo # limpia todo
all: imagen clean install all: imagen clean install
imagen: imagen:
cd ../servicios; make
cd ../; make
install: install:
-kubectl create -f pv-local-libros.yaml -kubectl create -f pv-local-libros.yaml
-kubectl create -f libros-prod-persistentvolumeclaim.yaml -kubectl create -f libros-prod-persistentvolumeclaim.yaml
-kubectl create -f static-volume-persistentvolumeclaim.yaml
-kubectl create -f env-prod-configmap.yaml
-envsubst < libros-deployment.yaml |kubectl create -f - -envsubst < libros-deployment.yaml |kubectl create -f -
-envsubst < nginx-deployment.yaml |kubectl create -f -
-kubectl create -f nginx-service.yaml
clean: clean:
-envsubst < nginx-deployment.yaml |kubectl delete -f -
-kubectl delete -f nginx-service.yaml
-envsubst < libros-deployment.yaml |kubectl delete -f - -envsubst < libros-deployment.yaml |kubectl delete -f -
-kubectl delete -f libros-prod-persistentvolumeclaim.yaml -kubectl delete -f libros-prod-persistentvolumeclaim.yaml
-kubectl delete -f env-prod-configmap.yaml
-kubectl delete -f static-volume-persistentvolumeclaim.yaml
-kubectl delete -f pv-local-libros.yaml -kubectl delete -f pv-local-libros.yaml
nginx:
cd ../nginx; make

+ 10
- 0
Libros/K8S/env-prod-configmap.yaml View File

@ -0,0 +1,10 @@
apiVersion: v1
data:
DEBUG: "0"
DJANGO_ALLOWED_HOSTS: localhost 127.0.0.1 [::1]
SECRET_KEY: change_me
kind: ConfigMap
metadata:
labels:
io.kompose.service: web-env-prod
name: env-prod

+ 33
- 16
Libros/K8S/libros-deployment.yaml View File

@ -3,12 +3,10 @@ kind: Service
metadata: metadata:
name: libros name: libros
spec: spec:
type: NodePort
ports: ports:
- name: http
- name: "8000"
port: 8000 port: 8000
nodePort: 30343
targetPort: libros
targetPort: 8000
selector: selector:
app: libros app: libros
--- ---
@ -31,29 +29,45 @@ spec:
app: libros app: libros
spec: spec:
containers: containers:
#- args:
#- gunicorn
#- --bind
#- 0.0.0.0:5000
#- libros:create_app()
- name: libros
image: registry.reymota.es/libros:$IMG_VERSION
- args:
- gunicorn
- biblioteca.wsgi:application
- --bind
- 0.0.0.0:8000
name: libros
image: registry.reymota.es/libros-$ARQUITECTURA:$IMG_VERSION
env: env:
- name: VERSION - name: VERSION
value: "$IMG_VERSION" value: "$IMG_VERSION"
- name: ENVIRONMENT - name: ENVIRONMENT
value: "Producción" value: "Producción"
- name: DEBUG
valueFrom:
configMapKeyRef:
key: DEBUG
name: env-prod
- name: DJANGO_ALLOWED_HOSTS
valueFrom:
configMapKeyRef:
key: DJANGO_ALLOWED_HOSTS
name: env-prod
- name: SECRET_KEY
valueFrom:
configMapKeyRef:
key: SECRET_KEY
name: env-prod
ports: ports:
- containerPort: 8000 - containerPort: 8000
name: libros
resources: {}
protocol: TCP
volumeMounts: volumeMounts:
- mountPath: /libros/media
- mountPath: /app/biblioteca/mediafiles
name: libros-media name: libros-media
- mountPath: /libros/datos
- mountPath: /app/biblioteca/datos
name: libros-datos name: libros-datos
- mountPath: /libros/gestion/migrations
- mountPath: /app/gestion/migrations
name: libros-migrations name: libros-migrations
- mountPath: /app/biblioteca/staticfiles
name: static-volume
imagePullSecrets: imagePullSecrets:
- name: myregistrykey - name: myregistrykey
restartPolicy: Always restartPolicy: Always
@ -67,4 +81,7 @@ spec:
- name: libros-migrations - name: libros-migrations
persistentVolumeClaim: persistentVolumeClaim:
claimName: libros-migrations claimName: libros-migrations
- name: static-volume
persistentVolumeClaim:
claimName: static-volume
status: {} status: {}

+ 45
- 0
Libros/K8S/nginx-deployment.yaml View File

@ -0,0 +1,45 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: nginx
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
spec:
containers:
- image: registry.reymota.es/nginx-$ARQUITECTURA:$IMG_NGINX_VERSION
name: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /app/biblioteca/staticfiles
name: static-volume
- mountPath: /app/biblioteca/mediafiles
name: libros-media
imagePullSecrets:
- name: myregistrykey
restartPolicy: Always
volumes:
- name: static-volume
persistentVolumeClaim:
claimName: static-volume
- name: libros-media
persistentVolumeClaim:
claimName: libros-media

+ 19
- 0
Libros/K8S/nginx-service.yaml View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: nginx
name: nginx
spec:
type: NodePort
ports:
- name: "1337"
port: 1337
nodePort: 30343
targetPort: 80
selector:
io.kompose.service: nginx

+ 15
- 2
Libros/K8S/pv-local-libros.yaml View File

@ -34,9 +34,22 @@ metadata:
app: libros app: libros
spec: spec:
capacity: capacity:
storage: 50Mi
storage: 150Mi
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
hostPath: hostPath:
path: "/mnt/Externo/libros/datos" path: "/mnt/Externo/libros/datos"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: libros-static-folder
labels:
app: libros
spec:
capacity:
storage: 70Mi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/Externo/libros/static"

+ 12
- 0
Libros/K8S/static-volume-persistentvolumeclaim.yaml View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
io.kompose.service: static-volume
name: static-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 70Mi

+ 1
- 1
Libros/K8S/verImg.sh View File

@ -1 +1 @@
docker run -it registry.reymota.es/libros:1.0 bash
docker run -it registry.reymota.es/libros:1.19 bash

+ 8
- 0
Libros/Makefile View File

@ -0,0 +1,8 @@
install:
echo "Creando imagen con version ${IMG_VERSION}"
docker build --no-cache -t registry.reymota.es/libros-${ARQUITECTURA}:${IMG_VERSION} .
docker push registry.reymota.es/libros-${ARQUITECTURA}:${IMG_VERSION}

+ 5
- 1
Libros/README.md View File

@ -9,4 +9,8 @@ User Group: {{ user.groups.all.0 }}
Email: {{ user.email }} Email: {{ user.email }}
Session Started at: {{ user.last_login }}
Session Started at: {{ user.last_login }}
## Para funcionar con gunicorn y nginx
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/

+ 32
- 6
Libros/biblioteca/biblioteca/settings.py View File

@ -21,13 +21,15 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-q0bxrr=*ab*b8oa#=+-@_4cu-cp6)c3lz#+!c_%51$*!bnz%4!'
#SECRET_KEY = 'django-insecure-q0bxrr=*ab*b8oa#=+-@_4cu-cp6)c3lz#+!c_%51$*!bnz%4!'
SECRET_KEY = os.environ.get("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
#DEBUG = True
ALLOWED_HOSTS = []
DEBUG = bool(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
# Application definition # Application definition
@ -82,7 +84,8 @@ DATABASES = {
'NAME': os.path.join(BASE_DIR, 'datos/libros.sqlite3'), 'NAME': os.path.join(BASE_DIR, 'datos/libros.sqlite3'),
} }
} }
print("DB:",DATABASES)
#print("DB:",DATABASES)
#print("BASE_DIR:",BASE_DIR)
# Password validation # Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
@ -118,7 +121,8 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/ # https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = 'static/'
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / "staticfiles"
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
@ -131,4 +135,26 @@ LOGOUT_REDIRECT_URL = 'principal'
AUTH_USER_MODEL = "gestion.ReyMotaUser" AUTH_USER_MODEL = "gestion.ReyMotaUser"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') # 'media' is my media folder
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') # 'media' is my media folder
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/tmp/debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
CSRF_TRUSTED_ORIGINS = ["http://localhost:30443"]

BIN
Libros/biblioteca/datos/libros.sqlite3 View File


+ 14
- 14
Libros/biblioteca/gestion/migrations/0001_initial.py View File

@ -1,9 +1,9 @@
# Generated by Django 5.1 on 2024-08-13 14:36
# Generated by Django 4.2 on 2024-08-14 14:46
import django.core.validators import django.core.validators
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import gestion.models import gestion.models
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -24,6 +24,18 @@ class Migration(migrations.Migration):
('foto', models.ImageField(blank=True, null=True, upload_to='autores/')), ('foto', models.ImageField(blank=True, null=True, upload_to='autores/')),
], ],
), ),
migrations.CreateModel(
name='Libro',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('titulo', models.CharField(max_length=200)),
('fecha_publicacion', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), gestion.models.max_value_current_year])),
('descripcion', models.TextField(blank=True, null=True)),
('archivo', models.FileField(upload_to='libros/')),
('portada', models.ImageField(blank=True, null=True, upload_to='portadas/')),
('autor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion.autor')),
],
),
migrations.CreateModel( migrations.CreateModel(
name='ReyMotaUser', name='ReyMotaUser',
fields=[ fields=[
@ -43,16 +55,4 @@ class Migration(migrations.Migration):
'abstract': False, 'abstract': False,
}, },
), ),
migrations.CreateModel(
name='Libro',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('titulo', models.CharField(max_length=200)),
('fecha_publicacion', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), gestion.models.max_value_current_year])),
('descripcion', models.TextField(blank=True, null=True)),
('archivo', models.FileField(upload_to='libros/')),
('portada', models.ImageField(blank=True, null=True, upload_to='portadas/')),
('autor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion.autor')),
],
),
] ]

+ 0
- 3
Libros/biblioteca/gestion/templatetags/filtros_de_entorno.py View File

@ -5,7 +5,4 @@ register = template.Library()
@register.filter @register.filter
def muestra_version(clave): def muestra_version(clave):
print("muestra_valor: ", clave)
print("muestra_valor: ", os.getenv(clave))
return os.getenv(clave, '') return os.getenv(clave, '')

+ 6
- 0
Libros/entrypoint.sh View File

@ -0,0 +1,6 @@
#!/bin/bash
python manage.py flush --no-input
python manage.py migrate
exec "$@"

+ 4
- 0
Libros/nginx/Dockerfile View File

@ -0,0 +1,4 @@
FROM nginx:1.25
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

+ 8
- 0
Libros/nginx/Makefile View File

@ -0,0 +1,8 @@
install:
echo "Creando imagen con version ${IMG_NGINX_VERSION} para la arquitectura ${ARQUITECTURA}"
docker build --no-cache -t registry.reymota.es/nginx-${ARQUITECTURA}:${IMG_NGINX_VERSION} .
docker push registry.reymota.es/nginx-${ARQUITECTURA}:${IMG_NGINX_VERSION}

+ 25
- 0
Libros/nginx/nginx.conf View File

@ -0,0 +1,25 @@
upstream libros {
server libros:8000;
}
server {
listen 80;
location / {
proxy_pass http://libros;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
client_max_body_size 100M;
}
location /static/ {
alias /app/biblioteca/staticfiles/;
}
location /media/ {
alias /app/biblioteca/mediafiles/;
}
}

+ 6
- 0
Libros/requirements.txt View File

@ -0,0 +1,6 @@
asgiref==3.8.1
Django==4.2
pillow==10.4.0
sqlparse==0.5.1
typing_extensions==4.12.2
gunicorn==22.0.0

+ 10
- 0
django-on-docker/.env.dev View File

@ -0,0 +1,10 @@
DEBUG=1
SECRET_KEY=foo
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_dev
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

+ 10
- 0
django-on-docker/.env.prod View File

@ -0,0 +1,10 @@
DEBUG=0
SECRET_KEY=change_me
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=hello_django_prod
SQL_USER=hello_django
SQL_PASSWORD=hello_django
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

+ 3
- 0
django-on-docker/.env.prod.db View File

@ -0,0 +1,3 @@
POSTGRES_USER=hello_django
POSTGRES_PASSWORD=hello_django
POSTGRES_DB=hello_django_prod

+ 42
- 0
django-on-docker/K8S/db-deployment.yaml View File

@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: db
name: db
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: db
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: db
spec:
containers:
- env:
- name: POSTGRES_DB
value: hello_django_dev
- name: POSTGRES_PASSWORD
value: hello_django
- name: POSTGRES_USER
value: hello_django
image: postgres:15
name: db
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgres-data
restartPolicy: Always
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-data

+ 17
- 0
django-on-docker/K8S/env-dev-configmap.yaml View File

@ -0,0 +1,17 @@
apiVersion: v1
data:
DATABASE: postgres
DEBUG: "1"
DJANGO_ALLOWED_HOSTS: localhost 127.0.0.1 [::1]
SECRET_KEY: foo
SQL_DATABASE: hello_django_dev
SQL_ENGINE: django.db.backends.postgresql
SQL_HOST: db
SQL_PASSWORD: hello_django
SQL_PORT: "5432"
SQL_USER: hello_django
kind: ConfigMap
metadata:
labels:
io.kompose.service: web-env-dev
name: env-dev

+ 12
- 0
django-on-docker/K8S/postgres-data-persistentvolumeclaim.yaml View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
io.kompose.service: postgres-data
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi

+ 14
- 0
django-on-docker/K8S/pv-local-hello.yaml View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: hello-pg-folder
labels:
app: hello
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/Externo/hello"

+ 174
- 0
django-on-docker/K8S/web-cm0-configmap.yaml View File

@ -0,0 +1,174 @@
apiVersion: v1
data:
Dockerfile: |+
# pull official base image
FROM python:3.11.4-slim-buster
# 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 netcat
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
# copy project
COPY . .
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
Dockerfile.prod: |+
###########
# BUILDER #
###########
# 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
#########
# FINAL #
#########
# 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
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
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
RUN pip install --no-cache /wheels/*
# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
RUN chmod +x $APP_HOME/entrypoint.prod.sh
# copy project
COPY . $APP_HOME
# chown all the files to the app user
RUN chown -R app:app $APP_HOME
# change to the app user
USER app
# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
entrypoint.prod.sh: |+
#!/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"
fi
exec "$@"
entrypoint.sh: |+
#!/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"
fi
#python manage.py flush --no-input
#python manage.py migrate
exec "$@"
manage.py: |
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_django.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
requirements.txt: |
Django==4.2.3
psycopg2-binary==2.9.6
gunicorn==21.2.0
kind: ConfigMap
metadata:
labels:
io.kompose.service: web
name: web-cm0

+ 94
- 0
django-on-docker/K8S/web-deployment.yaml View File

@ -0,0 +1,94 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: web
name: web
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: web
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: web
spec:
containers:
- args:
- python
- manage.py
- runserver
- 0.0.0.0:8000
env:
- name: DATABASE
valueFrom:
configMapKeyRef:
key: DATABASE
name: env-dev
- name: DEBUG
valueFrom:
configMapKeyRef:
key: DEBUG
name: env-dev
- name: DJANGO_ALLOWED_HOSTS
valueFrom:
configMapKeyRef:
key: DJANGO_ALLOWED_HOSTS
name: env-dev
- name: SECRET_KEY
valueFrom:
configMapKeyRef:
key: SECRET_KEY
name: env-dev
- name: SQL_DATABASE
valueFrom:
configMapKeyRef:
key: SQL_DATABASE
name: env-dev
- name: SQL_ENGINE
valueFrom:
configMapKeyRef:
key: SQL_ENGINE
name: env-dev
- name: SQL_HOST
valueFrom:
configMapKeyRef:
key: SQL_HOST
name: env-dev
- name: SQL_PASSWORD
valueFrom:
configMapKeyRef:
key: SQL_PASSWORD
name: env-dev
- name: SQL_PORT
valueFrom:
configMapKeyRef:
key: SQL_PORT
name: env-dev
- name: SQL_USER
valueFrom:
configMapKeyRef:
key: SQL_USER
name: env-dev
image: web
name: web
ports:
- containerPort: 8000
protocol: TCP
volumeMounts:
- mountPath: /usr/src/app
name: web-cm0
restartPolicy: Always
volumes:
- configMap:
name: web-cm0
name: web-cm0

+ 16
- 0
django-on-docker/K8S/web-service.yaml View File

@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.34.0 (cbf2835db)
labels:
io.kompose.service: web
name: web
spec:
ports:
- name: "8000"
port: 8000
targetPort: 8000
selector:
io.kompose.service: web

+ 29
- 0
django-on-docker/app/Dockerfile View File

@ -0,0 +1,29 @@
# pull official base image
FROM python:3.11.4-slim-buster
# 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 netcat
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh
# copy project
COPY . .
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

+ 74
- 0
django-on-docker/app/Dockerfile.prod View File

@ -0,0 +1,74 @@
###########
# BUILDER #
###########
# 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
#########
# FINAL #
#########
# 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
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
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
RUN pip install --no-cache /wheels/*
# copy entrypoint.prod.sh
COPY ./entrypoint.prod.sh .
RUN sed -i 's/\r$//g' $APP_HOME/entrypoint.prod.sh
RUN chmod +x $APP_HOME/entrypoint.prod.sh
# copy project
COPY . $APP_HOME
# chown all the files to the app user
RUN chown -R app:app $APP_HOME
# change to the app user
USER app
# run entrypoint.prod.sh
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]

+ 15
- 0
django-on-docker/app/entrypoint.prod.sh View File

@ -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"
fi
exec "$@"

+ 18
- 0
django-on-docker/app/entrypoint.sh View File

@ -0,0 +1,18 @@
#!/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"
fi
#python manage.py flush --no-input
#python manage.py migrate
exec "$@"

+ 0
- 0
django-on-docker/app/hello_django/__init__.py View File


+ 16
- 0
django-on-docker/app/hello_django/asgi.py View File

@ -0,0 +1,16 @@
"""
ASGI config for hello_django project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_django.settings')
application = get_asgi_application()

+ 137
- 0
django-on-docker/app/hello_django/settings.py View File

@ -0,0 +1,137 @@
import os
"""
Django settings for hello_django project.
Generated by 'django-admin startproject' using Django 4.2.3.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
SECRET_KEY = os.environ.get("SECRET_KEY")
DEBUG = bool(os.environ.get("DEBUG", default=0))
# 'DJANGO_ALLOWED_HOSTS' should be a single string of hosts with a space between each.
# For example: 'DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]'
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'upload',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'hello_django.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'hello_django.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
"NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
"USER": os.environ.get("SQL_USER", "user"),
"PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
"HOST": os.environ.get("SQL_HOST", "localhost"),
"PORT": os.environ.get("SQL_PORT", "5432"),
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "mediafiles"
CSRF_TRUSTED_ORIGINS = ["http://localhost:1337"]

+ 14
- 0
django-on-docker/app/hello_django/urls.py View File

@ -0,0 +1,14 @@
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from upload.views import image_upload
urlpatterns = [
path("", image_upload, name="upload"),
path("admin/", admin.site.urls),
]
if bool(settings.DEBUG):
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ 16
- 0
django-on-docker/app/hello_django/wsgi.py View File

@ -0,0 +1,16 @@
"""
WSGI config for hello_django project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_django.settings')
application = get_wsgi_application()

+ 22
- 0
django-on-docker/app/manage.py View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hello_django.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
django-on-docker/app/mediafiles/How to Install Kubernetes Cluster on Ubuntu 24.04 LTS (Step-by-Step Guide) by Hakan Bayraktar Medium.pdf View File


+ 3
- 0
django-on-docker/app/requirements.txt View File

@ -0,0 +1,3 @@
Django==4.2.3
psycopg2-binary==2.9.6
gunicorn==21.2.0

+ 0
- 0
django-on-docker/app/upload/__init__.py View File


+ 3
- 0
django-on-docker/app/upload/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
django-on-docker/app/upload/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class UploadConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'upload'

+ 0
- 0
django-on-docker/app/upload/migrations/__init__.py View File


+ 3
- 0
django-on-docker/app/upload/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 13
- 0
django-on-docker/app/upload/templates/upload.html View File

@ -0,0 +1,13 @@
{% block content %}
<form action="{% url "upload" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="image_file">
<input type="submit" value="submit" />
</form>
{% if image_url %}
<p>File uploaded at: <a href="{{ image_url }}">{{ image_url }}</a></p>
{% endif %}
{% endblock %}

+ 3
- 0
django-on-docker/app/upload/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 15
- 0
django-on-docker/app/upload/views.py View File

@ -0,0 +1,15 @@
from django.shortcuts import render
from django.core.files.storage import FileSystemStorage
def image_upload(request):
if request.method == "POST" and request.FILES["image_file"]:
image_file = request.FILES["image_file"]
fs = FileSystemStorage()
filename = fs.save(image_file.name, image_file)
image_url = fs.url(filename)
print(image_url)
return render(request, "upload.html", {
"image_url": image_url
})
return render(request, "upload.html")

+ 35
- 0
django-on-docker/docker-compose.prod.yml View File

@ -0,0 +1,35 @@
services:
web:
build:
context: ./app
dockerfile: Dockerfile.prod
command: gunicorn hello_django.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
expose:
- 8000
env_file:
- ./.env.prod
depends_on:
- db
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env.prod.db
nginx:
build: ./nginx
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
ports:
- 1337:80
depends_on:
- web
volumes:
postgres_data:
static_volume:
media_volume:

+ 25
- 0
django-on-docker/docker-compose.yml View File

@ -0,0 +1,25 @@
#version: '3.8'
services:
web:
build: ./app
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
ports:
- 8000:8000
env_file:
- ./.env.dev
depends_on:
- db
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=hello_django
- POSTGRES_PASSWORD=hello_django
- POSTGRES_DB=hello_django_dev
volumes:
postgres_data:

+ 4
- 0
django-on-docker/nginx/Dockerfile View File

@ -0,0 +1,4 @@
FROM nginx:1.25
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

+ 26
- 0
django-on-docker/nginx/nginx.conf View File

@ -0,0 +1,26 @@
upstream hello_django {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
client_max_body_size 100M;
}
location /static/ {
alias /home/app/web/staticfiles/;
}
location /media/ {
alias /home/app/web/mediafiles/;
}
}

Loading…
Cancel
Save