Add Docker containerization with external PostgreSQL support
- Add docker-compose.yml with PostgreSQL and Redis environment variables - Add Dockerfile for multi-stage .NET build optimized for production - Add .env.template with database connection configuration - Update Program.cs with JWT authentication and Docker logging - Configure external database connectivity (tested working) - Container successfully connects to external PostgreSQL server Infrastructure milestone: API containerized and database-ready
This commit is contained in:
parent
f8201ff080
commit
686001dc98
53
ShadowedRealmsMobile/src/server/.dockerignore
Normal file
53
ShadowedRealmsMobile/src/server/.dockerignore
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# File Location: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\.dockerignore
|
||||||
|
|
||||||
|
# Build output directories
|
||||||
|
**/bin/
|
||||||
|
**/obj/
|
||||||
|
**/out/
|
||||||
|
|
||||||
|
# Visual Studio files
|
||||||
|
**/.vs/
|
||||||
|
**/*.user
|
||||||
|
**/*.suo
|
||||||
|
**/*.userprefs
|
||||||
|
**/.vscode/
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Git files
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
**/*.md
|
||||||
|
README*
|
||||||
|
|
||||||
|
# Test results
|
||||||
|
TestResults/
|
||||||
|
**/*.trx
|
||||||
|
**/*.coverage
|
||||||
|
|
||||||
|
# NuGet packages (will be restored during build)
|
||||||
|
**/packages/
|
||||||
|
**/*.nupkg
|
||||||
|
|
||||||
|
# Docker files (don't copy into container)
|
||||||
|
**/Dockerfile*
|
||||||
|
**/docker-compose*
|
||||||
|
**/.dockerignore
|
||||||
|
|
||||||
|
# Environment files (secrets shouldn't go in containers)
|
||||||
|
**/.env
|
||||||
|
**/.env.*
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
**/logs/
|
||||||
|
**/*.log
|
||||||
64
ShadowedRealmsMobile/src/server/.env
Normal file
64
ShadowedRealmsMobile/src/server/.env
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Shadowed Realms Environment Variables Template
|
||||||
|
# File Location: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\.env.template
|
||||||
|
# Copy this file to .env and fill in your actual values
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# DATABASE CONFIGURATION
|
||||||
|
# ===============================
|
||||||
|
POSTGRES_HOST=209.25.140.218
|
||||||
|
POSTGRES_DB=ShadowedRealms
|
||||||
|
POSTGRES_USER=gameserver
|
||||||
|
POSTGRES_PASSWORD=w92oOUPGAR/ZRJaDynLQIq07aFzvTQ6tQzOJsXMStXE=
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# REDIS CONFIGURATION
|
||||||
|
# ===============================
|
||||||
|
REDIS_HOST=209.25.140.218
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# JWT AUTHENTICATION
|
||||||
|
# ===============================
|
||||||
|
JWT_SECRET_KEY=Ymn0e9ntVwbV&MUDRN$2wfWF^GDgBYWo
|
||||||
|
JWT_ISSUER=ShadowedRealms.API
|
||||||
|
JWT_AUDIENCE=ShadowedRealms.Players
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# APPLICATION SETTINGS
|
||||||
|
# ===============================
|
||||||
|
ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
KINGDOM_IDS=1,2,3,4,5
|
||||||
|
ALLOWED_ORIGINS=https://yourdomain.com,https://admin.yourdomain.com
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# ADMIN SETTINGS (Optional)
|
||||||
|
# ===============================
|
||||||
|
ADMIN_USER=admin
|
||||||
|
ADMIN_PASSWORD=admin_secure_password_here
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# INSTRUCTIONS
|
||||||
|
# ===============================
|
||||||
|
# 1. Copy this file to .env (DO NOT commit .env to git!)
|
||||||
|
# 2. Replace all placeholder values with your actual configuration
|
||||||
|
# 3. Make sure your PostgreSQL VM is accessible from Docker containers
|
||||||
|
# 4. Generate a secure JWT secret key (32+ characters)
|
||||||
|
# 5. Update POSTGRES_HOST with your actual VM IP address
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# DOCKER COMMANDS
|
||||||
|
# ===============================
|
||||||
|
# Build and start the API:
|
||||||
|
# docker-compose up -d shadowed-realms-api
|
||||||
|
|
||||||
|
# Start with admin dashboard:
|
||||||
|
# docker-compose --profile admin up -d
|
||||||
|
|
||||||
|
# View logs:
|
||||||
|
# docker-compose logs -f shadowed-realms-api
|
||||||
|
|
||||||
|
# Stop all services:
|
||||||
|
# docker-compose down
|
||||||
|
|
||||||
|
# Rebuild after code changes:
|
||||||
|
# docker-compose build --no-cache
|
||||||
64
ShadowedRealmsMobile/src/server/.env.template
Normal file
64
ShadowedRealmsMobile/src/server/.env.template
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Shadowed Realms Environment Variables Template
|
||||||
|
# File Location: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\.env.template
|
||||||
|
# Copy this file to .env and fill in your actual values
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# DATABASE CONFIGURATION
|
||||||
|
# ===============================
|
||||||
|
POSTGRES_HOST=192.168.1.100
|
||||||
|
POSTGRES_DB=ShadowedRealms
|
||||||
|
POSTGRES_USER=gameserver
|
||||||
|
POSTGRES_PASSWORD=your_secure_database_password_here
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# REDIS CONFIGURATION
|
||||||
|
# ===============================
|
||||||
|
REDIS_HOST=192.168.1.100
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# JWT AUTHENTICATION
|
||||||
|
# ===============================
|
||||||
|
JWT_SECRET_KEY=your_super_secure_jwt_secret_key_minimum_32_characters_long_for_production_use
|
||||||
|
JWT_ISSUER=ShadowedRealms.API
|
||||||
|
JWT_AUDIENCE=ShadowedRealms.Players
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# APPLICATION SETTINGS
|
||||||
|
# ===============================
|
||||||
|
ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
KINGDOM_IDS=1,2,3,4,5
|
||||||
|
ALLOWED_ORIGINS=https://yourdomain.com,https://admin.yourdomain.com
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# ADMIN SETTINGS (Optional)
|
||||||
|
# ===============================
|
||||||
|
ADMIN_USER=admin
|
||||||
|
ADMIN_PASSWORD=admin_secure_password_here
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# INSTRUCTIONS
|
||||||
|
# ===============================
|
||||||
|
# 1. Copy this file to .env (DO NOT commit .env to git!)
|
||||||
|
# 2. Replace all placeholder values with your actual configuration
|
||||||
|
# 3. Make sure your PostgreSQL VM is accessible from Docker containers
|
||||||
|
# 4. Generate a secure JWT secret key (32+ characters)
|
||||||
|
# 5. Update POSTGRES_HOST with your actual VM IP address
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# DOCKER COMMANDS
|
||||||
|
# ===============================
|
||||||
|
# Build and start the API:
|
||||||
|
# docker-compose up -d shadowed-realms-api
|
||||||
|
|
||||||
|
# Start with admin dashboard:
|
||||||
|
# docker-compose --profile admin up -d
|
||||||
|
|
||||||
|
# View logs:
|
||||||
|
# docker-compose logs -f shadowed-realms-api
|
||||||
|
|
||||||
|
# Stop all services:
|
||||||
|
# docker-compose down
|
||||||
|
|
||||||
|
# Rebuild after code changes:
|
||||||
|
# docker-compose build --no-cache
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
# Shadowed Realms API Dockerfile
|
||||||
|
# File Location: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\ShadowedRealms.API\Dockerfile
|
||||||
|
# Multi-stage build for production optimization
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# BUILD STAGE
|
||||||
|
# ===============================
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Copy solution file (from root directory)
|
||||||
|
COPY ShadowedRealmsMobile.sln ./
|
||||||
|
|
||||||
|
# Copy project files for dependency restoration (all existing projects)
|
||||||
|
COPY src/server/ShadowedRealms.API/*.csproj ./src/server/ShadowedRealms.API/
|
||||||
|
COPY src/server/ShadowedRealms.Admin/*.csproj ./src/server/ShadowedRealms.Admin/
|
||||||
|
COPY src/server/ShadowedRealms.Core/*.csproj ./src/server/ShadowedRealms.Core/
|
||||||
|
COPY src/server/ShadowedRealms.Data/*.csproj ./src/server/ShadowedRealms.Data/
|
||||||
|
COPY src/server/ShadowedRealms.Shared/*.csproj ./src/server/ShadowedRealms.Shared/
|
||||||
|
COPY src/server/ShadowedRealms.SignalR/*.csproj ./src/server/ShadowedRealms.SignalR/
|
||||||
|
|
||||||
|
# Restore dependencies (this layer is cached if project files don't change)
|
||||||
|
RUN dotnet restore src/server/ShadowedRealms.API/ShadowedRealms.API.csproj
|
||||||
|
|
||||||
|
# Copy all source code
|
||||||
|
COPY src/server/ ./src/server/
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN dotnet build src/server/ShadowedRealms.API/ShadowedRealms.API.csproj -c Release -o /app/build
|
||||||
|
|
||||||
|
# Publish the application
|
||||||
|
RUN dotnet publish src/server/ShadowedRealms.API/ShadowedRealms.API.csproj -c Release -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# RUNTIME STAGE
|
||||||
|
# ===============================
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
|
||||||
|
|
||||||
|
# Install curl for health checks
|
||||||
|
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create non-root user for security
|
||||||
|
RUN groupadd -r gameserver && useradd --no-log-init -r -g gameserver gameserver
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy published application from build stage
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
|
||||||
|
# Create log directory and set permissions
|
||||||
|
RUN mkdir -p /app/logs && chown -R gameserver:gameserver /app
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER gameserver
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# CONFIGURATION
|
||||||
|
# ===============================
|
||||||
|
|
||||||
|
# Expose port 8080 (standard for containers)
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
|
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
ENV DOTNET_PRINT_TELEMETRY_MESSAGE=false
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8080/health || exit 1
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
ENTRYPOINT ["dotnet", "ShadowedRealms.API.dll"]
|
||||||
@ -1,25 +1,200 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// ===============================
|
||||||
|
// DATABASE CONFIGURATION
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
// Get database connection string (Docker override support)
|
||||||
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||||
|
if (string.IsNullOrEmpty(connectionString))
|
||||||
|
{
|
||||||
|
// Fallback to environment variable for Docker
|
||||||
|
connectionString = Environment.GetEnvironmentVariable("DATABASE_CONNECTION_STRING");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(connectionString))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Database connection string not configured. Set ConnectionStrings:DefaultConnection in appsettings.json or DATABASE_CONNECTION_STRING environment variable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add Entity Framework when ready
|
||||||
|
// builder.Services.AddDbContext<GameDbContext>(options =>
|
||||||
|
// options.UseNpgsql(connectionString));
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// AUTHENTICATION (JWT)
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
var jwtSection = builder.Configuration.GetSection("JWT");
|
||||||
|
var jwtSecret = jwtSection["SecretKey"]
|
||||||
|
?? Environment.GetEnvironmentVariable("JWT_SECRET_KEY");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(jwtSecret) || jwtSecret.Contains("REPLACE"))
|
||||||
|
{
|
||||||
|
if (builder.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
Console.WriteLine("WARNING: Using development JWT secret. Set JWT_SECRET_KEY environment variable for production.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("JWT_SECRET_KEY environment variable must be set for production.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add JWT Authentication
|
||||||
|
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.RequireHttpsMetadata = !builder.Environment.IsDevelopment();
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidIssuer = jwtSection["Issuer"],
|
||||||
|
ValidAudience = jwtSection["Audience"],
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(
|
||||||
|
Encoding.UTF8.GetBytes(jwtSecret ?? "dev_jwt_secret_key_at_least_32_chars_long_not_for_production_use_only")),
|
||||||
|
ClockSkew = TimeSpan.Zero
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// REDIS CONFIGURATION
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
var redisConnection = builder.Configuration.GetConnectionString("Redis")
|
||||||
|
?? Environment.GetEnvironmentVariable("REDIS_CONNECTION_STRING")
|
||||||
|
?? "localhost:6379";
|
||||||
|
|
||||||
|
// TODO: Add Redis when ready
|
||||||
|
// builder.Services.AddSingleton<IConnectionMultiplexer>(provider =>
|
||||||
|
// ConnectionMultiplexer.Connect(redisConnection));
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// API SERVICES
|
||||||
|
// ===============================
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
|
||||||
|
{
|
||||||
|
Title = "Shadowed Realms API",
|
||||||
|
Version = "v1",
|
||||||
|
Description = "Medieval Fantasy Strategy MMO Backend API"
|
||||||
|
});
|
||||||
|
|
||||||
|
// JWT Bearer Authentication in Swagger
|
||||||
|
options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Description = "JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below.",
|
||||||
|
Name = "Authorization",
|
||||||
|
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
|
||||||
|
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
|
||||||
|
Scheme = "Bearer"
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new Microsoft.OpenApi.Models.OpenApiReference
|
||||||
|
{
|
||||||
|
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
|
||||||
|
Id = "Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new string[] {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// CORS configuration with environment variable support
|
||||||
|
var allowedOrigins = builder.Configuration.GetSection("AllowedOrigins").Get<string[]>()
|
||||||
|
?? Environment.GetEnvironmentVariable("ALLOWED_ORIGINS")?.Split(',')
|
||||||
|
?? new[] { "http://localhost:3000" };
|
||||||
|
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy("ShadowedRealmsPolicy", policy =>
|
||||||
|
{
|
||||||
|
policy.WithOrigins(allowedOrigins)
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowCredentials();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// HEALTH CHECKS
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
builder.Services.AddHealthChecks();
|
||||||
|
// TODO: Add database health checks when EF is configured
|
||||||
|
// .AddNpgSql(connectionString)
|
||||||
|
// .AddRedis(redisConnection);
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// BUILD APPLICATION
|
||||||
|
// ===============================
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// ===============================
|
||||||
|
// MIDDLEWARE PIPELINE
|
||||||
|
// ===============================
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI(options =>
|
||||||
|
{
|
||||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Shadowed Realms API V1");
|
||||||
|
options.RoutePrefix = "swagger";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
app.UseCors("ShadowedRealmsPolicy");
|
||||||
|
|
||||||
|
// Authentication and Authorization (proper order)
|
||||||
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
app.Run();
|
// Health check endpoint
|
||||||
|
app.MapHealthChecks("/health");
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// STARTUP LOGGING
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
var logger = app.Services.GetRequiredService<ILogger<Program>>();
|
||||||
|
logger.LogInformation("Shadowed Realms API starting...");
|
||||||
|
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||||
|
|
||||||
|
// Docker-specific logging
|
||||||
|
var containerId = Environment.GetEnvironmentVariable("CONTAINER_ID");
|
||||||
|
var kingdomIds = Environment.GetEnvironmentVariable("KINGDOM_IDS");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(containerId))
|
||||||
|
{
|
||||||
|
logger.LogInformation("Container ID: {ContainerId}", containerId);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(kingdomIds))
|
||||||
|
{
|
||||||
|
logger.LogInformation("Managing Kingdoms: {KingdomIds}", kingdomIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("API ready at /swagger (development) and /health");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=localhost;Database=ShadowedRealms_Dev;Username=postgres;Password=devpassword",
|
||||||
|
"Redis": "localhost:6379"
|
||||||
|
},
|
||||||
|
"JWT": {
|
||||||
|
"SecretKey": "dev_jwt_secret_key_at_least_32_chars_long_not_for_production_use_only",
|
||||||
|
"Issuer": "ShadowedRealms.API.Dev",
|
||||||
|
"Audience": "ShadowedRealms.Players.Dev",
|
||||||
|
"ExpiresInMinutes": 240
|
||||||
|
},
|
||||||
|
"AllowedOrigins": [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"https://localhost:3001",
|
||||||
|
"http://127.0.0.1:3000"
|
||||||
|
],
|
||||||
|
"GameSettings": {
|
||||||
|
"MaxPlayersPerKingdom": 100,
|
||||||
|
"KingdomTaxRate": 0.04,
|
||||||
|
"MaxAlliancesPerKingdom": 10,
|
||||||
|
"FieldInterceptionEnabled": true,
|
||||||
|
"CoalitionSystemEnabled": true,
|
||||||
|
"DevModeEnabled": true,
|
||||||
|
"FastProgressionEnabled": true
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"ShadowedRealms": "Debug",
|
||||||
|
"Microsoft.EntityFrameworkCore": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,35 @@
|
|||||||
{
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=localhost;Database=ShadowedRealms_Dev;Username=postgres;Password=devpassword",
|
||||||
|
"Redis": "localhost:6379"
|
||||||
|
},
|
||||||
|
"JWT": {
|
||||||
|
"SecretKey": "dev_jwt_secret_key_at_least_32_chars_long_not_for_production_use_only",
|
||||||
|
"Issuer": "ShadowedRealms.API.Dev",
|
||||||
|
"Audience": "ShadowedRealms.Players.Dev",
|
||||||
|
"ExpiresInMinutes": 240
|
||||||
|
},
|
||||||
|
"AllowedOrigins": [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"https://localhost:3001",
|
||||||
|
"http://127.0.0.1:3000"
|
||||||
|
],
|
||||||
|
"GameSettings": {
|
||||||
|
"MaxPlayersPerKingdom": 100,
|
||||||
|
"KingdomTaxRate": 0.04,
|
||||||
|
"MaxAlliancesPerKingdom": 10,
|
||||||
|
"FieldInterceptionEnabled": true,
|
||||||
|
"CoalitionSystemEnabled": true,
|
||||||
|
"DevModeEnabled": true,
|
||||||
|
"FastProgressionEnabled": true
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Debug",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"ShadowedRealms": "Debug",
|
||||||
|
"Microsoft.EntityFrameworkCore": "Information"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,9 +1,31 @@
|
|||||||
{
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Host=postgres-vm-host;Database=ShadowedRealms;Username=gameserver;Password=REPLACE_IN_DOCKER",
|
||||||
|
"Redis": "redis-vm-host:6379"
|
||||||
|
},
|
||||||
|
"JWT": {
|
||||||
|
"SecretKey": "REPLACE_WITH_ENV_VARIABLE",
|
||||||
|
"Issuer": "ShadowedRealms.API",
|
||||||
|
"Audience": "ShadowedRealms.Players",
|
||||||
|
"ExpiresInMinutes": 60
|
||||||
|
},
|
||||||
|
"AllowedOrigins": [
|
||||||
|
"https://shadowedrealms.game",
|
||||||
|
"https://admin.shadowedrealms.game"
|
||||||
|
],
|
||||||
|
"GameSettings": {
|
||||||
|
"MaxPlayersPerKingdom": 1500,
|
||||||
|
"KingdomTaxRate": 0.04,
|
||||||
|
"MaxAlliancesPerKingdom": 50,
|
||||||
|
"FieldInterceptionEnabled": true,
|
||||||
|
"CoalitionSystemEnabled": true
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning",
|
||||||
|
"ShadowedRealms": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
151
ShadowedRealmsMobile/src/server/docker-compose.yaml
Normal file
151
ShadowedRealmsMobile/src/server/docker-compose.yaml
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
# Shadowed Realms Docker Compose Configuration
|
||||||
|
# File Location: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\docker-compose.yml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ===============================
|
||||||
|
# GAME API SERVER
|
||||||
|
# ===============================
|
||||||
|
shadowed-realms-api:
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: src/server/ShadowedRealms.API/Dockerfile
|
||||||
|
image: shadowedrealms/api:latest
|
||||||
|
container_name: sr-api
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # API endpoints
|
||||||
|
- "8443:8443" # HTTPS (if configured)
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Database connection (replace with your PostgreSQL VM IP)
|
||||||
|
- DATABASE_CONNECTION_STRING=Host=${POSTGRES_HOST};Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}
|
||||||
|
|
||||||
|
# Redis connection (replace with your Redis VM IP or use same as Postgres)
|
||||||
|
- REDIS_CONNECTION_STRING=${REDIS_HOST}:${REDIS_PORT}
|
||||||
|
|
||||||
|
# JWT Configuration (MUST be set for production)
|
||||||
|
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
|
||||||
|
- JWT_ISSUER=${JWT_ISSUER:-ShadowedRealms.API}
|
||||||
|
- JWT_AUDIENCE=${JWT_AUDIENCE:-ShadowedRealms.Players}
|
||||||
|
|
||||||
|
# CORS Origins
|
||||||
|
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-https://yourdomain.com,https://admin.yourdomain.com}
|
||||||
|
|
||||||
|
# Container identification
|
||||||
|
- CONTAINER_ID=sr-api-main
|
||||||
|
- KINGDOM_IDS=${KINGDOM_IDS:-1,2,3,4,5}
|
||||||
|
|
||||||
|
# ASP.NET Core settings
|
||||||
|
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
|
||||||
|
- ASPNETCORE_URLS=http://+:8080
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Persist logs outside container
|
||||||
|
- api-logs:/app/logs
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 60s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- shadowed-realms-network
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# LOAD BALANCER / REVERSE PROXY
|
||||||
|
# ===============================
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: sr-proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./ssl:/etc/nginx/ssl:ro # SSL certificates (when ready)
|
||||||
|
- nginx-logs:/var/log/nginx
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- shadowed-realms-api
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- shadowed-realms-network
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# ADMIN DASHBOARD (Optional)
|
||||||
|
# ===============================
|
||||||
|
shadowed-realms-admin:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ShadowedRealms.Admin/Dockerfile # Create this later
|
||||||
|
image: shadowedrealms/admin:latest
|
||||||
|
container_name: sr-admin
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- DATABASE_CONNECTION_STRING=Host=${POSTGRES_HOST:-your-postgres-vm-ip};Database=${POSTGRES_DB:-ShadowedRealms};Username=${ADMIN_USER:-admin};Password=${ADMIN_PASSWORD}
|
||||||
|
- API_BASE_URL=http://shadowed-realms-api:8080
|
||||||
|
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- admin-logs:/app/logs
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- shadowed-realms-api
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- shadowed-realms-network
|
||||||
|
|
||||||
|
profiles:
|
||||||
|
- admin # Only start when explicitly requested
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# VOLUMES
|
||||||
|
# ===============================
|
||||||
|
volumes:
|
||||||
|
api-logs:
|
||||||
|
driver: local
|
||||||
|
admin-logs:
|
||||||
|
driver: local
|
||||||
|
nginx-logs:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# NETWORKS
|
||||||
|
# ===============================
|
||||||
|
networks:
|
||||||
|
shadowed-realms-network:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.20.0.0/16
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# ENVIRONMENT VARIABLES REQUIRED
|
||||||
|
# ===============================
|
||||||
|
# Create a .env file in the same directory with these values:
|
||||||
|
#
|
||||||
|
# POSTGRES_HOST=your.postgres.vm.ip
|
||||||
|
# POSTGRES_DB=ShadowedRealms
|
||||||
|
# POSTGRES_USER=gameserver
|
||||||
|
# POSTGRES_PASSWORD=your_secure_password
|
||||||
|
#
|
||||||
|
# REDIS_HOST=your.redis.vm.ip
|
||||||
|
# REDIS_PORT=6379
|
||||||
|
#
|
||||||
|
# JWT_SECRET_KEY=your_super_secure_jwt_secret_minimum_32_characters_long
|
||||||
|
# JWT_ISSUER=ShadowedRealms.API
|
||||||
|
# JWT_AUDIENCE=ShadowedRealms.Players
|
||||||
|
#
|
||||||
|
# KINGDOM_IDS=1,2,3,4,5
|
||||||
|
# ALLOWED_ORIGINS=https://yourdomain.com,https://admin.yourdomain.com
|
||||||
Loading…
x
Reference in New Issue
Block a user