migrate from traefik+nginx to angie

This commit is contained in:
ghostforpy 2024-08-17 11:59:43 +03:00
parent d8051c9db2
commit 6e59392f91
8 changed files with 117 additions and 146 deletions

View File

@ -32,7 +32,7 @@ production-ready Django projects quickly.
- Optional custom static build using Gulp or Webpack
- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable)
- Media storage using Amazon S3, Google Cloud Storage, Azure Storage or nginx
- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support)
- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Angie](https://angie.software/) with [LetsEncrypt](https://letsencrypt.org/) support)
- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku
- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/)
- Run tests with unittest or pytest

View File

@ -0,0 +1,5 @@
FROM docker.angie.software/angie:minimal
RUN rm /etc/angie/angie.conf && apk add --no-cache angie-console-light
COPY ./compose/production/angie/default.conf /etc/angie/angie.conf
CMD ["angie", "-g", "daemon off;"]

View File

@ -0,0 +1,93 @@
events {
worker_connections 1024;
}
http {
include /etc/angie/mime.types;
resolver 127.0.0.11;
acme_client {{ cookiecutter.project_slug }} https://acme-v02.api.letsencrypt.org/directory email={{ cookiecutter.email }};
acme_client_path /var/lib/angie/acme/domains;
upstream backend {
server django:5000;
}
{%- if cookiecutter.use_celery == 'y' %}
upstream flower {
server flower:5555;
}
{%- endif %}
server {
listen 80;
listen 443 ssl;
{%- if cookiecutter.domain_name.count('.') == 1 %}
server_name {{ cookiecutter.domain_name }} www.{{ cookiecutter.domain_name }};
{%- else %}
server_name {{ cookiecutter.domain_name }};
{%- endif %}
acme {{ cookiecutter.project_slug }};
ssl_certificate $acme_cert_{{ cookiecutter.project_slug }};
ssl_certificate_key $acme_cert_key_{{ cookiecutter.project_slug }};
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
{%- if cookiecutter.cloud_provider == 'None' %}
location /media/ {
root /usr/share/angie;
}
location /static/ {
root /usr/share/angie;
}
location = /favicon.ico {
root /usr/share/angie/static/images/favicons;
}
{% endif %}
}
{%- if cookiecutter.use_celery == 'y' %}
server {
listen 5555 ssl;
server_name {{ cookiecutter.domain_name }};
acme {{ cookiecutter.project_slug }};
ssl_certificate $acme_cert_{{ cookiecutter.project_slug }};
ssl_certificate_key $acme_cert_key_{{ cookiecutter.project_slug }};
location / {
proxy_pass http://flower;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{%- endif %}
server {
listen 5558 ssl;
server_name {{ cookiecutter.domain_name }};
acme {{ cookiecutter.project_slug }};
ssl_certificate $acme_cert_{{ cookiecutter.project_slug }};
ssl_certificate_key $acme_cert_key_{{ cookiecutter.project_slug }};
location /console/ {
auto_redirect on;
alias /usr/share/angie-console-light/html/;
index index.html;
location /console/api/ {
api /status/;
}
}
}
}

View File

@ -1,2 +0,0 @@
FROM docker.io/nginx:1.17.8-alpine
COPY ./compose/production/nginx/default.conf /etc/nginx/conf.d/default.conf

View File

@ -1,7 +0,0 @@
server {
listen 80;
server_name localhost;
location /media/ {
alias /usr/share/nginx/media/;
}
}

View File

@ -1,5 +0,0 @@
FROM docker.io/traefik:2.11.2
RUN mkdir -p /etc/traefik/acme \
&& touch /etc/traefik/acme/acme.json \
&& chmod 600 /etc/traefik/acme/acme.json
COPY ./compose/production/traefik/traefik.yml /etc/traefik

View File

@ -1,108 +0,0 @@
log:
level: INFO
entryPoints:
web:
# http
address: ':80'
http:
# https://doc.traefik.io/traefik/routing/entrypoints/#entrypoint
redirections:
entryPoint:
to: web-secure
web-secure:
# https
address: ':443'
{%- if cookiecutter.use_celery == 'y' %}
flower:
address: ':5555'
{%- endif %}
certificatesResolvers:
letsencrypt:
# https://doc.traefik.io/traefik/https/acme/#lets-encrypt
acme:
email: '{{ cookiecutter.email }}'
storage: /etc/traefik/acme/acme.json
# https://doc.traefik.io/traefik/https/acme/#httpchallenge
httpChallenge:
entryPoint: web
http:
routers:
web-secure-router:
{%- if cookiecutter.domain_name.count('.') == 1 %}
rule: 'Host(`{{ cookiecutter.domain_name }}`) || Host(`www.{{ cookiecutter.domain_name }}`)'
{%- else %}
rule: 'Host(`{{ cookiecutter.domain_name }}`)'
{%- endif %}
entryPoints:
- web-secure
middlewares:
- csrf
service: django
tls:
# https://doc.traefik.io/traefik/routing/routers/#certresolver
certResolver: letsencrypt
{%- if cookiecutter.use_celery == 'y' %}
flower-secure-router:
rule: 'Host(`{{ cookiecutter.domain_name }}`)'
entryPoints:
- flower
service: flower
tls:
# https://doc.traefik.io/traefik/master/routing/routers/#certresolver
certResolver: letsencrypt
{%- endif %}
{%- if cookiecutter.cloud_provider == 'None' %}
web-media-router:
{%- if cookiecutter.domain_name.count('.') == 1 %}
rule: '(Host(`{{ cookiecutter.domain_name }}`) || Host(`www.{{ cookiecutter.domain_name }}`)) && PathPrefix(`/media/`)'
{%- else %}
rule: 'Host(`{{ cookiecutter.domain_name }}`) && PathPrefix(`/media/`)'
{%- endif %}
entryPoints:
- web-secure
middlewares:
- csrf
service: django-media
tls:
certResolver: letsencrypt
{%- endif %}
middlewares:
csrf:
# https://doc.traefik.io/traefik/master/middlewares/http/headers/#hostsproxyheaders
# https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
headers:
hostsProxyHeaders: ['X-CSRFToken']
services:
django:
loadBalancer:
servers:
- url: http://django:5000
{%- if cookiecutter.use_celery == 'y' %}
flower:
loadBalancer:
servers:
- url: http://flower:5555
{%- endif %}
{%- if cookiecutter.cloud_provider == 'None' %}
django-media:
loadBalancer:
servers:
- url: http://nginx:80
{%- endif %}
providers:
# https://doc.traefik.io/traefik/master/providers/file/
file:
filename: /etc/traefik/traefik.yml
watch: true

View File

@ -1,9 +1,10 @@
volumes:
production_postgres_data: {}
production_postgres_data_backups: {}
production_traefik: {}
production_angie: {}
{%- if cookiecutter.cloud_provider == 'None' %}
production_django_media: {}
production_django_static: {}
{%- endif %}
{% if cookiecutter.use_celery == 'y' %}
production_redis_data: {}
@ -32,6 +33,7 @@ services:
{%- if cookiecutter.cloud_provider == 'None' %}
volumes:
- production_django_media:/app/{{ cookiecutter.project_slug }}/media
- production_django_static:/app/staticfiles
{%- endif %}
depends_on:
- postgres
@ -52,22 +54,6 @@ services:
env_file:
- ./.envs/.production/.postgres
traefik:
build:
context: .
dockerfile: ./compose/production/traefik/Dockerfile
image: {{ cookiecutter.project_slug }}_production_traefik
depends_on:
- django
volumes:
- production_traefik:/etc/traefik/acme
ports:
- '0.0.0.0:80:80'
- '0.0.0.0:443:443'
{%- if cookiecutter.use_celery == 'y' %}
- '0.0.0.0:5555:5555'
{%- endif %}
redis:
image: docker.io/redis:6
{% if cookiecutter.use_celery == 'y' %}
@ -104,15 +90,24 @@ services:
volumes:
- production_postgres_data_backups:/backups:z
{%- endif %}
{%- if cookiecutter.cloud_provider == 'None' %}
nginx:
angie:
build:
context: .
dockerfile: ./compose/production/nginx/Dockerfile
image: {{ cookiecutter.project_slug }}_production_nginx
dockerfile: ./compose/production/angie/Dockerfile
image: {{ cookiecutter.project_slug }}_production_angie
depends_on:
- django
volumes:
- production_django_media:/usr/share/nginx/media:ro
{%- endif %}
{%- if cookiecutter.cloud_provider == 'None' %}
- production_django_media:/usr/share/angie/media:ro
- production_django_static:/usr/share/angie/static:ro
{%- endif %}
- production_angie:/var/lib/angie/acme
ports:
- '0.0.0.0:80:80'
- '0.0.0.0:443:443'
- '0.0.0.0:5558:5558'
{%- if cookiecutter.use_celery == 'y' %}
- '0.0.0.0:5555:5555'
{%- endif %}