mirror of
https://github.com/daniviga/bite.git
synced 2024-11-26 23:06:14 +01:00
Add static support and health-check (#17)
This commit is contained in:
parent
454c4b43cf
commit
b18030f5e5
|
@ -1,3 +1,3 @@
|
||||||
# BITE - BasicIoTExample
|
# BITE - Basic/IoT/Example
|
||||||
|
|
||||||
Playing with IoT
|
Playing with IoT
|
||||||
|
|
|
@ -37,6 +37,9 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'health_check',
|
||||||
|
'health_check.db',
|
||||||
|
# 'health_check.storage',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'api',
|
'api',
|
||||||
'telemetry',
|
'telemetry',
|
||||||
|
@ -126,6 +129,8 @@ USE_TZ = True
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
STATIC_ROOT = '/srv/appdata/bite/static'
|
||||||
|
|
||||||
SKIP_WHITELIST = True
|
SKIP_WHITELIST = True
|
||||||
|
|
||||||
MQTT_BROKER = {
|
MQTT_BROKER = {
|
||||||
|
|
|
@ -22,6 +22,7 @@ from telemetry import urls as telemetry_urls
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
path('ht/', include('health_check.urls')),
|
||||||
path('api/', include(api_urls)),
|
path('api/', include(api_urls)),
|
||||||
path('telemetry/', include(telemetry_urls)),
|
path('telemetry/', include(telemetry_urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'telemetry.apps.TelemetryConfig'
|
|
@ -1,5 +1,10 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
from health_check.plugins import plugin_dir
|
||||||
|
|
||||||
|
|
||||||
class TelemetryConfig(AppConfig):
|
class TelemetryConfig(AppConfig):
|
||||||
name = 'telemetry'
|
name = 'telemetry'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
from telemetry.health import MQTTHealthCheck
|
||||||
|
plugin_dir.register(MQTTHealthCheck)
|
||||||
|
|
24
bite/telemetry/health.py
Normal file
24
bite/telemetry/health.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import socket
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
|
from health_check.backends import BaseHealthCheckBackend
|
||||||
|
from health_check.exceptions import ServiceUnavailable
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
MQTT_HOST = settings.MQTT_BROKER['HOST']
|
||||||
|
MQTT_PORT = int(settings.MQTT_BROKER['PORT'])
|
||||||
|
|
||||||
|
|
||||||
|
class MQTTHealthCheck(BaseHealthCheckBackend):
|
||||||
|
critical_service = True
|
||||||
|
|
||||||
|
def check_status(self):
|
||||||
|
client = mqtt.Client(client_id="django-hc")
|
||||||
|
try:
|
||||||
|
client.connect(MQTT_HOST, port=MQTT_PORT)
|
||||||
|
client.disconnect()
|
||||||
|
except (socket.gaierror, ConnectionRefusedError):
|
||||||
|
self.add_error(ServiceUnavailable("Connection refused"))
|
||||||
|
|
||||||
|
def identifier(self):
|
||||||
|
return self.__class__.__name__
|
|
@ -1,3 +1,4 @@
|
||||||
|
import socket
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
@ -46,8 +47,11 @@ class Command(BaseCommand):
|
||||||
try:
|
try:
|
||||||
client.connect(MQTT_HOST, MQTT_PORT)
|
client.connect(MQTT_HOST, MQTT_PORT)
|
||||||
break
|
break
|
||||||
except ConnectionRefusedError:
|
except (socket.gaierror, ConnectionRefusedError):
|
||||||
self.stdout.write('WARNING: Broker not available')
|
self.stdout.write(
|
||||||
|
self.style.WARNING('WARNING: Broker not available'))
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS('INFO: Broker subscribed'))
|
||||||
client.disconnect()
|
client.disconnect()
|
||||||
asyncio.run(self.mqtt_broker())
|
asyncio.run(self.mqtt_broker())
|
||||||
|
|
|
@ -15,7 +15,10 @@ COPY --from=builder /usr/local/lib/python3.8/site-packages/ /usr/local/lib/pytho
|
||||||
COPY --chown=1000:1000 bite /srv/app/bite
|
COPY --chown=1000:1000 bite /srv/app/bite
|
||||||
COPY --chown=1000:1000 requirements.txt /tmp/requirements.txt
|
COPY --chown=1000:1000 requirements.txt /tmp/requirements.txt
|
||||||
|
|
||||||
RUN pip3 install -r /tmp/requirements.txt && rm /tmp/requirements.txt
|
RUN mkdir -p /srv/appdata/bite/static \
|
||||||
|
&& chown -R 1000:1000 /srv/appdata/bite \
|
||||||
|
&& pip3 install -r /tmp/requirements.txt \
|
||||||
|
&& rm /tmp/requirements.txt
|
||||||
|
|
||||||
USER 1000:1000
|
USER 1000:1000
|
||||||
WORKDIR /srv/app/bite
|
WORKDIR /srv/app/bite
|
||||||
|
|
21
docker/docker-compose.dev.yml
Normal file
21
docker/docker-compose.dev.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
timescale:
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
bite:
|
||||||
|
volumes:
|
||||||
|
- ../bite:/srv/app/bite
|
||||||
|
command: ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
|
||||||
|
data-migration:
|
||||||
|
volumes:
|
||||||
|
- ../bite:/srv/app/bite
|
||||||
|
|
||||||
|
mqtt-to-db:
|
||||||
|
volumes:
|
||||||
|
- ../bite:/srv/app/bite
|
|
@ -1,20 +1,15 @@
|
||||||
version: "3.7"
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
ingress:
|
|
||||||
# command: --providers.docker # For traefik only
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
|
|
||||||
bite:
|
bite:
|
||||||
volumes:
|
volumes:
|
||||||
- "./django/production.py.sample:/srv/app/bite/bite/production.py"
|
- ./django/production.py.sample:/srv/app/bite/bite/production.py
|
||||||
command: ["gunicorn", "-b", "0.0.0.0:8000", "bite.wsgi:application"]
|
command: ["gunicorn", "-b", "0.0.0.0:8000", "bite.wsgi:application"]
|
||||||
|
|
||||||
data-migration:
|
data-migration:
|
||||||
volumes:
|
volumes:
|
||||||
- "./django/production.py.sample:/srv/app/bite/bite/production.py"
|
- ./django/production.py.sample:/srv/app/bite/bite/production.py
|
||||||
|
|
||||||
mqtt-to-db:
|
mqtt-to-db:
|
||||||
volumes:
|
volumes:
|
||||||
- "./django/production.py.sample:/srv/app/bite/bite/production.py"
|
- ./django/production.py.sample:/srv/app/bite/bite/production.py
|
||||||
|
|
|
@ -5,6 +5,7 @@ networks:
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
|
staticdata:
|
||||||
|
|
||||||
x-op-service-default: &service_default
|
x-op-service-default: &service_default
|
||||||
restart: always # unless-stopped
|
restart: always # unless-stopped
|
||||||
|
@ -44,25 +45,13 @@ services:
|
||||||
<<: *service_default
|
<<: *service_default
|
||||||
image: nginx:stable-alpine
|
image: nginx:stable-alpine
|
||||||
ports:
|
ports:
|
||||||
- "8000:80"
|
- "80:80"
|
||||||
networks:
|
networks:
|
||||||
- net
|
- net
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
- staticdata:/srv/appdata/bite/static
|
||||||
|
- ./ingress/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
|
||||||
# User traefix instead of nginx
|
|
||||||
# ingress:
|
|
||||||
# <<: *service_default
|
|
||||||
# image: traefik:v2.2
|
|
||||||
# command: --api.insecure=true --providers.docker
|
|
||||||
# ports:
|
|
||||||
# - "8000:80"
|
|
||||||
# - "8080:8080"
|
|
||||||
# networks:
|
|
||||||
# - net
|
|
||||||
# volumes:
|
|
||||||
# # So that Traefik can listen to the Docker events
|
|
||||||
# - /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
|
|
||||||
bite:
|
bite:
|
||||||
<<: *service_default
|
<<: *service_default
|
||||||
|
@ -70,33 +59,31 @@ services:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: ./docker/django/Dockerfile
|
dockerfile: ./docker/django/Dockerfile
|
||||||
image: daniviga/bite
|
image: daniviga/bite
|
||||||
volumes:
|
command: ["gunicorn", "-b", "0.0.0.0:8000", "bite.wsgi:application"]
|
||||||
- "../bite:/srv/app/bite"
|
|
||||||
command: ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
|
|
||||||
networks:
|
networks:
|
||||||
- net
|
- net
|
||||||
depends_on:
|
depends_on:
|
||||||
- ingress
|
- ingress
|
||||||
- data-migration
|
- data-migration
|
||||||
- timescale
|
- timescale
|
||||||
labels:
|
|
||||||
- "traefik.http.routers.bite.rule=PathPrefix(`/`)"
|
|
||||||
|
|
||||||
data-migration:
|
data-migration:
|
||||||
image: daniviga/bite
|
image: daniviga/bite
|
||||||
volumes:
|
|
||||||
- "../bite:/srv/app/bite"
|
|
||||||
command: ["dockerize", "-wait", "tcp://timescale:5432", "python3", "manage.py", "migrate", "--noinput"]
|
command: ["dockerize", "-wait", "tcp://timescale:5432", "python3", "manage.py", "migrate", "--noinput"]
|
||||||
networks:
|
networks:
|
||||||
- net
|
- net
|
||||||
depends_on:
|
depends_on:
|
||||||
- timescale
|
- timescale
|
||||||
|
|
||||||
|
static-files:
|
||||||
|
image: daniviga/bite
|
||||||
|
volumes:
|
||||||
|
- staticdata:/srv/appdata/bite/static
|
||||||
|
command: ["python3", "manage.py", "collectstatic", "--noinput"]
|
||||||
|
|
||||||
mqtt-to-db:
|
mqtt-to-db:
|
||||||
<<: *service_default
|
<<: *service_default
|
||||||
image: daniviga/bite
|
image: daniviga/bite
|
||||||
volumes:
|
|
||||||
- "../bite:/srv/app/bite"
|
|
||||||
command: ["python3", "manage.py", "mqtt-to-db"]
|
command: ["python3", "manage.py", "mqtt-to-db"]
|
||||||
networks:
|
networks:
|
||||||
- net
|
- net
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export DOCKER_HOST='127.0.0.1:22375'
|
export DOCKER_HOST='127.0.0.1:22375'
|
||||||
docker-compose -f docker-compose.edge.yml up -d --scale device-http=4
|
docker-compose -f docker-compose.modules.yml up -d --scale device-http=4
|
||||||
```
|
```
|
||||||
|
|
21
docker/ingress/docker-compose.traefik.yml
Normal file
21
docker/ingress/docker-compose.traefik.yml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
ingress:
|
||||||
|
<<: *service_default
|
||||||
|
image: traefik:v2.2
|
||||||
|
command: --api.insecure=true --providers.docker
|
||||||
|
ports:
|
||||||
|
- "8000:80"
|
||||||
|
- "8080:8080"
|
||||||
|
networks:
|
||||||
|
- net
|
||||||
|
volumes:
|
||||||
|
# So that Traefik can listen to the Docker events
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
restart: always
|
||||||
|
init: true
|
||||||
|
|
||||||
|
bite:
|
||||||
|
labels:
|
||||||
|
- "traefik.http.routers.bite.rule=PathPrefix(`/`)"
|
|
@ -51,6 +51,10 @@ http {
|
||||||
proxy_connect_timeout 300;
|
proxy_connect_timeout 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /static/ {
|
||||||
|
root /srv/appdata/bite;
|
||||||
|
}
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
error_page 500 502 503 504 /50x.html;
|
||||||
location = /50x.html {
|
location = /50x.html {
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
|
@ -1,5 +1,6 @@
|
||||||
Django
|
Django
|
||||||
djangorestframework
|
djangorestframework
|
||||||
|
django-health-check
|
||||||
psycopg2-binary
|
psycopg2-binary
|
||||||
paho-mqtt==1.5.0
|
paho-mqtt==1.5.0
|
||||||
asyncio-mqtt==0.5.0
|
asyncio-mqtt==0.5.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user