Files
audio-engine-hub/Makefile
stephan 528a185d3b feat: Overhaul application and add DX improvements
This commit introduces a wide range of improvements to the application, focusing on stability, developer experience (DX), and documentation.

Key changes include:

- **Fix Application Startup:** Resolved a critical bug where the FastAPI application instance was not correctly exposed, preventing Uvicorn from starting ().
- **Simplify Docker Compose:** Removed the integrated Traefik setup from the default  to support users with existing reverse proxies and simplify the local development environment.
- **Improve Makefile:**
    - Implemented a robust, automatic port-finding mechanism for Starting development environment on port 8001...
#1 [internal] load local bake definitions
#1 reading from stdin 534B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 1.22kB done
#2 WARN: FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 2)
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/python:3.11
#3 DONE 0.7s

#4 [internal] load metadata for docker.io/library/python:3.11-slim
#4 DONE 0.7s

#5 [internal] load .dockerignore
#5 transferring context: 385B done
#5 DONE 0.0s

#6 [builder 1/4] FROM docker.io/library/python:3.11@sha256:bf2d36b8fb1b4a0b590b36736cdd8a6b5175b411bf135c42694ecd68ab8fed02
#6 DONE 0.0s

#7 [stage-1 1/6] FROM docker.io/library/python:3.11-slim@sha256:193fdd0bbcb3d2ae612bd6cc3548d2f7c78d65b549fcaa8af75624c47474444d
#7 DONE 0.0s

#8 [internal] load build context
#8 transferring context: 4.90kB done
#8 DONE 0.0s

#9 [builder 2/4] WORKDIR /opt/venv
#9 CACHED

#10 [stage-1 4/6] WORKDIR /home/appuser
#10 CACHED

#11 [stage-1 3/6] RUN useradd --create-home --shell /bin/bash appuser
#11 CACHED

#12 [stage-1 2/6] RUN apt-get update && apt-get install -y --no-install-recommends     ffmpeg     && rm -rf /var/lib/apt/lists/*
#12 CACHED

#13 [stage-1 5/6] COPY --from=builder /opt/venv /opt/venv
#13 CACHED

#14 [builder 4/4] RUN python -m venv . && . /opt/venv/bin/activate && pip install --no-cache-dir -r requirements.txt
#14 CACHED

#15 [builder 3/4] COPY requirements.txt .
#15 CACHED

#16 [stage-1 6/6] COPY app/ ./app
#16 CACHED

#17 exporting to image
#17 exporting layers done
#17 writing image sha256:6cac7caac7fda2808672ad2f3d117d46d38c1d93013867858543ec74917857b7 done
#17 naming to docker.io/library/audioenginehub-app done
#17 DONE 0.0s

#18 resolving provenance for metadata file
#18 DONE 0.0s and Using host port 8000 for single app container
8a1c69e868e7f13b4c8c9948e81921b48efd9536f326d200b9e912fb12ff66e3 to prevent port conflicts.
    - Added a  target (Running health check on running container...
App container is running on port 8001.
Waiting for app to initialize...
ERROR: Failed to decode JSON from health endpoint.) to run post-deployment sanity checks against the running container's  endpoint.
    - Recommended using Starting development environment on port 8002...
#1 [internal] load local bake definitions
#1 reading from stdin 534B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 1.22kB done
#2 WARN: FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 2)
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/python:3.11-slim
#3 DONE 0.1s

#4 [internal] load metadata for docker.io/library/python:3.11
#4 DONE 0.2s

#5 [internal] load .dockerignore
#5 transferring context: 385B done
#5 DONE 0.0s

#6 [builder 1/4] FROM docker.io/library/python:3.11@sha256:bf2d36b8fb1b4a0b590b36736cdd8a6b5175b411bf135c42694ecd68ab8fed02
#6 DONE 0.0s

#7 [stage-1 1/6] FROM docker.io/library/python:3.11-slim@sha256:193fdd0bbcb3d2ae612bd6cc3548d2f7c78d65b549fcaa8af75624c47474444d
#7 DONE 0.0s

#8 [internal] load build context
#8 transferring context: 1.09GB 5.1s
#8 transferring context: 1.66GB 7.9s done
#8 DONE 8.0s

#9 [builder 3/4] COPY requirements.txt .
#9 CACHED

#10 [builder 4/4] RUN python -m venv . && . /opt/venv/bin/activate && pip install --no-cache-dir -r requirements.txt
#10 CACHED

#11 [stage-1 4/6] WORKDIR /home/appuser
#11 CACHED

#12 [stage-1 3/6] RUN useradd --create-home --shell /bin/bash appuser
#12 CACHED

#13 [builder 2/4] WORKDIR /opt/venv
#13 CACHED

#14 [stage-1 2/6] RUN apt-get update && apt-get install -y --no-install-recommends     ffmpeg     && rm -rf /var/lib/apt/lists/*
#14 CACHED

#15 [stage-1 5/6] COPY --from=builder /opt/venv /opt/venv
#15 CACHED

#16 [stage-1 6/6] COPY app/ ./app
#16 CACHED

#17 exporting to image
#17 exporting layers done
#17 writing image sha256:6cac7caac7fda2808672ad2f3d117d46d38c1d93013867858543ec74917857b7 done
#17 naming to docker.io/library/audioenginehub-app done
#17 DONE 0.0s

#18 resolving provenance for metadata file
#18 DONE 0.0s for reliable port detection.
- **Update Documentation:**
    - Replaced the outdated  (which contained old source code) with a comprehensive guide covering setup, usage, and  commands.
    - Added a note to  to clarify that it describes an older, more advanced setup, pointing readers to the new  for the current recommended workflow.

These changes address the service startup failures and significantly improve the project's usability and maintainability.
2025-12-04 17:33:44 +01:00

