From 9bfbed9b92fd154cbdbc159304b884a0504f9100 Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Tue, 3 Feb 2026 23:02:07 -0500 Subject: [PATCH] add docker config --- .gitignore | 7 ++- docker-compose.dev.yaml | 57 +++++++++++++++++++ docker-compose.prod.yaml | 55 ++++++++++++++++++ docker-compose.yml | 29 ---------- src/Core/.dockerignore | 25 ++++++++ src/Core/API/API.Core/API.Core.csproj | 7 +++ src/Core/API/API.Core/Dockerfile | 26 +++++++++ src/Core/API/API.Core/Program.cs | 24 ++++++++ .../API/API.Core/appsettings.Development.json | 13 ++++- .../API/API.Core/appsettings.Production.json | 19 +++++++ src/Core/API/API.Core/appsettings.json | 19 ++++++- src/Core/API/API.Specs/API.Specs.csproj | 2 + src/Core/Core.slnx | 14 ++--- 13 files changed, 257 insertions(+), 40 deletions(-) create mode 100644 docker-compose.dev.yaml create mode 100644 docker-compose.prod.yaml delete mode 100644 docker-compose.yml create mode 100644 src/Core/.dockerignore create mode 100644 src/Core/API/API.Core/Dockerfile create mode 100644 src/Core/API/API.Core/appsettings.Production.json diff --git a/.gitignore b/.gitignore index ba1194e..b06b40a 100644 --- a/.gitignore +++ b/.gitignore @@ -481,4 +481,9 @@ FodyWeavers.xsd .fake .idea -*.feature.cs \ No newline at end of file +*.feature.cs + + +database + +.env.* \ No newline at end of file diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml new file mode 100644 index 0000000..eeca7f0 --- /dev/null +++ b/docker-compose.dev.yaml @@ -0,0 +1,57 @@ +services: + sqlserver: + image: mcr.microsoft.com/mssql/server:2022-latest + platform: linux/amd64 + container_name: dev-env-sqlserver + environment: + ACCEPT_EULA: "Y" + SA_PASSWORD: "${SA_PASSWORD}" + MSSQL_PID: "Developer" + ports: + - "1433:1433" + volumes: + - sqlserverdata:/var/opt/mssql + healthcheck: + test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '${SA_PASSWORD}' -C -Q 'SELECT 1' || exit 1"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 30s + networks: + - devnet + + api.core: + image: api.core + container_name: dev-env-api-core + depends_on: + sqlserver: + condition: service_healthy + build: + context: ./src/Core + dockerfile: API/API.Core/Dockerfile + args: + BUILD_CONFIGURATION: Release + APP_UID: 1000 + ports: + - "8080:8080" + - "8081:8081" + environment: + ASPNETCORE_ENVIRONMENT: "Development" + ASPNETCORE_URLS: "http://0.0.0.0:8080" + DOTNET_RUNNING_IN_CONTAINER: "true" + DB_CONNECTION_STRING: "${DB_CONNECTION_STRING}" + restart: unless-stopped + networks: + - devnet + volumes: + - nuget-cache:/root/.nuget/packages + +volumes: + sqlserverdata: + driver: local + nuget-cache: + driver: local + +networks: + devnet: + driver: bridge \ No newline at end of file diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml new file mode 100644 index 0000000..b6b9655 --- /dev/null +++ b/docker-compose.prod.yaml @@ -0,0 +1,55 @@ +services: + sqlserver: + image: mcr.microsoft.com/mssql/server:2022-latest + platform: linux/amd64 + container_name: prod-env-sqlserver + environment: + ACCEPT_EULA: "Y" + SA_PASSWORD: "${SA_PASSWORD}" + MSSQL_PID: "Developer" + volumes: + - sqlserverdata:/var/opt/mssql + healthcheck: + test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '${SA_PASSWORD}' -C -Q 'SELECT 1' || exit 1"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 30s + networks: + - prodnet + + api.core: + image: api.core + container_name: prod-env-api-core + depends_on: + sqlserver: + condition: service_healthy + build: + context: ./src/Core + dockerfile: API/API.Core/Dockerfile + args: + BUILD_CONFIGURATION: Release + APP_UID: 1000 + ports: + - "8080:8080" + - "8081:8081" + environment: + ASPNETCORE_ENVIRONMENT: "Production" + ASPNETCORE_URLS: "http://0.0.0.0:8080" + DOTNET_RUNNING_IN_CONTAINER: "true" + DB_CONNECTION_STRING: "${DB_CONNECTION_STRING}" + restart: unless-stopped + networks: + - prodnet + volumes: + - nuget-cache:/root/.nuget/packages + +volumes: + sqlserverdata: + driver: local + nuget-cache: + driver: local + +networks: + prodnet: + driver: bridge \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index e7d8a81..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,29 +0,0 @@ -services: - sqlserver: - image: mcr.microsoft.com/mssql/server:2022-latest - platform: linux/amd64 - container_name: sqlserver - env_file: - - .env - environment: - ACCEPT_EULA: "Y" - SA_PASSWORD: "${SA_PASSWORD}" - ports: - - "1433:1433" - volumes: - - sqlserverdata:/var/opt/mssql - healthcheck: - test: ["CMD", "/opt/mssql-tools/bin/sqlcmd", "-S", "localhost", "-U", "sa", "-P", "${SA_PASSWORD}", "-Q", "SELECT 1" ] - interval: 10s - timeout: 5s - retries: 12 - networks: - - devnet - -volumes: - sqlserverdata: - nuget-cache: - -networks: - devnet: - driver: bridge diff --git a/src/Core/.dockerignore b/src/Core/.dockerignore new file mode 100644 index 0000000..38bece4 --- /dev/null +++ b/src/Core/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Core/API/API.Core/API.Core.csproj b/src/Core/API/API.Core/API.Core.csproj index 1e7ec86..f033c7e 100644 --- a/src/Core/API/API.Core/API.Core.csproj +++ b/src/Core/API/API.Core/API.Core.csproj @@ -4,6 +4,7 @@ enable enable WebAPI + Linux @@ -19,4 +20,10 @@ + + + + .dockerignore + + diff --git a/src/Core/API/API.Core/Dockerfile b/src/Core/API/API.Core/Dockerfile new file mode 100644 index 0000000..7376967 --- /dev/null +++ b/src/Core/API/API.Core/Dockerfile @@ -0,0 +1,26 @@ +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base +ARG APP_UID=1000 +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["API/API.Core/API.Core.csproj", "API/API.Core/"] +COPY ["Repository/Repository.Core/Repository.Core.csproj", "Repository/Repository.Core/"] +COPY ["Service/Service.Core/Service.Core.csproj", "Service/Service.Core/"] +RUN dotnet restore "API/API.Core/API.Core.csproj" +COPY . . +WORKDIR "/src/API/API.Core" +RUN dotnet build "./API.Core.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./API.Core.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "API.Core.dll"] diff --git a/src/Core/API/API.Core/Program.cs b/src/Core/API/API.Core/Program.cs index 48ca639..3a44298 100644 --- a/src/Core/API/API.Core/Program.cs +++ b/src/Core/API/API.Core/Program.cs @@ -10,6 +10,17 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddOpenApi(); +// Add health checks +builder.Services.AddHealthChecks(); + +// Configure logging for container output +builder.Logging.ClearProviders(); +builder.Logging.AddConsole(); +if (!builder.Environment.IsProduction()) +{ + builder.Logging.AddDebug(); +} + // Dependency Injection builder.Services.AddSingleton(); builder.Services.AddScoped(); @@ -17,6 +28,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + var app = builder.Build(); app.UseSwagger(); @@ -24,6 +36,18 @@ app.UseSwaggerUI(); app.MapOpenApi(); app.UseHttpsRedirection(); + +// Health check endpoint (used by Docker health checks and orchestrators) +app.MapHealthChecks("/health"); + app.MapControllers(); app.MapFallbackToController("Handle404", "NotFound"); + +// Graceful shutdown handling +var lifetime = app.Services.GetRequiredService(); +lifetime.ApplicationStopping.Register(() => +{ + app.Logger.LogInformation("Application is shutting down gracefully..."); +}); + app.Run(); \ No newline at end of file diff --git a/src/Core/API/API.Core/appsettings.Development.json b/src/Core/API/API.Core/appsettings.Development.json index ff66ba6..7498bb3 100644 --- a/src/Core/API/API.Core/appsettings.Development.json +++ b/src/Core/API/API.Core/appsettings.Development.json @@ -2,7 +2,18 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Information", + "Microsoft.EntityFrameworkCore": "Information" + }, + "Console": { + "IncludeScopes": true, + "TimestampFormat": "yyyy-MM-ddTHH:mm:ss.fffZ" } + }, + "AllowedHosts": "*", + "Jwt": { + "ExpirationMinutes": 120, + "Issuer": "biergarten-api", + "Audience": "biergarten-users" } } diff --git a/src/Core/API/API.Core/appsettings.Production.json b/src/Core/API/API.Core/appsettings.Production.json new file mode 100644 index 0000000..0e455a9 --- /dev/null +++ b/src/Core/API/API.Core/appsettings.Production.json @@ -0,0 +1,19 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Error" + }, + "Console": { + "IncludeScopes": false, + "TimestampFormat": "yyyy-MM-ddTHH:mm:ss.fffZ" + } + }, + "AllowedHosts": "*", + "Jwt": { + "ExpirationMinutes": 60, + "Issuer": "biergarten-api", + "Audience": "biergarten-users" + } +} diff --git a/src/Core/API/API.Core/appsettings.json b/src/Core/API/API.Core/appsettings.json index 4d56694..0495346 100644 --- a/src/Core/API/API.Core/appsettings.json +++ b/src/Core/API/API.Core/appsettings.json @@ -2,8 +2,23 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Information" + }, + "Console": { + "IncludeScopes": true, + "TimestampFormat": "yyyy-MM-ddTHH:mm:ss.fffZ" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultConnection": "" + }, + "Jwt": { + "SecretKey": "", + "ExpirationMinutes": 60, + "Issuer": "biergarten-api", + "Audience": "biergarten-users" + } } + diff --git a/src/Core/API/API.Specs/API.Specs.csproj b/src/Core/API/API.Specs/API.Specs.csproj index ba032cb..0791bcb 100644 --- a/src/Core/API/API.Specs/API.Specs.csproj +++ b/src/Core/API/API.Specs/API.Specs.csproj @@ -12,6 +12,7 @@ + @@ -33,5 +34,6 @@ + diff --git a/src/Core/Core.slnx b/src/Core/Core.slnx index 9fe412a..7687959 100644 --- a/src/Core/Core.slnx +++ b/src/Core/Core.slnx @@ -1,17 +1,17 @@ - - - + + + - - - + + + - +