| @ -0,0 +1,2 @@ | |||
| Dockerfile | |||
| Makefile | |||
| @ -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"] | |||
| @ -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 | |||
| all: imagen clean install | |||
| imagen: | |||
| cd ../servicios; make | |||
| cd ../; make | |||
| install: | |||
| -kubectl create -f pv-local-libros.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 < nginx-deployment.yaml |kubectl create -f - | |||
| -kubectl create -f nginx-service.yaml | |||
| clean: | |||
| -envsubst < nginx-deployment.yaml |kubectl delete -f - | |||
| -kubectl delete -f nginx-service.yaml | |||
| -envsubst < libros-deployment.yaml |kubectl delete -f - | |||
| -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 | |||
| nginx: | |||
| cd ../nginx; make | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 @@ | |||
| docker run -it registry.reymota.es/libros:1.0 bash | |||
| docker run -it registry.reymota.es/libros:1.19 bash | |||
| @ -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} | |||
| @ -0,0 +1,6 @@ | |||
| #!/bin/bash | |||
| python manage.py flush --no-input | |||
| python manage.py migrate | |||
| exec "$@" | |||
| @ -0,0 +1,4 @@ | |||
| FROM nginx:1.25 | |||
| RUN rm /etc/nginx/conf.d/default.conf | |||
| COPY nginx.conf /etc/nginx/conf.d | |||
| @ -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} | |||
| @ -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/; | |||
| } | |||
| } | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 | |||
| @ -0,0 +1,3 @@ | |||
| POSTGRES_USER=hello_django | |||
| POSTGRES_PASSWORD=hello_django | |||
| POSTGRES_DB=hello_django_prod | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 | |||
| @ -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" | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 | |||
| @ -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"] | |||
| @ -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"] | |||
| @ -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 "$@" | |||
| @ -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 +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() | |||
| @ -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"] | |||
| @ -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) | |||
| @ -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() | |||
| @ -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() | |||
| @ -0,0 +1,3 @@ | |||
| Django==4.2.3 | |||
| psycopg2-binary==2.9.6 | |||
| gunicorn==21.2.0 | |||
| @ -0,0 +1,3 @@ | |||
| from django.contrib import admin | |||
| # Register your models here. | |||
| @ -0,0 +1,6 @@ | |||
| from django.apps import AppConfig | |||
| class UploadConfig(AppConfig): | |||
| default_auto_field = 'django.db.models.BigAutoField' | |||
| name = 'upload' | |||
| @ -0,0 +1,3 @@ | |||
| from django.db import models | |||
| # Create your models here. | |||
| @ -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 %} | |||
| @ -0,0 +1,3 @@ | |||
| from django.test import TestCase | |||
| # Create your tests here. | |||
| @ -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") | |||
| @ -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: | |||
| @ -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: | |||
| @ -0,0 +1,4 @@ | |||
| FROM nginx:1.25 | |||
| RUN rm /etc/nginx/conf.d/default.conf | |||
| COPY nginx.conf /etc/nginx/conf.d | |||
| @ -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/; | |||
| } | |||
| } | |||