diff --git a/CHANGELOG.md b/CHANGELOG.md index fbbf409..1478f7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,13 @@ This project uses famous football stadiums (A-Z) that hosted FIFA World Cup matc ### Changed +- Switch runtime base image from `mcr.microsoft.com/dotnet/aspnet:10.0` (Debian) + to `mcr.microsoft.com/dotnet/aspnet:10.0-alpine` (before: 113.4 MB โ†’ + after: 73.9 MB compressed; measured via `docker manifest inspect` and + `docker save | wc -c`); replace `apt-get` with `apk` and + `useradd`/`groupadd` with `adduser`/`addgroup` accordingly (#456) +- Refactor `scripts/entrypoint.sh`: add `log()` helper with timestamp prefix, + replace raw `echo` calls, and print API base URL on startup (#456) - Rename `ValidateAsync_SquadNumber_BelongsToPlayerBeingUpdated_ReturnsNoErrors` to `ValidateAsync_SquadNumberBelongsToPlayerBeingUpdated_ReturnsNoErrors` to align with the 3-segment naming convention for service/validator tests (#427) - Make CSharpier step in `/pre-commit` conditional (skip with a note if not installed), consistent with the Docker and CodeRabbit steps (#427) - Add "Verify tag commit is reachable from master" step to CD workflow using `git merge-base --is-ancestor` before any build or publish steps (#439) diff --git a/Dockerfile b/Dockerfile index 2ede89c..2560490 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,13 +22,12 @@ RUN dotnet publish -c Release -o /app/publish # Stage 2: Runtime # This stage creates the final, minimal image to run the application. # ------------------------------------------------------------------------------ -FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS runtime WORKDIR /app # Install curl for health check -RUN apt-get update && apt-get install -y --no-install-recommends curl && \ - rm -rf /var/lib/apt/lists/* +RUN apk add --no-cache curl # Metadata labels for the image. These are useful for registries and inspection. LABEL org.opencontainers.image.title="๐Ÿงช Web API made with .NET 10 (LTS) and ASP.NET Core" @@ -39,6 +38,9 @@ LABEL org.opencontainers.image.source="https://github.com/nanotaboada/Dotnet.Sam # Set environment variables ENV ASPNETCORE_URLS=http://+:9000 ENV ASPNETCORE_ENVIRONMENT=Production +# Alpine images default to invariant globalization mode. Explicitly opt in since +# this API uses ISO-8601 dates and ASCII data โ€” ICU is not required. +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true # Copy published app from builder COPY --from=builder /app/publish/ . @@ -57,7 +59,8 @@ COPY --chmod=555 scripts/healthcheck.sh ./healthcheck.sh COPY --from=builder /src/Dotnet.Samples.AspNetCore.WebApi/storage/players-sqlite3.db ./hold/players-sqlite3.db # Add non-root user and make volume mount point writable -RUN groupadd -r aspnetcore && useradd -r -g aspnetcore aspnetcore && \ +RUN addgroup -S aspnetcore && \ + adduser -S -G aspnetcore aspnetcore && \ mkdir -p /storage && \ chown aspnetcore:aspnetcore /storage diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 2642076..a1158cf 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -1,25 +1,37 @@ #!/bin/sh set -e +# Helper function for formatted logging +log() { + local message="$1" + echo "[ENTRYPOINT] $(date '+%Y/%m/%d - %H:%M:%S') | $message" + return 0 +} + IMAGE_STORAGE_PATH="/app/hold/players-sqlite3.db" VOLUME_STORAGE_PATH="/storage/players-sqlite3.db" -echo "โœ” Starting container..." +log "โœ” Starting container..." if [ ! -f "$VOLUME_STORAGE_PATH" ]; then - echo "โš ๏ธ No existing database file found in volume." + log "โš ๏ธ No existing database file found in volume." if [ -f "$IMAGE_STORAGE_PATH" ]; then - echo "๐Ÿ”„ Copying database file to writable volume..." + log "๐Ÿ”„ Copying database file to writable volume..." cp "$IMAGE_STORAGE_PATH" "$VOLUME_STORAGE_PATH" - echo "โœ” Database initialized at $VOLUME_STORAGE_PATH" + log "โœ” Database initialized at $VOLUME_STORAGE_PATH" else - echo "โš ๏ธ Database file missing at $IMAGE_STORAGE_PATH" + log "โš ๏ธ Database file missing at $IMAGE_STORAGE_PATH" exit 1 fi else - echo "โœ” Existing database file found. Skipping seed copy." + log "โœ” Existing database file found. Skipping seed copy." fi -echo "โœ” Ready!" -echo "๐Ÿš€ Launching app..." +log "โœ” Ready!" +log "๐Ÿš€ Launching app..." +# Derive the API URL from ASPNETCORE_URLS (first entry if semicolon-separated), +# replacing the wildcard host (+, 0.0.0.0) with localhost for display purposes. +_raw_url=$(printf '%s' "${ASPNETCORE_URLS:-http://+:9000}" | cut -d';' -f1) +API_URL=$(printf '%s' "$_raw_url" | sed 's|+|localhost|g; s|0\.0\.0\.0|localhost|g') +log "๐Ÿ”Œ API endpoints | $API_URL" exec "$@"