Simplified mounting volumes

[backend] simplified mounting volumes with volume config where it goes everything except logs
This commit is contained in:
João Vitória Silva
2025-06-17 09:25:27 +01:00
parent b57aed012f
commit cc23016823
18 changed files with 42 additions and 46 deletions

29
.gitignore vendored
View File

@@ -9,6 +9,7 @@ aux_scripts/.garminconnect
backend/app/__pycache__/
backend/app/*/__pycache__/
backend/app/*/*/__pycache__/
backend/app/*/*/*/__pycache__/
backend/app/*.pyc
# Logs
@@ -17,24 +18,24 @@ backend/app/*.log
backend/logs/*.log
# server image folder images
backend/app/server_images/*.jpeg
backend/app/server_images/*.png
backend/app/server_images/*.jpg
backend/app/config/server_images/*.jpeg
backend/app/config/server_images/*.png
backend/app/config/server_images/*.jpg
# user image folder images
backend/app/user_images/*.jpeg
backend/app/user_images/*.png
backend/app/user_images/*.jpg
backend/app/config/user_images/*.jpeg
backend/app/config/user_images/*.png
backend/app/config/user_images/*.jpg
# gpx and fit files
backend/app/files/*.gpx
backend/app/files/*.zip
backend/app/files/*.fit
backend/app/files/bulk_import/*.gpx
backend/app/files/bulk_import/*.fit
backend/app/files/processed/*.gpx
backend/app/files/processed/*.fit
backend/files/
backend/app/config/files/*.gpx
backend/app/config/files/*.zip
backend/app/config/files/*.fit
backend/app/config/files/bulk_import/*.gpx
backend/app/config/files/bulk_import/*.fit
backend/app/config/files/processed/*.gpx
backend/app/config/files/processed/*.fit
backend/config/files/
# Frontend
frontend/app/img/users_img/*.*

View File

@@ -563,7 +563,7 @@ async def create_activity_with_bulk_import(
):
try:
# Ensure the 'bulk_import' directory exists
bulk_import_dir = "files/bulk_import"
bulk_import_dir = "config/files/bulk_import"
os.makedirs(bulk_import_dir, exist_ok=True)
# Iterate over each file in the 'bulk_import' directory
@@ -682,7 +682,7 @@ async def delete_activity(
activities_crud.delete_activity(activity_id, db)
# Define the search pattern using the file ID (e.g., '1.*')
pattern = f"files/processed/{activity_id}.*"
pattern = f"config/files/processed/{activity_id}.*"
# Use glob to find files that match the pattern
files_to_delete = glob.glob(pattern)

View File

@@ -343,7 +343,7 @@ def parse_and_store_activity_from_file(
f"File extension not supported: {file_extension}", "error"
)
# Define the directory where the processed files will be stored
processed_dir = "files/processed"
processed_dir = "config/files/processed"
# Define new file path with activity ID as filename
new_file_name = f"{idsToFileName}{file_extension}"
@@ -373,7 +373,7 @@ def parse_and_store_activity_from_uploaded_file(
try:
# Ensure the 'files' directory exists
upload_dir = "files"
upload_dir = "config/files"
os.makedirs(upload_dir, exist_ok=True)
# Build the full path where the file will be saved
@@ -447,7 +447,7 @@ def parse_and_store_activity_from_uploaded_file(
)
# Define the directory where the processed files will be stored
processed_dir = "files/processed"
processed_dir = "config/files/processed"
# Define new file path with activity ID as filename
new_file_name = f"{idsToFileName}{file_extension}"

View File

@@ -7,14 +7,14 @@ def return_frontend_index(path: str):
def return_user_img_path(user_img: str):
file_path = "/app/backend/user_images/" + user_img
file_path = "/app/backend/config/user_images/" + user_img
if not os.path.isfile(file_path):
return None
return FileResponse(file_path)
def return_server_img_path(server_img: str):
file_path = "/app/backend/server_images/" + server_img
file_path = "/app/backend/config/server_images/" + server_img
if not os.path.isfile(file_path):
return None
return FileResponse(file_path)

View File

@@ -75,7 +75,7 @@ def fetch_and_process_activities_by_dates(
activity_id, dl_fmt=garminconnect_client.ActivityDownloadFormat.ORIGINAL
)
# Save the zip file
output_file = f"files/{str(activity_id)}.zip"
output_file = f"config/files/{str(activity_id)}.zip"
# Write the ZIP data to the output file
with open(output_file, "wb") as fb:
@@ -87,7 +87,7 @@ def fetch_and_process_activities_by_dates(
# Open the ZIP file
with zipfile.ZipFile(output_file, "r") as zip_ref:
# Extract all contents to the specified directory
zip_ref.extractall("files")
zip_ref.extractall("config/files")
# Populate the array with file names
extracted_files = zip_ref.namelist()
@@ -100,7 +100,7 @@ def fetch_and_process_activities_by_dates(
for file_path_suffix in extracted_files:
# Parse and store the activity from the extracted file
full_file_path = os.path.join("files", file_path_suffix)
full_file_path = os.path.join("config/files", file_path_suffix)
parsed_activities.extend(
activities_utils.parse_and_store_activity_from_file(

View File

@@ -109,9 +109,9 @@ def create_app() -> FastAPI:
app.include_router(api_router)
# Add a route to serve the user images
app.mount("/user_images", StaticFiles(directory="user_images"), name="user_images")
app.mount("/config/user_images", StaticFiles(directory="config/user_images"), name="user_images")
app.mount(
"/server_images", StaticFiles(directory="server_images"), name="server_images"
"/config/server_images", StaticFiles(directory="config/server_images"), name="server_images"
)
app.mount(
"/", StaticFiles(directory=core_config.FRONTEND_DIR, html=True), name="frontend"

View File

@@ -58,7 +58,7 @@ def process_migration_3(db: Session):
# check if activity file exists
activity_fit_file_path = find_activity_fit_file(activity.id)
activity_gpx_file_path = os.path.join(
"files/processed", f"{activity.id}.gpx"
"config/files/processed", f"{activity.id}.gpx"
)
if (
@@ -128,7 +128,7 @@ def process_migration_3(db: Session):
def find_activity_fit_file(activity_id):
processed_dir = "files/processed"
processed_dir = "config/files/processed"
# Try single activity file first
single_path = os.path.join(processed_dir, f"{activity_id}.fit")
@@ -167,7 +167,7 @@ def get_fit_file_from_garminconnect(activity: activities_schema.Activity, db: Se
)
# Save the zip file
output_file = f"files/{str(activity.garminconnect_activity_id)}.zip"
output_file = f"config/files/{str(activity.garminconnect_activity_id)}.zip"
# Write the ZIP data to the output file
with open(output_file, "wb") as fb:
@@ -179,7 +179,7 @@ def get_fit_file_from_garminconnect(activity: activities_schema.Activity, db: Se
# Open the ZIP file
with zipfile.ZipFile(output_file, "r") as zip_ref:
# Extract all contents to the specified directory
zip_ref.extractall("files")
zip_ref.extractall("config/files")
# Populate the array with file names
extracted_files = zip_ref.namelist()
@@ -195,16 +195,16 @@ def get_fit_file_from_garminconnect(activity: activities_schema.Activity, db: Se
try:
# Define the directory where the processed files will be stored
processed_dir = "files/processed"
processed_dir = "config/files/processed"
for file in extracted_files:
_, file_extension = os.path.splitext(f"files/{file}")
_, file_extension = os.path.splitext(f"config/files/{file}")
# Define new file path with activity ID as filename
new_file_name = f"{activity.id}{file_extension}"
# Move the file to the processed directory
activities_utils.move_file(processed_dir, new_file_name, f"files/{file}")
activities_utils.move_file(processed_dir, new_file_name, f"config/files/{file}")
except Exception as err:
core_logger.print_to_log(
f"Migration 3 - Failed to move activity {activity.id} file: {err}",
@@ -213,7 +213,7 @@ def get_fit_file_from_garminconnect(activity: activities_schema.Activity, db: Se
)
# check if activity file exists
return os.path.join("files/processed", f"{activity.id}.fit")
return os.path.join("config/files/processed", f"{activity.id}.fit")
def process_fit_file(

View File

@@ -62,7 +62,7 @@ async def upload_login_photo(
):
try:
# Ensure the 'server_images' directory exists
upload_dir = "server_images"
upload_dir = "config/server_images"
os.makedirs(upload_dir, exist_ok=True)
# Build the full path with the name "login.png"
@@ -93,7 +93,7 @@ async def delete_login_photo(
):
try:
# Build the full path to the file
file_path = os.path.join("server_images", "login.png")
file_path = os.path.join("config/server_images", "login.png")
# Check if the file exists
if os.path.exists(file_path):

View File

@@ -25,7 +25,7 @@ def check_user_is_active(user: users_schema.User) -> None:
def delete_user_photo_filesystem(user_id: int):
# Define the pattern to match files with the specified name regardless of the extension
folder = "user_images"
folder = "config/user_images"
file = f"{user_id}.*"
# Find all files matching the pattern
@@ -44,7 +44,7 @@ def format_user_birthdate(user):
async def save_user_image(user_id: int, file: UploadFile, db: Session):
try:
upload_dir = "user_images"
upload_dir = "config/user_images"
os.makedirs(upload_dir, exist_ok=True)
# Get file extension

View File

@@ -12,10 +12,8 @@ services:
- ENDURAIN_HOST=http://localhost:8080 # host or local ip (example: http://192.168.1.10:8080 or https://endurain.com), default is http://localhost:8080
volumes:
# - <local_path>/endurain/backend/app:/app/backend # Configure volume if you want to edit the code locally by cloning the repo
- <local_path>/endurain/backend/user_images:/app/backend/user_images # necessary for user image persistence on container image updates
- <local_path>/endurain/backend/files/bulk_import:/app/backend/files/bulk_import # necessary to enable bulk import of activities. Place here your activities files
- <local_path>/endurain/backend/files/processed:/app/backend/files/processed # necessary for processed original files persistence on container image updates
- <local_path>/endurain/backend/logs:/app/backend/logs # log files for the backend
- <local_path>/endurain/backend/config:/app/backend/config # necessary for image and activity files persistence on docker image update
ports:
- "8080:8080" # Endurain port, change per your needs
depends_on:

View File

@@ -34,7 +34,7 @@ validate_id "$GID"
echo_info_log "UID=$UID, GID=$GID"
# List of directories (space-separated for POSIX shell)
directories="/app/backend/logs /app/backend/user_images /app/backend/files /app/backend/server_images"
directories="/app/backend/logs /app/backend/config"
for dir in $directories; do
adjust_folder_ownership "$dir"

View File

@@ -74,11 +74,8 @@ Docker image uses a non-root user, so ensure target folders are not owned by roo
| Volume | Notes |
| --- | --- |
| `<local_path>/endurain/backend/files/bulk_import:/app/backend/files/bulk_import` | Necessary to enable bulk import of activities. Place here your activities files |
| `<local_path>/endurain/backend/files/processed:/app/backend/files/processed` | Necessary for processed original files persistence on container image updates |
| `<local_path>/endurain/backend/user_images:/app/backend/user_images` | Necessary for user image persistence on container image updates |
| `<local_path>/endurain/backend/server_images:/app/backend/server_images` | Necessary for server image persistence on container image updates |
| `<local_path>/endurain/backend/logs:/app/backend/logs` | Log files for the backend |
| `<local_path>/endurain/backend/config:/app/backend/config` | Necessary for image and activity files persistence on docker image update |
## Bulk import and file upload