diff --git a/Dockerfile b/Dockerfile index 84bde1b3..e1dbb2ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-r && rm -rf /var/lib/apt/lists/* # Install the application server. -RUN pip install uwsgi django-storages boto3 +RUN pip install uwsgi django-storages boto3 django-prometheus # Install the project requirements. COPY requirements.txt / diff --git a/Dockerfile.local b/Dockerfile.local new file mode 100644 index 00000000..01da44de --- /dev/null +++ b/Dockerfile.local @@ -0,0 +1,58 @@ +# Build staticfiles +FROM node:18-alpine AS node-builder + +WORKDIR /app + +COPY /app . + +WORKDIR /app/tailwind + +RUN npm i + +RUN npm run page:build + +RUN npm run admin:build + +# Use an official Python runtime based on Debian 10 "buster" as a parent image. +FROM python:slim-buster + +# Port used by this container to serve HTTP. +EXPOSE 8000 + +# Set environment variables. +# 1. Force Python stdout and stderr streams to be unbuffered. +# 2. Set PORT variable that is used by Gunicorn. This should match "EXPOSE" +# command. +ENV PYTHONUNBUFFERED=1 \ + PORT=8000 + +# Install system packages required by Django CMS and Django. +RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-recommends \ + build-essential \ + cargo \ + libssl-dev \ + libffi-dev \ + sox \ + ffmpeg \ + libcairo2 \ + libcairo2-dev \ + python3-dev \ +&& rm -rf /var/lib/apt/lists/* + +# Install the application server. +RUN pip install uwsgi django-storages boto3 django-prometheus + +# Install the project requirements. +COPY app/requirements.txt / +RUN pip install -r requirements.txt + +# Use /app folder as a directory where the source code is stored. +WORKDIR /app + +# Copy the source code of the project into the container. +COPY --from=node-builder /app ./ + +RUN python manage.py collectstatic --noinput --clear -i tailwindcss + +# Runtime command that executes when "docker run" is called. +CMD ["uwsgi", "--ini", "/app/wsgi.ini"] \ No newline at end of file diff --git a/app/project/settings/base.py b/app/project/settings/base.py index 5524a0a2..042eb04d 100644 --- a/app/project/settings/base.py +++ b/app/project/settings/base.py @@ -82,10 +82,14 @@ "contrib.ga", # ExperimentaĆ§Ć£o "eleicao", - "django_social_share" + "django_social_share", + # + # "django_prometheus" ] MIDDLEWARE = [ + # "django_prometheus.middleware.PrometheusBeforeMiddleware", + # "django.middleware.security.SecurityMiddleware", "project.middleware.WwwRedirectMiddleware", "eleicao.middleware.EleicaoRedirectMiddleware", @@ -101,6 +105,8 @@ "cms.middleware.page.CurrentPageMiddleware", "cms.middleware.toolbar.ToolbarMiddleware", "cms.middleware.language.LanguageCookieMiddleware", + # + # "django_prometheus.middleware.PrometheusAfterMiddleware", ] ROOT_URLCONF = "project.urls" @@ -142,7 +148,6 @@ "contrib.bonde.router.AuthRouter", ] - # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators diff --git a/app/project/settings_prod.py b/app/project/settings_prod.py index 80a1e4a7..5afd90d7 100644 --- a/app/project/settings_prod.py +++ b/app/project/settings_prod.py @@ -1,22 +1,26 @@ from .settings import * -INSTALLED_APPS += [ - 'project', - 'storages' -] +MIDDLEWARE = ( + ["django_prometheus.middleware.PrometheusBeforeMiddleware"] + + MIDDLEWARE + + ["django_prometheus.middleware.PrometheusAfterMiddleware"] +) + + +INSTALLED_APPS += ["project", "storages", "django_prometheus"] # aws settings -AWS_ACCESS_KEY_ID = env('AWS_ACCESS_KEY_ID') +AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID") -AWS_SECRET_ACCESS_KEY = env('AWS_SECRET_ACCESS_KEY') +AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY") -AWS_STORAGE_BUCKET_NAME = env('AWS_STORAGE_BUCKET_NAME') +AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME") # AWS_DEFAULT_ACL = 'public-read' -AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' +AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com" -AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'} +AWS_S3_OBJECT_PARAMETERS = {"CacheControl": "max-age=86400"} # s3 static settings # STATIC_LOCATION = 'static' @@ -26,8 +30,8 @@ # STATICFILES_STORAGE = 'project.storages.StaticStorage' # s3 public media settings -PUBLIC_MEDIA_LOCATION = 'media' +PUBLIC_MEDIA_LOCATION = "media" -MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/' +MEDIA_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/" -DEFAULT_FILE_STORAGE = 'project.storages.PublicMediaStorage' \ No newline at end of file +DEFAULT_FILE_STORAGE = "project.storages.PublicMediaStorage" diff --git a/app/project/urls.py b/app/project/urls.py index 31118043..ff1b1af6 100644 --- a/app/project/urls.py +++ b/app/project/urls.py @@ -21,16 +21,17 @@ urlpatterns = [ + path("monitoring/", include("django_prometheus.urls")), path("admin/", admin.site.urls), path("select2/", include("django_select2.urls")), path("actions/", include("contrib.actions.pressure.urls")), - path("", include("cms.urls")) + path("", include("cms.urls")), ] urlpatterns += staticfiles_urlpatterns() -handler404 = 'contrib.frontend.views.error_404' -handler500 = 'contrib.frontend.views.error_500' +handler404 = "contrib.frontend.views.error_404" +handler500 = "contrib.frontend.views.error_500" if settings.DEBUG: urlpatterns.extend(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)) diff --git a/app/requirements.txt b/app/requirements.txt index bc355999..b0c725c2 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -17,4 +17,4 @@ bcrypt whitenoise svglib reportlab -django-social-share \ No newline at end of file +django-social-share diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index e335e1ff..a992a6ca 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -20,12 +20,43 @@ services: - traefik.http.services.cms.loadbalancer.server.port=8000 - traefik.http.routers.cms.tls=true - traefik.http.routers.cms.tls.certresolver=myresolver - - traefik.http.routers.cms.rule=${TRAEFIK_ROUTERS_RULE} - # prod - # - traefik.http.routers.cms.rule=HostRegexp(`aeleicaodoano.org`,`{subdomain:[a-z]+}.aeleicaodoano.org`,`cms.bonde.org`,`{subdomain:[a-z]+}.cms.bonde.org`) - # staging - # - traefik.http.routers.cms.rule=HostRegexp(`cms.staging.bonde.org`,`{subdomain:[a-z]+}.cms.staging.bonde.org`) + - traefik.http.routers.cms.rule=${TRAEFIK_ROUTERS_RULE:-"HostRegexp(`cms.staging.bonde.org`)"} + + # prometheus: + # image: prom/prometheus + # restart: 'no' + # user: root + # volumes: + # - prometheus_data:/prometheus + # # - ./prometheus.yml:/etc/prometheus/prometheus.yml + # labels: + # - traefik.enable=true + # - traefik.http.services.prometheus.loadbalancer.server.port=9090 + # - traefik.http.routers.prometheus.tls=true + # - traefik.http.routers.prometheus.tls.certresolver=myresolver + + # grafana: + # image: grafana/grafana + # user: root + # environment: + # GF_INSTALL_PLUGINS: "grafana-clock-panel,grafana-simple-json-datasource" + # restart: 'no' + # volumes: + # - grafana_data:/var/lib/grafana + # depends_on: + # - prometheus + # labels: + # - traefik.enable=true + # - traefik.http.services.grafana.loadbalancer.server.port=3000 + # - traefik.http.routers.grafana.tls=true + # - traefik.http.routers.grafana.tls.certresolver=myresolver networks: default: name: bonde + +# volumes: +# prometheus_data: +# driver: local +# grafana_data: +# driver: local diff --git a/docker-compose.yml b/docker-compose.yml index ea7163bc..6f03f9ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,27 +1,77 @@ services: - web: - build: - context: . - dockerfile: Dockerfile - ports: - - "80:8000" - env_file: - - .env-local - depends_on: - - db + # web: + # build: + # context: . + # dockerfile: Dockerfile.local + # # image: nossas/cms:main + # networks: + # - bonde + # ports: + # - "80:8000" + # env_file: + # - .env-local + # depends_on: + # - db - db: - image: postgres:latest - restart: always - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - - POSTGRES_DB=cms - # logging: - # options: - # max-size: 10m - # max-file: "3" - ports: - - '5432:5432' - volumes: - - /tmp/data:/var/lib/postgresql/data \ No newline at end of file + # db: + # image: postgres:latest + # restart: always + # environment: + # - POSTGRES_USER=postgres + # - POSTGRES_PASSWORD=postgres + # - POSTGRES_DB=cms + # # logging: + # # options: + # # max-size: 10m + # # max-file: "3" + # networks: + # - bonde + # ports: + # - '5432:5432' + # volumes: + # - /tmp/data:/var/lib/postgresql/data + + prometheus: + image: prom/prometheus + restart: 'no' + user: root + volumes: + - /tmp/prometheus_data:/prometheus + - ./deploy/prometheus.yml:/etc/prometheus/prometheus.yml + # networks: + # - bonde + # ports: + # - 9090:9090 + network_mode: "host" + # depends_on: + # - web + + grafana: + image: grafana/grafana + user: root + environment: + GF_INSTALL_PLUGINS: "grafana-clock-panel,grafana-simple-json-datasource" + restart: 'no' + volumes: + - /tmp/grafana_data:/var/lib/grafana + # networks: + # - bonde + # ports: + # - 3000:3000 + network_mode: "host" + depends_on: + - prometheus + + redis: + image: redis:6.2-alpine + restart: always + command: redis-server --save 20 1 --loglevel warning --requirepass eYVX7EwVmmxKPCDmwMtyKVge8oLd2t81 + # ports: + # - '6379:6379' + network_mode: "host" + volumes: + - /tmp/redis_data:/data + +# networks: +# bonde: +# external: True \ No newline at end of file diff --git a/locustfile.py b/locustfile.py new file mode 100644 index 00000000..e776e4f9 --- /dev/null +++ b/locustfile.py @@ -0,0 +1,23 @@ +from locust import HttpUser, task + +class SimulateRequestOverUser(HttpUser): + + @task + def index(self): + self.client.get("/") + + @task + def list(self): + self.client.get("/candidaturas/") + + @task + def admin(self): + self.client.get("/admin") + + @task + def not_found(self): + self.client.get("/not_found/asdasdasd") + + @task + def form(self): + self.client.get("/candidaturas/cadastro/") \ No newline at end of file