feat: add docker configuration
This commit is contained in:
parent
821712f43b
commit
cf2f624ae4
21 changed files with 232 additions and 13 deletions
23
.dockerignore
Normal file
23
.dockerignore
Normal file
|
@ -0,0 +1,23 @@
|
|||
**/.dockerignore
|
||||
**/.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
|
8
DOCKER.md
Normal file
8
DOCKER.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Running with Docker
|
||||
|
||||
1. Copy `docker/config.example.ini` to `docker/config.ini`, and change the settings to your liking.
|
||||
2. Copy `docker/proxy-config.example.json` to `docker/proxy-config.json`, and do the same.
|
||||
3. Build with `docker compose build`
|
||||
4. Run with `docker compose up`
|
||||
|
||||
The Caddy server will listen on `localhost:5004`.
|
22
Dockerfile.backend
Normal file
22
Dockerfile.backend
Normal file
|
@ -0,0 +1,22 @@
|
|||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||
USER $APP_UID
|
||||
WORKDIR /app
|
||||
EXPOSE 5000
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
WORKDIR /src
|
||||
COPY ["Foxnouns.Backend/Foxnouns.Backend.csproj", "Foxnouns.Backend/"]
|
||||
RUN dotnet restore "Foxnouns.Backend/Foxnouns.Backend.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Foxnouns.Backend"
|
||||
RUN dotnet build "Foxnouns.Backend.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
RUN dotnet publish "Foxnouns.Backend.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Foxnouns.Backend.dll", "--migrate-and-start"]
|
|
@ -4,6 +4,7 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -44,4 +45,10 @@
|
|||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\.version" LogicalName="version" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
12
Foxnouns.Frontend/Dockerfile
Normal file
12
Foxnouns.Frontend/Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
|||
FROM docker.io/node:22
|
||||
|
||||
RUN mkdir -p /app/node_modules && chown -R node:node /app
|
||||
WORKDIR /app
|
||||
COPY package.json yarn.lock ./
|
||||
USER node
|
||||
RUN yarn
|
||||
COPY --chown=node:node . .
|
||||
|
||||
RUN yarn build
|
||||
|
||||
CMD ["yarn", "start"]
|
|
@ -1,5 +1,5 @@
|
|||
import { TFunction } from "i18next";
|
||||
import Alert from "react-bootstrap/Alert";
|
||||
import { Alert } from "react-bootstrap";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import {
|
||||
ApiError,
|
||||
|
|
|
@ -3,9 +3,7 @@ import Meta from "~/lib/api/meta";
|
|||
import { User, UserSettings } from "~/lib/api/user";
|
||||
import Logo from "./Logo";
|
||||
|
||||
import Nav from "react-bootstrap/Nav";
|
||||
import Navbar from "react-bootstrap/Navbar";
|
||||
import NavDropdown from "react-bootstrap/NavDropdown";
|
||||
import { Nav, Navbar, NavDropdown } from "react-bootstrap";
|
||||
import { BrightnessHigh, BrightnessHighFill, MoonFill } from "react-bootstrap-icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import "dotenv/config";
|
||||
import { env } from "node:process";
|
||||
|
||||
export const API_BASE = env.API_BASE || "https://pronouns.localhost/api";
|
||||
|
|
|
@ -10,10 +10,8 @@ import {
|
|||
ShouldRevalidateFunction,
|
||||
} from "@remix-run/react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import Form from "react-bootstrap/Form";
|
||||
import Button from "react-bootstrap/Button";
|
||||
import { Form, Button, Alert } from "react-bootstrap";
|
||||
import ErrorAlert from "~/components/ErrorAlert";
|
||||
import Alert from "react-bootstrap/Alert";
|
||||
|
||||
export const shouldRevalidate: ShouldRevalidateFunction = ({ actionResult }) => {
|
||||
return !actionResult;
|
||||
|
|
|
@ -6,11 +6,7 @@ import {
|
|||
ActionFunctionArgs,
|
||||
} from "@remix-run/node";
|
||||
import { Form as RemixForm, useActionData, useLoaderData } from "@remix-run/react";
|
||||
import Form from "react-bootstrap/Form";
|
||||
import Button from "react-bootstrap/Button";
|
||||
import ButtonGroup from "react-bootstrap/ButtonGroup";
|
||||
import ListGroup from "react-bootstrap/ListGroup";
|
||||
import { Row, Col } from "react-bootstrap";
|
||||
import { Form, Button, ButtonGroup, ListGroup, Row, Col } from "react-bootstrap";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import i18n from "~/i18next.server";
|
||||
import serverRequest, { getToken, writeCookie } from "~/lib/request.server";
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"compression": "^1.7.4",
|
||||
"cookie": "^0.6.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"i18next": "^23.15.1",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
|
|
|
@ -2554,7 +2554,7 @@ domutils@^3.0.1, domutils@^3.1.0:
|
|||
domelementtype "^2.3.0"
|
||||
domhandler "^5.0.3"
|
||||
|
||||
dotenv@^16.0.0:
|
||||
dotenv@^16.0.0, dotenv@^16.4.5:
|
||||
version "16.4.5"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
|
||||
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
|
||||
|
|
71
docker-compose.yml
Normal file
71
docker-compose.yml
Normal file
|
@ -0,0 +1,71 @@
|
|||
services:
|
||||
backend:
|
||||
image: backend
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile.backend
|
||||
environment:
|
||||
- "Database:Url=Host=pgbouncer;Database=postgres;Username=postgres;Password=postgres"
|
||||
- "Database:EnablePooling=false"
|
||||
- "Host=0.0.0.0"
|
||||
- "Port=5000"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./docker/config.ini:/app/config.ini
|
||||
|
||||
frontend:
|
||||
image: frontend
|
||||
build: ./Foxnouns.Frontend
|
||||
environment:
|
||||
- "API_BASE=http://rate:5003/api"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./docker/frontend.env:/app/.env
|
||||
|
||||
rate:
|
||||
image: rate
|
||||
build: ./rate
|
||||
environment:
|
||||
- "PORT=5003"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./docker/proxy-config.json:/app/proxy-config.json
|
||||
|
||||
pgbouncer:
|
||||
image: docker.io/edoburu/pgbouncer:latest
|
||||
environment:
|
||||
- "DATABASE_URL=postgres://postgres:postgres@postgres/postgres"
|
||||
- "AUTH_TYPE=scram-sha-256"
|
||||
- "MAX_CLIENT_CONN=100"
|
||||
- "DEFAULT_POOL_SIZE=100"
|
||||
- "MIN_POOL_SIZE=10"
|
||||
restart: unless-stopped
|
||||
|
||||
postgres:
|
||||
image: docker.io/postgres:16
|
||||
command: [ "postgres",
|
||||
"-c", "max-connections=1000",
|
||||
"-c", "timezone=Etc/UTC",
|
||||
"-c", "max_wal_size=1GB",
|
||||
"-c", "min_wal_size=80MB",
|
||||
"-c", "shared_buffers=128MB" ]
|
||||
environment:
|
||||
- "POSTGRES_PASSWORD=postgres"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
caddy:
|
||||
image: docker.io/caddy:2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5004:80"
|
||||
volumes:
|
||||
- ./docker/Caddyfile:/etc/caddy/Caddyfile
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
postgres_data:
|
4
docker/Caddyfile
Normal file
4
docker/Caddyfile
Normal file
|
@ -0,0 +1,4 @@
|
|||
http:// {
|
||||
reverse_proxy /api/* http://rate:5003
|
||||
reverse_proxy http://frontend:3000
|
||||
}
|
48
docker/config.example.ini
Normal file
48
docker/config.example.ini
Normal file
|
@ -0,0 +1,48 @@
|
|||
;; This configuration file is specifically for Docker installations.
|
||||
;; Host, Port, and Database settings are overridden in the compose configuration.
|
||||
|
||||
; The base *external* URL
|
||||
BaseUrl = https://pronouns.localhost
|
||||
; The base URL for media, without a trailing slash. This must be publicly accessible.
|
||||
MediaBaseUrl = https://cdn-staging.pronouns.localhost
|
||||
|
||||
[Logging]
|
||||
; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal
|
||||
LogEventLevel = Debug
|
||||
; The URL to the Seq instance (optional)
|
||||
SeqLogUrl = http://localhost:5341
|
||||
; The Sentry DSN to log to (optional)
|
||||
SentryUrl = https://examplePublicKey@o0.ingest.sentry.io/0
|
||||
; Whether to trace performance with Sentry (optional)
|
||||
SentryTracing = true
|
||||
; Percentage of performance traces to send to Sentry (optional). Defaults to 0.0 (no traces at all)
|
||||
SentryTracesSampleRate = 1.0
|
||||
; Whether to log SQL queries. Note that this is very verbose. Defaults to false.
|
||||
LogQueries = false
|
||||
; Whether metrics are enabled. If this is set to true, Foxnouns.NET will rely on Prometheus scraping metrics to update stats.
|
||||
; If set to false, a background service will be used instead. Does not actually disable the /metrics endpoint.
|
||||
; Defaults to false.
|
||||
EnableMetrics = true
|
||||
; The port the /metrics endpoint will listen on. Defaults to 5001.
|
||||
MetricsPort = 5001
|
||||
|
||||
[Storage]
|
||||
Endpoint = <s3EndpointHere>
|
||||
AccessKey = <s3AccessKey>
|
||||
SecretKey = <s3SecretKey>
|
||||
Bucket = pronounscc
|
||||
|
||||
[EmailAuth]
|
||||
; The address that emails will be sent from. If not set, email auth is disabled.
|
||||
From = noreply@accounts.pronouns.cc
|
||||
|
||||
; The Coravel mail driver configuration. Keys should be self-explanatory.
|
||||
[Coravel:Mail]
|
||||
Host = localhost
|
||||
Port = 1025
|
||||
Username = smtp-username
|
||||
Password = smtp-password
|
||||
|
||||
[DiscordAuth]
|
||||
ClientId = <clientIdHere>
|
||||
ClientSecret = <clientSecretHere>
|
0
docker/frontend.env
Normal file
0
docker/frontend.env
Normal file
6
docker/proxy-config.example.json
Normal file
6
docker/proxy-config.example.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"port": 5003,
|
||||
"proxy_target": "http://localhost:5000",
|
||||
"debug": true,
|
||||
"powered_by": "5 gay rats"
|
||||
}
|
16
rate/Dockerfile
Normal file
16
rate/Dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
FROM docker.io/golang:latest AS builder
|
||||
WORKDIR /build
|
||||
EXPOSE 5003
|
||||
|
||||
COPY . ./
|
||||
RUN go mod download -x
|
||||
ENV CGO_ENABLED 0
|
||||
RUN go build -v -o rate
|
||||
|
||||
FROM alpine:latest
|
||||
RUN apk --no-cache add ca-certificates
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /build/rate rate
|
||||
|
||||
CMD ["/app/rate"]
|
|
@ -23,6 +23,14 @@ func main() {
|
|||
log.Fatalf("unmarshaling config.json: %v", err)
|
||||
}
|
||||
|
||||
// Override port from environment if it's set
|
||||
if portEnv := os.Getenv("PORT"); portEnv != "" {
|
||||
port, err := strconv.Atoi(portEnv)
|
||||
if err == nil {
|
||||
hn.Port = port
|
||||
}
|
||||
}
|
||||
|
||||
proxyURL, err := url.Parse(hn.ProxyTarget)
|
||||
if err != nil {
|
||||
log.Fatalf("parsing proxy_target as URL: %v", err)
|
||||
|
|
Loading…
Reference in a new issue