From 42e6905db490498106d8c8d4e15778ebff0ecd21 Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Thu, 19 Feb 2026 16:10:04 +0100 Subject: [PATCH] improved docker startup: frontend now waits for healthy backend --- backend/Dockerfile | 1 + backend/holy_backend/urls.py | 7 +++++++ docker-compose.yml | 9 ++++++++- frontend/Dockerfile | 6 +++++- frontend/entrypoint.sh | 21 +++++++++++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 frontend/entrypoint.sh diff --git a/backend/Dockerfile b/backend/Dockerfile index 636a820..c50cde3 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,6 +10,7 @@ WORKDIR /app # Install dependencies COPY requirements.txt . +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* RUN pip install --no-cache-dir -r requirements.txt # Copy the rest of the backend code diff --git a/backend/holy_backend/urls.py b/backend/holy_backend/urls.py index aec8d25..f114fad 100644 --- a/backend/holy_backend/urls.py +++ b/backend/holy_backend/urls.py @@ -6,12 +6,19 @@ from django.conf import settings from django.conf.urls.static import static from django.views.static import serve from django.views.generic.base import TemplateView +from django.http import HttpResponse import os +def health_check(request): + return HttpResponse("OK", content_type="text/plain") + # Clean the admin path admin_url = os.environ.get('ADMIN_URL', 'admin').strip('/') urlpatterns = [ + # Health check + path('health/', health_check, name='health_check'), + # Robots.txt path('robots.txt', TemplateView.as_view(template_name="robots.txt", content_type="text/plain")), diff --git a/docker-compose.yml b/docker-compose.yml index 127c032..f168e34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,12 @@ services: - "traefik.http.routers.holy-energy-backend.entrypoints=websecure" - "traefik.http.routers.holy-energy-backend.tls.certresolver=https_resolver" - "traefik.http.services.holy-energy-backend.loadbalancer.server.port=8000" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health/"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s frontend: build: @@ -41,7 +47,8 @@ services: env_file: - .env.narl.io depends_on: - - backend + backend: + condition: service_healthy labels: - "traefik.enable=true" - "traefik.docker.network=narl" diff --git a/frontend/Dockerfile b/frontend/Dockerfile index e1f9a98..2850b58 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -27,6 +27,10 @@ FROM nginx:stable-alpine # Copy built files COPY --from=build-stage /app/dist /usr/share/nginx/html +# Copy entrypoint script +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + # Custom Nginx config to handle React Router (SPA) RUN printf 'server {\n\ listen 80;\n\ @@ -38,4 +42,4 @@ RUN printf 'server {\n\ }' > /etc/nginx/conf.d/default.conf EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +ENTRYPOINT ["/entrypoint.sh"] diff --git a/frontend/entrypoint.sh b/frontend/entrypoint.sh new file mode 100644 index 0000000..32b583a --- /dev/null +++ b/frontend/entrypoint.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# The backend hostname is 'holy-backend' based on docker-compose.yml +# We wait for port 8000 to be open +echo "Waiting for backend (holy-backend:8000) to be available..." + +MAX_RETRIES=30 +COUNT=0 + +while ! nc -z holy-backend 8000; do + COUNT=$((COUNT + 1)) + if [ $COUNT -ge $MAX_RETRIES ]; then + echo "Backend timed out after $MAX_RETRIES attempts - starting Nginx anyway" + break + fi + echo "Backend is unavailable (attempt $COUNT/$MAX_RETRIES) - sleeping" + sleep 2 +done + +echo "Starting Nginx..." +exec nginx -g "daemon off;"