Skip to content

Commit

Permalink
Merge pull request #206 from reef-technologies/gunicorn-unix
Browse files Browse the repository at this point in the history
Use unix domain socket for gunicorn
  • Loading branch information
olzhasar-reef authored Nov 4, 2024
2 parents ad24032 + 457a37d commit c2504ec
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 12 deletions.
2 changes: 0 additions & 2 deletions {{cookiecutter.repostory_name}}/app/envs/prod/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,4 @@ RUN grep psycopg pdm.lock && apk add --no-cache libpq || true
RUN grep Pillow pdm.lock && apk add --no-cache jpeg tiff zlib libwebp || true
{%- endif %}

EXPOSE 8000

CMD ["./entrypoint.sh"]
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
workers = min(max_workers, workers)
threads = env.int("GUNICORN_THREADS", 1)
preload_app = env.bool("GUNICORN_PRELOAD_APP", True)
bind = "0.0.0.0:8000"
bind = "unix:/var/run/gunicorn/gunicorn.sock"
{%- if cookiecutter.use_channels == "y" %}
wsgi_app = "{{ cookiecutter.django_project_name }}.asgi:application"
{%- else %}
Expand Down
33 changes: 33 additions & 0 deletions {{cookiecutter.repostory_name}}/app/src/healthcheck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3

import argparse
import socket
import sys


def healthcheck(socket_path: str, url: str):
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
s.settimeout(1)
s.connect(socket_path)
req = f"GET {url} HTTP/1.1\r\n\r\n"
s.sendall(req.encode())
response = s.recv(64)
assert response, "No response received"

status_code = int(response.decode().split()[1])
assert status_code == 200, f"Unexpected status code: {status_code}"

sys.stdout.write("OK\n")


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("socket_path", type=str, help="Path to the socket file")
parser.add_argument("--url", type=str, required=False, default="/admin/login/", help="URL to check")
args = parser.parse_args()

try:
healthcheck(args.socket_path, args.url)
except Exception as e:
sys.stderr.write(f"Error: {e}\n")
sys.exit(1)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ services:
init: true
restart: always
env_file: ./.env
healthcheck:
test: ["CMD", "./healthcheck.py", "/var/run/gunicorn/gunicorn.sock"]
{% if cookiecutter.monitoring == 'y' %}
environment:
# Add this variable to all containers that should dump Prometheus metrics. Each container besides this one
Expand All @@ -16,6 +18,7 @@ services:
{% endif %}
volumes:
- backend-static:/root/src/static
- gunicorn-socket:/var/run/gunicorn
- ./media:/root/src/media
{% if cookiecutter.monitoring == 'y' %}
# Add this mount to each container that should dump Prometheus metrics.
Expand Down Expand Up @@ -67,7 +70,7 @@ services:
image: 'ghcr.io/reef-technologies/nginx-rt:v1.2.2'
restart: unless-stopped
healthcheck:
test: wget -q --spider http://0.0.0.0:8000/admin/login || exit 1
test: wget -q --spider http://0.0.0.0:8000/admin/login/ || exit 1
depends_on:
- app
{% if cookiecutter.monitoring == 'y' %}
Expand All @@ -86,6 +89,7 @@ services:
- backend-static:/srv/static:ro
- ./media:/srv/media:ro
- ./nginx/monitoring_certs:/etc/monitoring_certs
- gunicorn-socket:/var/run/gunicorn:ro
logging:
driver: awslogs
options:
Expand All @@ -100,3 +104,4 @@ services:

volumes:
backend-static:
gunicorn-socket:
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
upstream gunicorn {
server unix:/var/run/gunicorn/gunicorn.sock fail_timeout=0;
}

server {
listen 8000 default_server;
server_name _;
Expand Down Expand Up @@ -43,7 +47,7 @@ server {
{% if cookiecutter.nginx_tls_early_data_enabled == 'y' -%}
proxy_set_header Early-Data $ssl_early_data;
{%- endif %}
proxy_pass http://app:8000/;
proxy_pass http://gunicorn;
}
}

Expand Down Expand Up @@ -98,7 +102,7 @@ server {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X_SCHEME $scheme;
proxy_pass http://app:8000/metrics;
proxy_pass http://gunicorn/metrics;
}

location /business-metrics/ {
Expand All @@ -107,7 +111,7 @@ server {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X_SCHEME $scheme;
proxy_pass http://app:8000/business-metrics;
proxy_pass http://gunicorn/business-metrics;
}

}
Expand Down
7 changes: 5 additions & 2 deletions {{cookiecutter.repostory_name}}/envs/prod/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ services:
dockerfile: app/Dockerfile
image: {{cookiecutter.django_project_name}}/app
healthcheck:
test: wget -q --spider 127.0.0.1:8000/admin/login/ || exit 1
test: ["CMD", "./healthcheck.py", "/var/run/gunicorn/gunicorn.sock"]
init: true
restart: unless-stopped
env_file: ./.env
Expand All @@ -49,6 +49,7 @@ services:
{%- endif %}
volumes:
- backend-static:/root/src/static
- gunicorn-socket:/var/run/gunicorn
- ./media:/root/src/media
{% if cookiecutter.monitoring == 'y' -%}
# Add this mount to each container that should dump Prometheus metrics.
Expand Down Expand Up @@ -125,7 +126,7 @@ services:
healthcheck:
test: [
"CMD-SHELL",
"curl 0.0.0.0:80 -s --fail -H \"Host: $NGINX_HOST\" -H \"User-Agent: docker-compose-healthcheck\" -o /dev/null || exit 1"
"curl 0.0.0.0:80/admin/login/ -s --fail -H \"Host: $NGINX_HOST\" -H \"User-Agent: docker-compose-healthcheck\" -o /dev/null || exit 1"
]
interval: 30s
retries: 5
Expand All @@ -140,6 +141,7 @@ services:
- ./media:/srv/media:ro
- ./letsencrypt/etc:/etc/letsencrypt
- ./nginx/monitoring_certs:/etc/monitoring_certs
- gunicorn-socket:/var/run/gunicorn:ro
depends_on:
- app
{% if cookiecutter.monitoring == 'y' %}
Expand Down Expand Up @@ -217,3 +219,4 @@ services:

volumes:
backend-static:
gunicorn-socket:
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
# Generated for Intermediate configuration, nginx 1.20.1 or later
#

upstream gunicorn {
server unix:/var/run/gunicorn/gunicorn.sock fail_timeout=0;
}

server {
listen 80 default_server;
server_name _;
Expand Down Expand Up @@ -106,7 +110,7 @@ server {
{% if cookiecutter.nginx_tls_early_data_enabled == 'y' -%}
proxy_set_header Early-Data $ssl_early_data;
{%- endif %}
proxy_pass http://app:8000/;
proxy_pass http://gunicorn;
}
}

Expand Down Expand Up @@ -161,7 +165,7 @@ server {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X_SCHEME $scheme;
proxy_pass http://app:8000/metrics;
proxy_pass http://gunicorn/metrics;
}

location /business-metrics {
Expand All @@ -170,7 +174,7 @@ server {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X_SCHEME $scheme;
proxy_pass http://app:8000/business-metrics;
proxy_pass http://gunicorn/business-metrics;
}
}
{%- endif %}
Expand Down

0 comments on commit c2504ec

Please sign in to comment.