feat: docker-compose prod setup
This commit is contained in:
parent
cdc91aec57
commit
d3fd4d6c0e
7 changed files with 157 additions and 21 deletions
17
.env.example
17
.env.example
|
|
@ -1 +1,16 @@
|
||||||
OIDC_CLIENT_SECRET=
|
# Production Environment Variables for docker-compose.prod.yml
|
||||||
|
# Copy this file to .env and fill in the actual values
|
||||||
|
|
||||||
|
# Required: Phoenix secrets (generate with: mix phx.gen.secret)
|
||||||
|
SECRET_KEY_BASE=changeme-run-mix-phx.gen.secret
|
||||||
|
TOKEN_SIGNING_SECRET=changeme-run-mix-phx.gen.secret
|
||||||
|
|
||||||
|
# Required: Hostname for URL generation
|
||||||
|
PHX_HOST=localhost
|
||||||
|
|
||||||
|
# Optional: OIDC Configuration
|
||||||
|
# These have defaults in docker-compose.prod.yml, only override if needed
|
||||||
|
# OIDC_CLIENT_ID=mv
|
||||||
|
# OIDC_BASE_URL=http://localhost:8080/auth/v1
|
||||||
|
# OIDC_REDIRECT_URI=http://localhost:4001/auth/user/rauthy/callback
|
||||||
|
# OIDC_CLIENT_SECRET=your-rauthy-client-secret
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
ARG BUILDER_IMAGE="hexpm/elixir:1.18.3-erlang-27.3-debian-bullseye-20250317-slim"
|
ARG BUILDER_IMAGE="hexpm/elixir:1.18.3-erlang-27.3-debian-bullseye-20250317-slim"
|
||||||
ARG RUNNER_IMAGE="debian:bullseye-20250317-slim"
|
ARG RUNNER_IMAGE="debian:bullseye-20250317-slim"
|
||||||
|
|
||||||
FROM ${BUILDER_IMAGE} as builder
|
FROM ${BUILDER_IMAGE} AS builder
|
||||||
|
|
||||||
# install build dependencies
|
# install build dependencies
|
||||||
RUN apt-get update -y && apt-get install -y build-essential git \
|
RUN apt-get update -y && apt-get install -y build-essential git \
|
||||||
|
|
@ -70,9 +70,9 @@ RUN apt-get update -y && \
|
||||||
# Set the locale
|
# Set the locale
|
||||||
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
|
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
|
||||||
|
|
||||||
ENV LANG en_US.UTF-8
|
ENV LANG=en_US.UTF-8
|
||||||
ENV LANGUAGE en_US:en
|
ENV LANGUAGE=en_US:en
|
||||||
ENV LC_ALL en_US.UTF-8
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
WORKDIR "/app"
|
WORKDIR "/app"
|
||||||
RUN chown nobody /app
|
RUN chown nobody /app
|
||||||
|
|
|
||||||
66
README.md
66
README.md
|
|
@ -183,12 +183,70 @@ Useful `just` commands:
|
||||||
- `just reset-database` — reset local DB
|
- `just reset-database` — reset local DB
|
||||||
- `just regen-migrations <name>` — regenerate migrations
|
- `just regen-migrations <name>` — regenerate migrations
|
||||||
|
|
||||||
## 📦 Deployment
|
## 📦 Production Deployment
|
||||||
|
|
||||||
A production release image is built via the provided `Dockerfile`.
|
### Local Production Testing
|
||||||
Entrypoint: `/app/bin/server`.
|
|
||||||
|
For testing the production Docker build locally:
|
||||||
|
|
||||||
|
1. **Generate secrets:**
|
||||||
|
```bash
|
||||||
|
mix phx.gen.secret # for SECRET_KEY_BASE
|
||||||
|
mix phx.gen.secret # for TOKEN_SIGNING_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create `.env` file:**
|
||||||
|
```bash
|
||||||
|
# Copy template and edit
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env
|
||||||
|
|
||||||
|
# Required variables:
|
||||||
|
SECRET_KEY_BASE=<your-generated-secret>
|
||||||
|
TOKEN_SIGNING_SECRET=<your-generated-secret>
|
||||||
|
PHX_HOST=localhost
|
||||||
|
|
||||||
|
# Optional (have defaults in docker-compose.prod.yml):
|
||||||
|
# OIDC_CLIENT_ID=mv
|
||||||
|
# OIDC_BASE_URL=http://localhost:8080/auth/v1
|
||||||
|
# OIDC_REDIRECT_URI=http://localhost:4001/auth/user/rauthy/callback
|
||||||
|
# OIDC_CLIENT_SECRET=<from-rauthy-client>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start development environment** (for Rauthy):
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Build and start production environment:**
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Run database migrations:**
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml exec app /app/bin/mv eval "Mv.Release.migrate"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Access the production app:**
|
||||||
|
- Production App: http://localhost:4001
|
||||||
|
- Uses same Rauthy instance as dev (localhost:8080)
|
||||||
|
|
||||||
|
**Note:** The local production setup uses `network_mode: host` to share localhost with the development Rauthy instance. For real production deployment, configure an external OIDC provider and remove `network_mode: host`.
|
||||||
|
|
||||||
|
### Real Production Deployment
|
||||||
|
|
||||||
|
For actual production deployment:
|
||||||
|
|
||||||
|
1. **Use an external OIDC provider** (not the local Rauthy)
|
||||||
|
2. **Update `docker-compose.prod.yml`:**
|
||||||
|
- Remove `network_mode: host`
|
||||||
|
- Set `OIDC_BASE_URL` to your production OIDC provider
|
||||||
|
- Configure proper Docker networks
|
||||||
|
3. **Set up SSL/TLS** (e.g., via reverse proxy like Nginx/Traefik)
|
||||||
|
4. **Use secure secrets management** (environment variables, Docker secrets, vault)
|
||||||
|
5. **Configure database backups**
|
||||||
|
|
||||||
More detailed deployment docs are planned.
|
|
||||||
|
|
||||||
## 🤝 Contributing
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,16 @@ config :swoosh, local: false
|
||||||
# Do not print debug messages in production
|
# Do not print debug messages in production
|
||||||
config :logger, level: :info
|
config :logger, level: :info
|
||||||
|
|
||||||
|
# AshAuthentication production configuration
|
||||||
|
# These must be set at compile-time (not in runtime.exs) because
|
||||||
|
# Application.compile_env!/3 is used in lib/accounts/user.ex
|
||||||
|
config :mv, :session_identifier, :jti
|
||||||
|
|
||||||
|
config :mv, :require_token_presence_for_authentication, true
|
||||||
|
|
||||||
|
# Token signing secret - using a placeholder that MUST be overridden
|
||||||
|
# at runtime via environment variable in config/runtime.exs
|
||||||
|
config :mv, :token_signing_secret, "REPLACE_ME_AT_RUNTIME"
|
||||||
|
|
||||||
# Runtime production configuration, including reading
|
# Runtime production configuration, including reading
|
||||||
# of environment variables, is done on config/runtime.exs.
|
# of environment variables, is done on config/runtime.exs.
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,24 @@ if config_env() == :prod do
|
||||||
|
|
||||||
config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
|
config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
|
||||||
|
|
||||||
config :mv, :rauthy, redirect_uri: "http://localhost:4000/auth/user/rauthy/callback"
|
# Rauthy OIDC configuration
|
||||||
|
config :mv, :rauthy,
|
||||||
|
client_id: System.get_env("OIDC_CLIENT_ID") || "mv",
|
||||||
|
base_url: System.get_env("OIDC_BASE_URL") || "http://localhost:8080/auth/v1",
|
||||||
|
client_secret: System.get_env("OIDC_CLIENT_SECRET"),
|
||||||
|
redirect_uri:
|
||||||
|
System.get_env("OIDC_REDIRECT_URI") || "http://#{host}:#{port}/auth/user/rauthy/callback"
|
||||||
|
|
||||||
# AshAuthentication production configuration
|
# Token signing secret from environment variable
|
||||||
config :mv, :session_identifier, :jti
|
# This overrides the placeholder value set in prod.exs
|
||||||
|
token_signing_secret =
|
||||||
|
System.get_env("TOKEN_SIGNING_SECRET") ||
|
||||||
|
raise """
|
||||||
|
environment variable TOKEN_SIGNING_SECRET is missing.
|
||||||
|
You can generate one by calling: mix phx.gen.secret
|
||||||
|
"""
|
||||||
|
|
||||||
config :mv, :require_token_presence_for_authentication, true
|
config :mv, :token_signing_secret, token_signing_secret
|
||||||
|
|
||||||
config :mv, MvWeb.Endpoint,
|
config :mv, MvWeb.Endpoint,
|
||||||
url: [host: host, port: 443, scheme: "https"],
|
url: [host: host, port: 443, scheme: "https"],
|
||||||
|
|
@ -70,7 +82,13 @@ if config_env() == :prod do
|
||||||
ip: {0, 0, 0, 0, 0, 0, 0, 0},
|
ip: {0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
port: port
|
port: port
|
||||||
],
|
],
|
||||||
secret_key_base: secret_key_base
|
secret_key_base: secret_key_base,
|
||||||
|
# Allow connections from localhost and 127.0.0.1
|
||||||
|
check_origin: [
|
||||||
|
"//#{host}",
|
||||||
|
"//localhost:#{port}",
|
||||||
|
"//127.0.0.1:#{port}"
|
||||||
|
]
|
||||||
|
|
||||||
# ## SSL Support
|
# ## SSL Support
|
||||||
#
|
#
|
||||||
|
|
|
||||||
39
docker-compose.prod.yml
Normal file
39
docker-compose.prod.yml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
image: mv:latest
|
||||||
|
container_name: mv-prod-app
|
||||||
|
# Use host network for local testing to access localhost:8080 (Rauthy)
|
||||||
|
# In real production, remove this and use external OIDC provider
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: "ecto://postgres:postgres@localhost:5001/mv_prod"
|
||||||
|
SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
|
||||||
|
TOKEN_SIGNING_SECRET: "${TOKEN_SIGNING_SECRET}"
|
||||||
|
PHX_HOST: "${PHX_HOST}"
|
||||||
|
PORT: "4001"
|
||||||
|
PHX_SERVER: "true"
|
||||||
|
# Rauthy OIDC config - uses localhost because of host network mode
|
||||||
|
OIDC_CLIENT_ID: "mv"
|
||||||
|
OIDC_BASE_URL: "http://localhost:8080/auth/v1"
|
||||||
|
OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET:-}"
|
||||||
|
OIDC_REDIRECT_URI: "http://localhost:4001/auth/user/rauthy/callback"
|
||||||
|
depends_on:
|
||||||
|
- db-prod
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
db-prod:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: mv-prod-db
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: mv_prod
|
||||||
|
volumes:
|
||||||
|
- postgres_data_prod:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "5001:5432"
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data_prod:
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
networks:
|
networks:
|
||||||
local:
|
local:
|
||||||
rauthy-dev:
|
rauthy-dev:
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
|
|
@ -39,12 +38,8 @@ services:
|
||||||
- LISTEN_SCHEME=http
|
- LISTEN_SCHEME=http
|
||||||
- PUB_URL=localhost:8080
|
- PUB_URL=localhost:8080
|
||||||
- BOOTSTRAP_ADMIN_PASSWORD_PLAIN=RauthyTest12345
|
- BOOTSTRAP_ADMIN_PASSWORD_PLAIN=RauthyTest12345
|
||||||
#- HIQLITE=false
|
# Disable strict IP validation to allow access from multiple Docker networks
|
||||||
#- PG_HOST=db
|
- SESSION_VALIDATE_IP=false
|
||||||
#- PG_PORT=5432
|
|
||||||
#- PG_USER=postgres
|
|
||||||
#- PG_PASSWORD=postgres
|
|
||||||
#- PG_DB_NAME=mv_dev
|
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue