mirror of
https://github.com/pacnpal/simpleguardhome.git
synced 2025-12-20 12:31:16 -05:00
feat(docker): enhance Dockerfile with debugging outputs and install tree utility; update .dockerignore and MANIFEST.in for better packaging
This commit is contained in:
@@ -42,6 +42,3 @@ htmlcov/
|
||||
|
||||
# Project specific
|
||||
rules_backup/
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
37
Dockerfile
37
Dockerfile
@@ -12,6 +12,7 @@ RUN apt-get update && \
|
||||
libc6-dev \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
tree \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& python3 -m pip install --no-cache-dir --upgrade "pip>=21.3" setuptools wheel
|
||||
@@ -26,23 +27,27 @@ RUN mkdir -p /app/src/simpleguardhome && \
|
||||
# Copy source code, maintaining directory structure
|
||||
COPY . /app/
|
||||
|
||||
# Set execute permission for entrypoint script
|
||||
RUN chmod +x /app/docker-entrypoint.sh && \
|
||||
# Debug: Show the copied files and set execute permission for entrypoint script
|
||||
RUN echo "Project structure:" && \
|
||||
tree /app && \
|
||||
echo "Package directory contents:" && \
|
||||
ls -la /app/src/simpleguardhome/ && \
|
||||
chmod +x /app/docker-entrypoint.sh && \
|
||||
cp /app/docker-entrypoint.sh /usr/local/bin/
|
||||
|
||||
# Set PYTHONPATH
|
||||
ENV PYTHONPATH=/app/src
|
||||
|
||||
# Install Python requirements
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Install and verify the package
|
||||
RUN set -e && \
|
||||
# Install Python requirements and verify the package
|
||||
RUN pip install --no-cache-dir -r requirements.txt && \
|
||||
set -e && \
|
||||
echo "Installing package..." && \
|
||||
pip uninstall -y simpleguardhome || true && \
|
||||
# Verify source files exist
|
||||
echo "Verifying source files..." && \
|
||||
ls -la /app/src/simpleguardhome/ && \
|
||||
# Debug: Show package files
|
||||
echo "Python path:" && \
|
||||
python3 -c "import sys; print('\n'.join(sys.path))" && \
|
||||
echo "Source directory contents:" && \
|
||||
ls -R /app/src && \
|
||||
# Install package in editable mode with compatibility mode enabled
|
||||
pip install --use-pep517 -e . --config-settings editable_mode=compat && \
|
||||
echo "Verifying installation..." && \
|
||||
@@ -50,13 +55,15 @@ RUN set -e && \
|
||||
# List all package files
|
||||
echo "Package contents:" && \
|
||||
find /app/src/simpleguardhome -type f -ls && \
|
||||
# Verify import works
|
||||
# Verify package can be imported
|
||||
echo "Testing import..." && \
|
||||
python3 -c "import simpleguardhome; from simpleguardhome.main import app; print(f'Package found at: {simpleguardhome.__file__}')" && \
|
||||
echo "Package installation successful"
|
||||
|
||||
python3 -c "import simpleguardhome; print(f'Package found at: {simpleguardhome.__file__}')" && \
|
||||
# Verify app can be imported
|
||||
echo "Testing app import..." && \
|
||||
python3 -c "from simpleguardhome.main import app; print('App imported successfully')" && \
|
||||
echo "Package installation successful" && \
|
||||
# Create rules backup directory with proper permissions
|
||||
RUN mkdir -p /app/rules_backup && \
|
||||
mkdir -p /app/rules_backup && \
|
||||
chmod 777 /app/rules_backup
|
||||
|
||||
# Default environment variables
|
||||
|
||||
19
MANIFEST.in
19
MANIFEST.in
@@ -1,3 +1,18 @@
|
||||
recursive-include src/simpleguardhome/templates *
|
||||
# Include all package Python files
|
||||
graft src/simpleguardhome
|
||||
|
||||
# Include package data files
|
||||
include src/simpleguardhome/favicon.ico
|
||||
recursive-include src/simpleguardhome *.py
|
||||
include src/simpleguardhome/templates/*.html
|
||||
|
||||
# Include important project files
|
||||
include README.md
|
||||
include LICENSE
|
||||
include requirements.txt
|
||||
include pyproject.toml
|
||||
include setup.py
|
||||
|
||||
# Exclude bytecode files
|
||||
global-exclude *.py[cod]
|
||||
global-exclude __pycache__
|
||||
global-exclude *.so
|
||||
@@ -22,9 +22,21 @@ dependencies = [
|
||||
]
|
||||
|
||||
[tool.setuptools]
|
||||
# Using explicit package configuration
|
||||
package-dir = {"" = "src"}
|
||||
packages = ["simpleguardhome"]
|
||||
include-package-data = true
|
||||
|
||||
# Include all package data
|
||||
[tool.setuptools.package-data]
|
||||
simpleguardhome = ["templates/*", "favicon.ico"]
|
||||
"*" = ["*.ico", "templates/*.html"]
|
||||
|
||||
# Explicitly include the package data
|
||||
[options.package_data]
|
||||
simpleguardhome = [
|
||||
"templates/*",
|
||||
"favicon.ico"
|
||||
]
|
||||
|
||||
# Make sure data files are included
|
||||
[options]
|
||||
include_package_data = true
|
||||
@@ -1,6 +1,7 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
from typing import Optional
|
||||
|
||||
from pydantic_settings import BaseSettings # type: ignore
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application settings using environment variables."""
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
from fastapi import FastAPI, Request, Form, HTTPException, status
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pathlib import Path
|
||||
import httpx
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
from . import adguard
|
||||
from .config import settings
|
||||
from .adguard import (
|
||||
AdGuardError,
|
||||
AdGuardConnectionError,
|
||||
AdGuardAPIError,
|
||||
AdGuardValidationError,
|
||||
FilterStatus,
|
||||
FilterCheckHostResponse,
|
||||
SetRulesRequest
|
||||
|
||||
import httpx # noqa: F401
|
||||
from fastapi import ( # type: ignore # noqa: F401
|
||||
FastAPI,
|
||||
Form,
|
||||
HTTPException,
|
||||
Request,
|
||||
status,
|
||||
)
|
||||
from fastapi.middleware.cors import CORSMiddleware # type: ignore
|
||||
from fastapi.responses import HTMLResponse, JSONResponse # type: ignore
|
||||
from fastapi.staticfiles import StaticFiles # type: ignore
|
||||
from fastapi.templating import Jinja2Templates # type: ignore
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from . import adguard
|
||||
from .adguard import (
|
||||
AdGuardAPIError,
|
||||
AdGuardConnectionError,
|
||||
AdGuardError,
|
||||
AdGuardValidationError,
|
||||
FilterCheckHostResponse,
|
||||
FilterStatus,
|
||||
SetRulesRequest,
|
||||
)
|
||||
from .config import settings # noqa: F401
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -53,13 +61,17 @@ app.mount("/static", StaticFiles(directory=str(Path(__file__).parent)), name="st
|
||||
|
||||
# Mount favicon.ico at root
|
||||
static_files_path = Path(__file__).parent
|
||||
app.mount("/favicon.ico", StaticFiles(directory=str(static_files_path)), name="favicon")
|
||||
app.mount("/favicon.ico",
|
||||
StaticFiles(directory=str(static_files_path)), name="favicon")
|
||||
|
||||
# Response models matching AdGuard spec
|
||||
|
||||
|
||||
class ErrorResponse(BaseModel):
|
||||
"""Error response model according to AdGuard spec."""
|
||||
message: str = Field(..., description="The error message")
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def home(request: Request):
|
||||
"""Render the home page."""
|
||||
@@ -68,6 +80,7 @@ async def home(request: Request):
|
||||
{"request": request}
|
||||
)
|
||||
|
||||
|
||||
@app.get(
|
||||
"/control/filtering/check_host",
|
||||
response_model=FilterCheckHostResponse,
|
||||
@@ -96,11 +109,12 @@ async def check_domain(name: str) -> FilterCheckHostResponse:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e)
|
||||
)
|
||||
) from e
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking domain {name}: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@app.post(
|
||||
"/control/filtering/set_rules",
|
||||
response_model=Dict,
|
||||
@@ -144,11 +158,12 @@ async def add_to_whitelist(request: SetRulesRequest) -> Dict:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=str(e)
|
||||
)
|
||||
) from e
|
||||
except Exception as e:
|
||||
logger.error(f"Error adding domain to whitelist: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@app.get(
|
||||
"/control/filtering/status",
|
||||
response_model=FilterStatus,
|
||||
@@ -167,8 +182,9 @@ async def get_filtering_status() -> FilterStatus:
|
||||
logger.error(f"Error getting filter status: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@app.exception_handler(AdGuardError)
|
||||
async def adguard_exception_handler(request: Request, exc: AdGuardError) -> JSONResponse:
|
||||
async def adguard_exception_handler(_request: Request, exc: AdGuardError) -> JSONResponse:
|
||||
"""Handle AdGuard-related exceptions according to spec."""
|
||||
if isinstance(exc, AdGuardConnectionError):
|
||||
status_code = status.HTTP_503_SERVICE_UNAVAILABLE
|
||||
@@ -184,9 +200,10 @@ async def adguard_exception_handler(request: Request, exc: AdGuardError) -> JSON
|
||||
content={"message": str(exc)}
|
||||
)
|
||||
|
||||
|
||||
def start():
|
||||
"""Start the application using uvicorn."""
|
||||
import uvicorn
|
||||
import uvicorn # type: ignore
|
||||
uvicorn.run(
|
||||
app,
|
||||
host="0.0.0.0",
|
||||
@@ -194,5 +211,6 @@ def start():
|
||||
reload=False # Disable reload in Docker
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start()
|
||||
Reference in New Issue
Block a user