sync public allowlist from private myoffice
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# MyOffice API (Kestrel :8080) — build from repo root:
|
||||
# docker build -f Docker/Dockerfile.api -t myoffice-api .
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
COPY MyOffice.sln ./
|
||||
COPY MyOffice.Core/MyOffice.Core.csproj MyOffice.Core/
|
||||
COPY MyOffice.Shared/MyOffice.Shared.csproj MyOffice.Shared/
|
||||
COPY MyOffice.Data.Models/MyOffice.Data.Models.csproj MyOffice.Data.Models/
|
||||
COPY MyOffice.DbContext/MyOffice.DbContext.csproj MyOffice.DbContext/
|
||||
COPY MyOffice.Data.Repositories/MyOffice.Data.Repositories.csproj MyOffice.Data.Repositories/
|
||||
COPY MyOffice.Services/MyOffice.Services.csproj MyOffice.Services/
|
||||
COPY MyOffice.Migration.Sqlite/MyOffice.Migrations.Sqlite.csproj MyOffice.Migration.Sqlite/
|
||||
COPY MyOffice.Migration.Postgres/MyOffice.Migrations.Postgres.csproj MyOffice.Migration.Postgres/
|
||||
COPY MyOffice.Web/MyOffice.Web.csproj MyOffice.Web/
|
||||
|
||||
RUN dotnet restore MyOffice.Web/MyOffice.Web.csproj
|
||||
|
||||
COPY MyOffice.Core/ MyOffice.Core/
|
||||
COPY MyOffice.Shared/ MyOffice.Shared/
|
||||
COPY MyOffice.Data.Models/ MyOffice.Data.Models/
|
||||
COPY MyOffice.DbContext/ MyOffice.DbContext/
|
||||
COPY MyOffice.Data.Repositories/ MyOffice.Data.Repositories/
|
||||
COPY MyOffice.Services/ MyOffice.Services/
|
||||
COPY MyOffice.Migration.Sqlite/ MyOffice.Migration.Sqlite/
|
||||
COPY MyOffice.Migration.Postgres/ MyOffice.Migration.Postgres/
|
||||
COPY MyOffice.Web/ MyOffice.Web/
|
||||
|
||||
RUN dotnet publish MyOffice.Web/MyOffice.Web.csproj -c Release -o /app/publish --no-restore
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/publish .
|
||||
|
||||
ENV ASPNETCORE_ENVIRONMENT=Docker
|
||||
ENV ASPNETCORE_URLS=http://+:8080
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["dotnet", "MyOffice.Web.dll"]
|
||||
@@ -0,0 +1,34 @@
|
||||
# MyOffice SPA (nginx :80) — build from repo root:
|
||||
# docker build -f Docker/Dockerfile.web --build-arg API_PUBLIC_URL=http://localhost:32081 -t myoffice-web .
|
||||
FROM node:20-alpine AS build
|
||||
WORKDIR /src
|
||||
|
||||
ARG API_PUBLIC_URL=http://localhost:32081
|
||||
|
||||
COPY MyOffice.SPA/package.json MyOffice.SPA/package-lock.json MyOffice.SPA/.npmrc ./
|
||||
RUN npm ci
|
||||
|
||||
COPY MyOffice.SPA/ ./
|
||||
|
||||
# environment.ts is gitignored locally — stub + docker env with public API URL (host port).
|
||||
RUN cp src/environments/environment.sample.ts src/environments/environment.ts \
|
||||
&& printf '%s\n' \
|
||||
'export const environment = {' \
|
||||
' production: true,' \
|
||||
" apiUrl: '${API_PUBLIC_URL}'," \
|
||||
" identityServer: '${API_PUBLIC_URL}/'," \
|
||||
" allowedUrls: ['${API_PUBLIC_URL}']," \
|
||||
' requireHttps: false,' \
|
||||
' externalLogins: {' \
|
||||
" google: { clientId: '' }," \
|
||||
" auth0: { clientId: '', domain: '' }" \
|
||||
' }' \
|
||||
'};' \
|
||||
> src/environments/environment.docker.ts \
|
||||
&& npm run build -- --configuration docker --output-path /out \
|
||||
&& if [ -d /out/browser ]; then cp -a /out/browser/. /out/ && rm -rf /out/browser; fi
|
||||
|
||||
FROM nginx:1.27-alpine AS final
|
||||
COPY Docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /out /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
@@ -0,0 +1,57 @@
|
||||
# MyOffice Docker demo
|
||||
|
||||
| Service | Default host port | Notes |
|
||||
|------------|-------------------|--------------------------------|
|
||||
| `web` | **32080** | Angular SPA (nginx) |
|
||||
| `api` | **32081** | ASP.NET Core + OpenIddict |
|
||||
| `pgadmin` | **32082** | pgAdmin 4 |
|
||||
| `postgres` | *(none)* | Internal only (`postgres:5432`) |
|
||||
|
||||
Empty Postgres is migrated and filled with demo users on API startup.
|
||||
|
||||
## Commands
|
||||
|
||||
```powershell
|
||||
.\build.ps1 # defaults :32080 / :32081 / :32082
|
||||
.\build.ps1 32080 32081 32082 # override front, back, pgAdmin
|
||||
.\build.ps1 up # build + recreate containers
|
||||
.\build.ps1 rebuild # --no-cache images + recreate (picks up API/CORS code)
|
||||
.\build.ps1 reset # wipe DB volumes + rebuild (new seed / password user_UAH)
|
||||
.\build.ps1 down
|
||||
.\build.ps1 logs
|
||||
```
|
||||
|
||||
Linux/macOS: `./build.sh` (same commands)
|
||||
|
||||
**Important:** demo users are seeded only into an empty DB. Changing password in code does nothing until you run `.\build.ps1 reset` (clears `data/demo/postgres`).
|
||||
|
||||
Custom ports rebuild the SPA so `apiUrl` / OIDC point at the chosen backend host port, and set `FrontEnd:Host` + CORS for the frontend origin.
|
||||
|
||||
## URLs & logins
|
||||
|
||||
Defaults (`.\build.ps1`):
|
||||
|
||||
| App | URL | Login |
|
||||
|-----|-----|--------|
|
||||
| Frontend | http://localhost:32080 | `user_UAH@user_UAH.userUAH` / `user_UAH` |
|
||||
| Backend | http://localhost:32081 | — |
|
||||
| pgAdmin | http://localhost:32082 | `admin@example.com` / `admin` |
|
||||
|
||||
Postgres is auto-registered in pgAdmin as server **myoffice** (host `postgres`, user/db/password `myoffice`) — no manual setup.
|
||||
If the server is missing after an older run: `.\build.ps1 reset` (or delete `data/demo/pgadmin`).
|
||||
|
||||
## Data folders
|
||||
|
||||
Bind mounts next to the compose file (gitignored under `Docker/data/`):
|
||||
|
||||
| Host path | Container |
|
||||
|-----------|-----------|
|
||||
| `Docker/data/demo/postgres` | `/var/lib/postgresql/data` |
|
||||
| `Docker/data/demo/pgadmin` | `/var/lib/pgadmin` |
|
||||
|
||||
Stop/start keeps these folders. Wipe with `.\build.ps1 reset` or delete the folders manually.
|
||||
|
||||
## Notes
|
||||
|
||||
- API uses `ASPNETCORE_ENVIRONMENT=Docker`, ephemeral OpenIddict keys, HTTP allowed.
|
||||
- Changing front/back ports rebuilds the SPA so API/OIDC URLs match.
|
||||
@@ -0,0 +1,158 @@
|
||||
# Build and start the MyOffice demo stack (SPA + API + Postgres + pgAdmin).
|
||||
# Usage:
|
||||
# .\build.ps1 # front 32080, back 32081, pgAdmin 32082
|
||||
# .\build.ps1 32080 32081 32082 # override ports
|
||||
# .\build.ps1 build | up | down | logs
|
||||
# .\build.ps1 rebuild # --no-cache images + recreate containers
|
||||
# .\build.ps1 reset # wipe ./data/demo/*, rebuild, start (new demo passwords)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Set-Location $here
|
||||
|
||||
$composeFile = 'docker-compose.demo.yml'
|
||||
$knownActions = @('build', 'up', 'down', 'logs', 'all', 'rebuild', 'reset')
|
||||
|
||||
function Test-Port([string]$value) {
|
||||
return $value -match '^\d{1,5}$' -and [int]$value -ge 1 -and [int]$value -le 65535
|
||||
}
|
||||
|
||||
function Format-Origin([string]$port) {
|
||||
if ($port -eq '80') { return 'http://localhost' }
|
||||
return "http://localhost:$port"
|
||||
}
|
||||
|
||||
function Show-UpInfo {
|
||||
param([string]$FrontOrigin, [string]$ApiPublicUrl, [string]$PgAdminUrl)
|
||||
Write-Host ''
|
||||
Write-Host 'Demo is up:'
|
||||
Write-Host " Frontend $FrontOrigin"
|
||||
Write-Host " Backend $ApiPublicUrl"
|
||||
Write-Host " pgAdmin $PgAdminUrl (admin@example.com / admin; DB auto-connected)"
|
||||
Write-Host ' Postgres internal host=postgres user/pass/db=myoffice'
|
||||
Write-Host ''
|
||||
Write-Host 'Demo logins: user_UAH@user_UAH.userUAH / user_UAH (also USD, EUR)'
|
||||
}
|
||||
|
||||
function Invoke-DockerCompose {
|
||||
param([Parameter(ValueFromRemainingArguments = $true)][string[]]$ComposeArgs)
|
||||
# Docker writes progress to stderr; with ErrorAction Stop that aborts the script.
|
||||
$prev = $ErrorActionPreference
|
||||
$ErrorActionPreference = 'Continue'
|
||||
try {
|
||||
& docker compose -f $composeFile @ComposeArgs
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "docker compose failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
finally {
|
||||
$ErrorActionPreference = $prev
|
||||
}
|
||||
}
|
||||
|
||||
# Parse: [action] [frontPort] [backPort] [pgAdminPort]
|
||||
# Numeric args arrive as Int32 — always normalize to string first.
|
||||
$action = 'all'
|
||||
$frontPort = '32080'
|
||||
$backPort = '32081'
|
||||
$pgAdminPort = '32082'
|
||||
$rest = @($args | ForEach-Object { "$_" })
|
||||
|
||||
if ($rest.Count -gt 0 -and $knownActions -contains $rest[0].ToLowerInvariant()) {
|
||||
$action = $rest[0].ToLowerInvariant()
|
||||
$rest = @($rest | Select-Object -Skip 1)
|
||||
}
|
||||
elseif ($rest.Count -gt 0 -and (Test-Port $rest[0])) {
|
||||
$action = 'all'
|
||||
}
|
||||
|
||||
if ($rest.Count -ge 1) {
|
||||
if (-not (Test-Port $rest[0])) {
|
||||
Write-Error "Invalid front port '$($rest[0])'. Example: .\build.ps1 32080 32081 32082"
|
||||
}
|
||||
$frontPort = [string]$rest[0]
|
||||
}
|
||||
if ($rest.Count -ge 2) {
|
||||
if (-not (Test-Port $rest[1])) {
|
||||
Write-Error "Invalid back port '$($rest[1])'. Example: .\build.ps1 32080 32081 32082"
|
||||
}
|
||||
$backPort = [string]$rest[1]
|
||||
}
|
||||
if ($rest.Count -ge 3) {
|
||||
if (-not (Test-Port $rest[2])) {
|
||||
Write-Error "Invalid pgAdmin port '$($rest[2])'. Example: .\build.ps1 32080 32081 32082"
|
||||
}
|
||||
$pgAdminPort = [string]$rest[2]
|
||||
}
|
||||
if ($rest.Count -gt 3 -and $action -ne 'down' -and $action -ne 'logs') {
|
||||
Write-Error 'Too many arguments. Usage: .\build.ps1 [build|up|down|logs|rebuild|reset] [frontPort] [backPort] [pgAdminPort]'
|
||||
}
|
||||
|
||||
$frontOrigin = Format-Origin $frontPort
|
||||
$apiPublicUrl = "http://localhost:$backPort"
|
||||
$pgAdminUrl = Format-Origin $pgAdminPort
|
||||
|
||||
$env:MYOFFICE_WEB_PORT = $frontPort
|
||||
$env:MYOFFICE_API_PORT = $backPort
|
||||
$env:MYOFFICE_PGADMIN_PORT = $pgAdminPort
|
||||
$env:MYOFFICE_FRONTEND_HOST = $frontOrigin
|
||||
$env:MYOFFICE_API_PUBLIC_URL = $apiPublicUrl
|
||||
$env:MYOFFICE_CORS_0 = $frontOrigin
|
||||
$env:MYOFFICE_CORS_1 = if ($frontPort -eq '80') { 'http://127.0.0.1' } else { "http://127.0.0.1:$frontPort" }
|
||||
|
||||
# Avoid stale compose env / cached layers leaving old API code running.
|
||||
$env:COMPOSE_DOCKER_CLI_BUILD = '1'
|
||||
$env:DOCKER_BUILDKIT = '1'
|
||||
|
||||
switch ($action) {
|
||||
'build' {
|
||||
Invoke-DockerCompose build
|
||||
}
|
||||
'up' {
|
||||
New-Item -ItemType Directory -Path (Join-Path $here 'data\demo\postgres') -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path (Join-Path $here 'data\demo\pgadmin') -Force | Out-Null
|
||||
Invoke-DockerCompose up -d --build --force-recreate --remove-orphans
|
||||
Show-UpInfo $frontOrigin $apiPublicUrl $pgAdminUrl
|
||||
}
|
||||
'down' {
|
||||
Invoke-DockerCompose down
|
||||
}
|
||||
'logs' {
|
||||
Invoke-DockerCompose logs -f
|
||||
}
|
||||
'rebuild' {
|
||||
Write-Host 'Rebuilding images with --no-cache (api + web)...'
|
||||
Invoke-DockerCompose build --no-cache --pull
|
||||
Invoke-DockerCompose up -d --force-recreate --remove-orphans
|
||||
Show-UpInfo $frontOrigin $apiPublicUrl $pgAdminUrl
|
||||
}
|
||||
'reset' {
|
||||
Write-Host 'Stopping stack and wiping ./data/demo/postgres and ./data/demo/pgadmin...'
|
||||
Invoke-DockerCompose down
|
||||
foreach ($dir in @('data\demo\postgres', 'data\demo\pgadmin')) {
|
||||
$path = Join-Path $here $dir
|
||||
if (Test-Path $path) {
|
||||
Remove-Item -LiteralPath $path -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Path $path -Force | Out-Null
|
||||
}
|
||||
# Drop old named volumes if they still exist from earlier setups.
|
||||
docker volume rm myoffice-demo_myoffice_pgdata myoffice-demo_myoffice_pgadmin 2>$null | Out-Null
|
||||
Write-Host 'Rebuilding images with --no-cache...'
|
||||
Invoke-DockerCompose build --no-cache --pull
|
||||
Invoke-DockerCompose up -d --force-recreate --remove-orphans
|
||||
Show-UpInfo $frontOrigin $apiPublicUrl $pgAdminUrl
|
||||
Write-Host ''
|
||||
Write-Host 'DB was reset. Login with password user_UAH (not user1_UAH).'
|
||||
Write-Host 'Data folders: Docker\data\demo\postgres , Docker\data\demo\pgadmin'
|
||||
}
|
||||
'all' {
|
||||
New-Item -ItemType Directory -Path (Join-Path $here 'data\demo\postgres') -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path (Join-Path $here 'data\demo\pgadmin') -Force | Out-Null
|
||||
Invoke-DockerCompose up -d --build --force-recreate --remove-orphans
|
||||
Show-UpInfo $frontOrigin $apiPublicUrl $pgAdminUrl
|
||||
}
|
||||
default {
|
||||
Write-Error "Unknown action '$action'. Use: build, up, down, logs, rebuild, reset, or no args."
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env sh
|
||||
# Build and start the MyOffice demo stack (SPA + API + Postgres + pgAdmin).
|
||||
# Usage:
|
||||
# ./build.sh # front 32080, back 32081, pgAdmin 32082
|
||||
# ./build.sh 32080 32081 32082 # override ports
|
||||
# ./build.sh build | up | down | logs
|
||||
# ./build.sh rebuild # --no-cache images + recreate containers
|
||||
# ./build.sh reset # wipe DB volumes, rebuild, start
|
||||
|
||||
set -eu
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
COMPOSE_FILE=docker-compose.demo.yml
|
||||
ACTION=all
|
||||
FRONT_PORT=32080
|
||||
BACK_PORT=32081
|
||||
PGADMIN_PORT=32082
|
||||
|
||||
is_port() {
|
||||
echo "$1" | grep -Eq '^[0-9]{1,5}$' && [ "$1" -ge 1 ] && [ "$1" -le 65535 ]
|
||||
}
|
||||
|
||||
origin_for() {
|
||||
if [ "$1" = "80" ]; then
|
||||
echo "http://localhost"
|
||||
else
|
||||
echo "http://localhost:$1"
|
||||
fi
|
||||
}
|
||||
|
||||
show_up_info() {
|
||||
echo ""
|
||||
echo "Demo is up:"
|
||||
echo " Frontend $1"
|
||||
echo " Backend $2"
|
||||
echo " pgAdmin $3 (admin@example.com / admin; DB auto-connected)"
|
||||
echo " Postgres internal host=postgres user/pass/db=myoffice"
|
||||
echo ""
|
||||
echo "Demo logins: user_UAH@user_UAH.userUAH / user_UAH (also USD, EUR)"
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "build" ] || [ "${1:-}" = "up" ] || [ "${1:-}" = "down" ] || [ "${1:-}" = "logs" ] || [ "${1:-}" = "all" ] || [ "${1:-}" = "rebuild" ] || [ "${1:-}" = "reset" ]; then
|
||||
ACTION=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "${1:-}" != "" ]; then
|
||||
is_port "$1" || { echo "Invalid front port '$1'. Example: ./build.sh 32080 32081 32082" >&2; exit 1; }
|
||||
FRONT_PORT=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "${1:-}" != "" ]; then
|
||||
is_port "$1" || { echo "Invalid back port '$1'. Example: ./build.sh 32080 32081 32082" >&2; exit 1; }
|
||||
BACK_PORT=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "${1:-}" != "" ]; then
|
||||
is_port "$1" || { echo "Invalid pgAdmin port '$1'. Example: ./build.sh 32080 32081 32082" >&2; exit 1; }
|
||||
PGADMIN_PORT=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "${1:-}" != "" ] && [ "$ACTION" != "down" ] && [ "$ACTION" != "logs" ]; then
|
||||
echo "Too many arguments. Usage: ./build.sh [build|up|down|logs|rebuild|reset] [frontPort] [backPort] [pgAdminPort]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FRONT_ORIGIN=$(origin_for "$FRONT_PORT")
|
||||
API_PUBLIC_URL="http://localhost:$BACK_PORT"
|
||||
PGADMIN_URL=$(origin_for "$PGADMIN_PORT")
|
||||
|
||||
export MYOFFICE_WEB_PORT=$FRONT_PORT
|
||||
export MYOFFICE_API_PORT=$BACK_PORT
|
||||
export MYOFFICE_PGADMIN_PORT=$PGADMIN_PORT
|
||||
export MYOFFICE_FRONTEND_HOST=$FRONT_ORIGIN
|
||||
export MYOFFICE_API_PUBLIC_URL=$API_PUBLIC_URL
|
||||
export MYOFFICE_CORS_0=$FRONT_ORIGIN
|
||||
if [ "$FRONT_PORT" = "80" ]; then
|
||||
export MYOFFICE_CORS_1=http://127.0.0.1
|
||||
else
|
||||
export MYOFFICE_CORS_1="http://127.0.0.1:$FRONT_PORT"
|
||||
fi
|
||||
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
case "$ACTION" in
|
||||
build)
|
||||
docker compose -f "$COMPOSE_FILE" build
|
||||
;;
|
||||
up)
|
||||
mkdir -p data/demo/postgres data/demo/pgadmin
|
||||
docker compose -f "$COMPOSE_FILE" up -d --build --force-recreate --remove-orphans
|
||||
show_up_info "$FRONT_ORIGIN" "$API_PUBLIC_URL" "$PGADMIN_URL"
|
||||
;;
|
||||
down)
|
||||
docker compose -f "$COMPOSE_FILE" down
|
||||
;;
|
||||
logs)
|
||||
docker compose -f "$COMPOSE_FILE" logs -f
|
||||
;;
|
||||
rebuild)
|
||||
echo "Rebuilding images with --no-cache (api + web)..."
|
||||
docker compose -f "$COMPOSE_FILE" build --no-cache --pull
|
||||
docker compose -f "$COMPOSE_FILE" up -d --force-recreate --remove-orphans
|
||||
show_up_info "$FRONT_ORIGIN" "$API_PUBLIC_URL" "$PGADMIN_URL"
|
||||
;;
|
||||
reset)
|
||||
echo "Stopping stack and wiping ./data/demo/postgres and ./data/demo/pgadmin..."
|
||||
docker compose -f "$COMPOSE_FILE" down
|
||||
rm -rf data/demo/postgres data/demo/pgadmin
|
||||
mkdir -p data/demo/postgres data/demo/pgadmin
|
||||
docker volume rm myoffice-demo_myoffice_pgdata myoffice-demo_myoffice_pgadmin 2>/dev/null || true
|
||||
echo "Rebuilding images with --no-cache..."
|
||||
docker compose -f "$COMPOSE_FILE" build --no-cache --pull
|
||||
docker compose -f "$COMPOSE_FILE" up -d --force-recreate --remove-orphans
|
||||
show_up_info "$FRONT_ORIGIN" "$API_PUBLIC_URL" "$PGADMIN_URL"
|
||||
echo ""
|
||||
echo "DB was reset. Login with password user_UAH (not user1_UAH)."
|
||||
echo "Data folders: Docker/data/demo/postgres , Docker/data/demo/pgadmin"
|
||||
;;
|
||||
all)
|
||||
mkdir -p data/demo/postgres data/demo/pgadmin
|
||||
docker compose -f "$COMPOSE_FILE" up -d --build --force-recreate --remove-orphans
|
||||
show_up_info "$FRONT_ORIGIN" "$API_PUBLIC_URL" "$PGADMIN_URL"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown action '$ACTION'. Use: build, up, down, logs, rebuild, reset, or no args." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
container_name: postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: appdb
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- ./data/postgres:/var/lib/postgresql/data
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:latest
|
||||
container_name: pgadmin
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: admin@example.com
|
||||
PGADMIN_DEFAULT_PASSWORD: admin
|
||||
ports:
|
||||
- "5433:80"
|
||||
volumes:
|
||||
- ./data/pgadmin:/var/lib/pgadmin
|
||||
depends_on:
|
||||
- postgres
|
||||
@@ -0,0 +1,96 @@
|
||||
# Demo stack: SPA + API + Postgres (internal) + pgAdmin.
|
||||
# Ports from env / build.ps1:
|
||||
# MYOFFICE_WEB_PORT (32080), MYOFFICE_API_PORT (32081), MYOFFICE_PGADMIN_PORT (32082)
|
||||
name: myoffice-demo
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17
|
||||
container_name: myoffice-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: myoffice
|
||||
POSTGRES_USER: myoffice
|
||||
POSTGRES_PASSWORD: myoffice
|
||||
volumes:
|
||||
# Host path (next to this compose file): ./data/demo/postgres
|
||||
- ./data/demo/postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U myoffice -d myoffice"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
networks:
|
||||
- myoffice
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:9
|
||||
container_name: myoffice-pgadmin
|
||||
restart: unless-stopped
|
||||
# Strip CRLF (Windows checkouts) then create pgpass (0600) and run image entrypoint.
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- sed 's/\r$//' /pgadmin-entrypoint.sh > /tmp/pgadmin-entrypoint.sh && exec /bin/sh /tmp/pgadmin-entrypoint.sh
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: admin@example.com
|
||||
PGADMIN_DEFAULT_PASSWORD: admin
|
||||
PGADMIN_CONFIG_SERVER_MODE: "False"
|
||||
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False"
|
||||
ports:
|
||||
- "${MYOFFICE_PGADMIN_PORT:-32082}:80"
|
||||
volumes:
|
||||
# Host path: ./data/demo/pgadmin
|
||||
- ./data/demo/pgadmin:/var/lib/pgadmin
|
||||
- ./pgadmin/servers.json:/pgadmin4/servers.json:ro
|
||||
- ./pgadmin/entrypoint.sh:/pgadmin-entrypoint.sh:ro
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- myoffice
|
||||
|
||||
api:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Docker/Dockerfile.api
|
||||
image: myoffice-api:demo
|
||||
container_name: myoffice-api
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${MYOFFICE_API_PORT:-32081}:8080"
|
||||
environment:
|
||||
ASPNETCORE_ENVIRONMENT: Docker
|
||||
ASPNETCORE_URLS: http://+:8080
|
||||
DatabaseProvider: npgsql
|
||||
ConnectionStrings__npgsql: Host=postgres;Port=5432;Database=myoffice;Username=myoffice;Password=myoffice
|
||||
FrontEnd__Host: ${MYOFFICE_FRONTEND_HOST:-http://localhost:32080}
|
||||
Cors__AllowedOrigins__0: ${MYOFFICE_CORS_0:-http://localhost:32080}
|
||||
Cors__AllowedOrigins__1: ${MYOFFICE_CORS_1:-http://127.0.0.1:32080}
|
||||
OpenIddict__UseEphemeralKeys: "true"
|
||||
OpenIddict__AllowHttp: "true"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- myoffice
|
||||
|
||||
web:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Docker/Dockerfile.web
|
||||
args:
|
||||
API_PUBLIC_URL: ${MYOFFICE_API_PUBLIC_URL:-http://localhost:32081}
|
||||
image: myoffice-web:demo
|
||||
container_name: myoffice-web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${MYOFFICE_WEB_PORT:-32080}:80"
|
||||
depends_on:
|
||||
- api
|
||||
networks:
|
||||
- myoffice
|
||||
|
||||
networks:
|
||||
myoffice:
|
||||
driver: bridge
|
||||
@@ -0,0 +1,17 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# Create pgpass inside the container (mode 0600). Bind-mounted files from Windows
|
||||
# cannot satisfy pgAdmin's permission check.
|
||||
set -eu
|
||||
|
||||
PASSFILE=/var/lib/pgadmin/pgpass
|
||||
printf '%s\n' 'postgres:5432:*:myoffice:myoffice' > "$PASSFILE"
|
||||
chown 5050:0 "$PASSFILE" 2>/dev/null || true
|
||||
chmod 600 "$PASSFILE"
|
||||
|
||||
exec /entrypoint.sh "$@"
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "myoffice",
|
||||
"Group": "Servers",
|
||||
"Host": "postgres",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "myoffice",
|
||||
"Username": "myoffice",
|
||||
"SSLMode": "prefer",
|
||||
"PassFile": "/var/lib/pgadmin/pgpass"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user