146 lines
4.8 KiB
Makefile

SHELL := /bin/bash
# --- Configuration ---
IMAGE_NAME := audio-engine-hub
TAG := latest
# Default internal application port (exposed to Traefik)
PORT := 8000
# Traefik's external entrypoints
TRAEFIK_WEB_PORT := 80
TRAEFIK_DASHBOARD_PORT := 8080
# --- Port Checking Functions ---
# Function to check if required Traefik ports are free
# Exits if any are busy, does not suggest alternatives.
define check_traefik_ports_free
check_traefik_ports_free_func() { \
echo "Checking if Traefik ports ($(TRAEFIK_WEB_PORT), $(TRAEFIK_DASHBOARD_PORT)) are free..." >&2; \
local busy_ports=""; \
if ss -tulnp | grep ":$(TRAEFIK_WEB_PORT) " > /dev/null; then \
busy_ports="$$busy_ports $(TRAEFIK_WEB_PORT)"; \
fi; \
if ss -tulnp | grep ":$(TRAEFIK_DASHBOARD_PORT) " > /dev/null; then \
busy_ports="$$busy_ports $(TRAEFIK_DASHBOARD_PORT)"; \
fi; \
if [ -n "$$busy_ports" ]; then \
echo "ERROR: The following Traefik ports are already in use: $$busy_ports. Please free them or stop Traefik if already running." >&2; \
exit 1; \
fi; \
echo "Traefik ports are free." >&2; \
} ; \
check_traefik_ports_free_func
endef
# --- Docker Commands ---
.PHONY: build
build:
@echo "Building Docker image: $(IMAGE_NAME):$(TAG)"
docker build -t $(IMAGE_NAME):$(TAG) .
.PHONY: run
run:
@APP_PORT=$$(bash -c 'port=$${PORT:-8000}; while ss -tulnp | grep -q :$$port; do echo "Port $$port is busy. Checking next..." >&2; ((port++)); done; echo $$port'); \
echo "Using host port $$APP_PORT for single app container" && \
docker run -d -p $$APP_PORT:$(PORT) --name $(IMAGE_NAME) $(IMAGE_NAME):$(TAG)
.PHONY: stop
stop:
@echo "Stopping Docker containers..."
docker compose stop || true
docker compose rm -f || true
docker stop $(IMAGE_NAME) || true
docker rm $(IMAGE_NAME) || true
.PHONY: logs
logs:
@echo "Showing logs for container: $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)"
docker logs -f $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)
.PHONY: shell
shell:
@echo "Accessing shell in container: $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)"
docker exec -it $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app) /bin/bash
# --- Docker Compose Commands ---
.PHONY: up
up:
@APP_PORT=$$(bash -c 'port=$${PORT:-8000}; while ss -tulnp | grep -q :$$port; do echo "Port $$port is busy. Checking next..." >&2; ((port++)); done; echo $$port'); \
echo "Starting development environment on port $$APP_PORT..."; \
export IMAGE_NAME=$(IMAGE_NAME); \
APP_PORT=$$APP_PORT docker compose up --build -d
.PHONY: down
down:
@echo "Stopping development environment with Docker Compose..."
export IMAGE_NAME=$(IMAGE_NAME) && docker compose down
# --- Image Management ---
.PHONY: tag
tag:
@echo "Tagging image $(IMAGE_NAME):$(TAG) as $(REGISTRY)/$(IMAGE_NAME):$(TAG)"
docker tag $(IMAGE_NAME):$(TAG) $(REGISTRY)/$(IMAGE_NAME):$(TAG)
.PHONY: push
push: tag
@echo "Pushing image $(REGISTRY)/$(IMAGE_NAME):$(TAG) to registry..."
docker push $(REGISTRY)/$(IMAGE_NAME):$(TAG)
.PHONY: test
test:
@if [ -d ".venv" ]; then \
echo "Activating virtual environment..."; \
. .venv/bin/activate; \
fi; \
export PYTHONPATH=$(PWD); \
echo "Running tests with coverage..." && \
pytest --cov=. app/ tests/
.PHONY: health-check
health-check:
@echo "Running health check on running container..."
@CONTAINER_ID=$$(docker compose ps -q app); \
if [ -z "$$CONTAINER_ID" ]; then \
echo "ERROR: App container is not running. Please run 'make up' first." >&2; \
exit 1; \
fi; \
HOST_PORT=$$(docker port $$CONTAINER_ID 8000 | cut -d: -f2); \
if [ -z "$$HOST_PORT" ]; then \
echo "ERROR: Could not determine host port for the app container." >&2; \
exit 1; \
fi; \
echo "App container is running on port $$HOST_PORT."; \
echo "Waiting for app to initialize..."; \
sleep 2; \
curl -s http://localhost:$$HOST_PORT/health | ./scripts/health_check.py
# --- Cleanup ---
.PHONY: clean
clean:
@echo "Cleaning up stopped containers and dangling images..."
docker container prune -f
docker image prune -f
.PHONY: help
help:
@echo "Available commands:"
@echo " build - Build the Docker image"
@echo " run - Run the Docker container (single app, no Traefik)"
@echo " stop - Stop and remove the Docker container"
@echo " logs - Follow the logs of the container"
@echo " shell - Get a shell inside the running container"
@echo " up - Start the dev environment with docker-compose"
@echo " down - Stop the dev environment with docker-compose"
@echo " tag - Tag the image for a registry"
@echo " push - Push the image to a registry (after tagging)"
@echo " test - Run the pytest test suite"
@echo " health-check - Run a sanity check on the deployed container"
@echo " clean - Clean up unused containers and images"
@echo " help - Show this help message"
.DEFAULT_GOAL := help