Add self-contained Docker Compose stacks for pivoine.art infrastructure
Migrated 11 services from monolithic docker-compose project into independent stacks, each with dedicated databases, minimal .env configuration, and bind-mount data volumes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.claude
|
||||
.env
|
||||
*.sql
|
||||
39
README.md
Normal file
39
README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Stacks
|
||||
|
||||
Self-contained Docker Compose stacks for `pivoine.art` infrastructure.
|
||||
|
||||
Each stack is independently deployable with its own `compose.yml` and `.env`. All persistent data lives in `../.data/<stack>/`.
|
||||
|
||||
## Stacks
|
||||
|
||||
| Stack | Description | Services |
|
||||
|---|---|---|
|
||||
| `traefik` | Reverse proxy, TLS termination | traefik |
|
||||
| `mailpit` | SMTP relay (no web UI) | mailpit |
|
||||
| `watchtower` | Automatic container updates | watchtower |
|
||||
| `umami` | Web analytics | umami, db |
|
||||
| `immich` | Photo & video management | immich, ml, redis, db |
|
||||
| `joplin` | Note sync server | joplin, db |
|
||||
| `mattermost` | Team chat | mattermost, db |
|
||||
| `gitea` | Git hosting + CI runner | gitea, runner, db |
|
||||
| `coolify` | Deployment platform | coolify, realtime, redis, db |
|
||||
| `sexy` | pivoine.art website | directus, frontend, redis, db |
|
||||
| `vaultwarden` | Password manager | vaultwarden |
|
||||
|
||||
## Deployment
|
||||
|
||||
```bash
|
||||
# Sync a stack to VPS
|
||||
rsync -avz <stack>/ vps:~/stacks/<stack>/
|
||||
|
||||
# Start a stack
|
||||
ssh vps 'cd ~/stacks/<stack> && docker compose up -d'
|
||||
```
|
||||
|
||||
## Network
|
||||
|
||||
All stacks share the external `falcon_network` Docker network for inter-service communication (e.g. traefik routing, mailpit SMTP).
|
||||
|
||||
## Data
|
||||
|
||||
Persistent data is stored in `~/stacks/.data/<stack>/` on the VPS using bind mounts. Database stacks use dedicated Postgres instances with simple credentials.
|
||||
129
coolify/compose.yml
Normal file
129
coolify/compose.yml
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
services:
|
||||
coolify:
|
||||
image: ghcr.io/coollabsio/coolify:latest
|
||||
container_name: coolify
|
||||
environment:
|
||||
APP_ID: ${APP_ID}
|
||||
APP_KEY: ${APP_KEY}
|
||||
APP_NAME: Coolify
|
||||
APP_ENV: production
|
||||
APP_URL: https://${TRAEFIK_HOST}
|
||||
APP_PORT: 8080
|
||||
DB_HOST: coolify_db
|
||||
DB_PORT: 5432
|
||||
DB_DATABASE: coolify
|
||||
DB_USERNAME: coolify
|
||||
DB_PASSWORD: coolify
|
||||
REDIS_HOST: coolify_redis
|
||||
REDIS_PORT: 6379
|
||||
PUSHER_HOST: realtime.${TRAEFIK_HOST}
|
||||
PUSHER_PORT: 443
|
||||
PUSHER_APP_ID: ${PUSHER_APP_ID}
|
||||
PUSHER_APP_KEY: ${PUSHER_APP_KEY}
|
||||
PUSHER_APP_SECRET: ${PUSHER_APP_SECRET}
|
||||
PUSHER_SCHEME: https
|
||||
SSL_MODE: "off"
|
||||
volumes:
|
||||
- ../.data/coolify/data:/data/coolify
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ../.data/coolify/storage/ssh:/var/www/html/storage/app/ssh
|
||||
- ../.data/coolify/storage/applications:/var/www/html/storage/app/applications
|
||||
- ../.data/coolify/storage/databases:/var/www/html/storage/app/databases
|
||||
- ../.data/coolify/storage/services:/var/www/html/storage/app/services
|
||||
- ../.data/coolify/storage/backups:/var/www/html/storage/app/backups
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
realtime:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.coolify-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.coolify-web.middlewares=coolify-redirect-web-secure"
|
||||
- "traefik.http.routers.coolify-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.coolify-web.entrypoints=web"
|
||||
- "traefik.http.routers.coolify-web.service=coolify"
|
||||
- "traefik.http.routers.coolify-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.coolify-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.coolify-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.coolify-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.routers.coolify-web-secure.service=coolify"
|
||||
- "traefik.http.routers.coolify-web-secure.priority=1"
|
||||
- "traefik.http.services.coolify.loadbalancer.server.port=8080"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
realtime:
|
||||
image: ghcr.io/coollabsio/coolify-realtime:1.0.10
|
||||
container_name: coolify_realtime
|
||||
environment:
|
||||
APP_NAME: Coolify
|
||||
SOKETI_DEBUG: "false"
|
||||
SOKETI_DEFAULT_APP_ID: ${PUSHER_APP_ID}
|
||||
SOKETI_DEFAULT_APP_KEY: ${PUSHER_APP_KEY}
|
||||
SOKETI_DEFAULT_APP_SECRET: ${PUSHER_APP_SECRET}
|
||||
volumes:
|
||||
- ../.data/coolify/storage/ssh:/var/www/html/storage/app/ssh
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready"]
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 10
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.coolify-realtime-web.rule=Host(`realtime.${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.coolify-realtime-web.entrypoints=web"
|
||||
- "traefik.http.routers.coolify-realtime-web.service=coolify-realtime"
|
||||
- "traefik.http.routers.coolify-realtime-web-secure.rule=Host(`realtime.${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.coolify-realtime-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.coolify-realtime-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.coolify-realtime-web-secure.service=coolify-realtime"
|
||||
- "traefik.http.services.coolify-realtime.loadbalancer.server.port=6001"
|
||||
- "traefik.http.routers.coolify-terminal-ws.rule=Host(`${TRAEFIK_HOST}`) && PathPrefix(`/terminal/ws`)"
|
||||
- "traefik.http.routers.coolify-terminal-ws.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.coolify-terminal-ws.entrypoints=web-secure"
|
||||
- "traefik.http.routers.coolify-terminal-ws.service=coolify-terminal"
|
||||
- "traefik.http.routers.coolify-terminal-ws.priority=100"
|
||||
- "traefik.http.services.coolify-terminal.loadbalancer.server.port=6002"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: coolify_redis
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: coolify_db
|
||||
environment:
|
||||
POSTGRES_DB: coolify
|
||||
POSTGRES_USER: coolify
|
||||
POSTGRES_PASSWORD: coolify
|
||||
volumes:
|
||||
- ../.data/coolify/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
104
gitea/compose.yml
Normal file
104
gitea/compose.yml
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
USER_UID: 1000
|
||||
USER_GID: 1000
|
||||
GITEA__APP_NAME: dev.pivoine.art
|
||||
GITEA__database__DB_TYPE: postgres
|
||||
GITEA__database__HOST: gitea_db:5432
|
||||
GITEA__database__NAME: gitea
|
||||
GITEA__database__USER: gitea
|
||||
GITEA__database__PASSWD: gitea
|
||||
GITEA__server__DOMAIN: ${TRAEFIK_HOST}
|
||||
GITEA__server__SSH_DOMAIN: ${TRAEFIK_HOST}
|
||||
GITEA__server__ROOT_URL: https://${TRAEFIK_HOST}/
|
||||
GITEA__server__PROTOCOL: http
|
||||
GITEA__server__HTTP_PORT: 3000
|
||||
GITEA__server__START_SSH_SERVER: "true"
|
||||
GITEA__server__SSH_PORT: 2222
|
||||
GITEA__server__SSH_LISTEN_PORT: 2222
|
||||
GITEA__mailer__ENABLED: "true"
|
||||
GITEA__mailer__PROTOCOL: smtp
|
||||
GITEA__mailer__SMTP_ADDR: mailpit
|
||||
GITEA__mailer__SMTP_PORT: 1025
|
||||
GITEA__service__DISABLE_REGISTRATION: "false"
|
||||
GITEA__service__REQUIRE_SIGNIN_VIEW: "false"
|
||||
GITEA__service__ENABLE_NOTIFY_MAIL: "true"
|
||||
GITEA__service__DEFAULT_EMAIL_NOTIFICATIONS: enabled
|
||||
GITEA__packages__ENABLED: "true"
|
||||
GITEA__actions__ENABLED: "true"
|
||||
GITEA__ui__THEMES: gitea-auto,gitea-light,gitea-dark,arc-green,edge-auto,edge-dark,edge-light,everforest-auto,everforest-dark,everforest-light,gruvbox-auto,gruvbox-dark,gruvbox-light,gruvbox-material-auto,gruvbox-material-dark,gruvbox-material-light,nord,palenight,soft-era,sonokai,sonokai-andromeda,sonokai-atlantis,sonokai-espresso,sonokai-maia,sonokai-shusia
|
||||
GITEA__ui__DEFAULT_THEME: edge-dark
|
||||
GITEA__ui__ENABLE_FEED: "true"
|
||||
ports:
|
||||
- "2222:2222"
|
||||
volumes:
|
||||
- ../.data/gitea/data:/data
|
||||
- ../.data/gitea/config:/etc/gitea
|
||||
- ./themes:/data/gitea/public/assets/css:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.gitea-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.gitea-web.middlewares=gitea-redirect-web-secure"
|
||||
- "traefik.http.routers.gitea-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.gitea-web.entrypoints=web"
|
||||
- "traefik.http.routers.gitea-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.gitea-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.gitea-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.gitea-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.gitea-web-secure.loadbalancer.server.port=3000"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
runner:
|
||||
image: gitea/act_runner:latest
|
||||
container_name: gitea_runner
|
||||
privileged: true
|
||||
command: ["act_runner", "daemon", "--config", "/data/config.yaml"]
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
GITEA_INSTANCE_URL: https://${TRAEFIK_HOST}
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
||||
GITEA_RUNNER_NAME: docker-runner
|
||||
GITEA_RUNNER_LABELS: ubuntu-latest:docker://catthehacker/ubuntu:act-latest,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04
|
||||
DOCKER_HOST: unix:///var/run/docker.sock
|
||||
volumes:
|
||||
- ../.data/gitea/runner:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./runner-config.yaml:/data/config.yaml:ro
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
restart: always
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: gitea_db
|
||||
environment:
|
||||
POSTGRES_DB: gitea
|
||||
POSTGRES_USER: gitea
|
||||
POSTGRES_PASSWORD: gitea
|
||||
volumes:
|
||||
- ../.data/gitea/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
32
gitea/runner-config.yaml
Normal file
32
gitea/runner-config.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: .runner
|
||||
capacity: 1
|
||||
envs: {}
|
||||
env_file: .env
|
||||
timeout: 3h
|
||||
insecure: false
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
labels: []
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: ""
|
||||
host: ""
|
||||
port: 0
|
||||
external_server: ""
|
||||
|
||||
container:
|
||||
network: ""
|
||||
privileged: false
|
||||
options: "-v /var/run/docker.sock:/var/run/docker.sock"
|
||||
workdir_parent: ""
|
||||
valid_volumes: []
|
||||
docker_host: ""
|
||||
force_pull: false
|
||||
|
||||
host:
|
||||
workdir_parent: ""
|
||||
1
gitea/themes/theme-edge-auto.css
Normal file
1
gitea/themes/theme-edge-auto.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-edge-dark.css
Normal file
1
gitea/themes/theme-edge-dark.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-edge-light.css
Normal file
1
gitea/themes/theme-edge-light.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-everforest-auto.css
Normal file
1
gitea/themes/theme-everforest-auto.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-everforest-dark.css
Normal file
1
gitea/themes/theme-everforest-dark.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-everforest-light.css
Normal file
1
gitea/themes/theme-everforest-light.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-auto.css
Normal file
1
gitea/themes/theme-gruvbox-auto.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-dark.css
Normal file
1
gitea/themes/theme-gruvbox-dark.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-light.css
Normal file
1
gitea/themes/theme-gruvbox-light.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-material-auto.css
Normal file
1
gitea/themes/theme-gruvbox-material-auto.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-material-dark.css
Normal file
1
gitea/themes/theme-gruvbox-material-dark.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-gruvbox-material-light.css
Normal file
1
gitea/themes/theme-gruvbox-material-light.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-nord.css
Normal file
1
gitea/themes/theme-nord.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-palenight.css
Normal file
1
gitea/themes/theme-palenight.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-soft-era.css
Normal file
1
gitea/themes/theme-soft-era.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai-andromeda.css
Normal file
1
gitea/themes/theme-sonokai-andromeda.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai-atlantis.css
Normal file
1
gitea/themes/theme-sonokai-atlantis.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai-espresso.css
Normal file
1
gitea/themes/theme-sonokai-espresso.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai-maia.css
Normal file
1
gitea/themes/theme-sonokai-maia.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai-shusia.css
Normal file
1
gitea/themes/theme-sonokai-shusia.css
Normal file
File diff suppressed because one or more lines are too long
1
gitea/themes/theme-sonokai.css
Normal file
1
gitea/themes/theme-sonokai.css
Normal file
File diff suppressed because one or more lines are too long
84
immich/compose.yml
Normal file
84
immich/compose.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
services:
|
||||
immich:
|
||||
image: ghcr.io/immich-app/immich-server:release
|
||||
container_name: immich
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
DB_HOSTNAME: immich_db
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: immich
|
||||
DB_PASSWORD: immich
|
||||
DB_DATABASE_NAME: immich
|
||||
REDIS_HOSTNAME: immich_redis
|
||||
REDIS_PORT: 6379
|
||||
IMMICH_MACHINE_LEARNING_URL: http://immich_ml:3003
|
||||
volumes:
|
||||
- ../.data/immich/upload:/usr/src/app/upload
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.immich-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.immich-web.middlewares=immich-redirect-web-secure"
|
||||
- "traefik.http.routers.immich-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.immich-web.entrypoints=web"
|
||||
- "traefik.http.routers.immich-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.immich-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.immich-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.immich-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.immich-web-secure.loadbalancer.server.port=2283"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
ml:
|
||||
image: ghcr.io/immich-app/immich-machine-learning:release
|
||||
container_name: immich_ml
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
volumes:
|
||||
- ../.data/immich/model-cache:/cache
|
||||
restart: always
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: immich_redis
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
|
||||
container_name: immich_db
|
||||
environment:
|
||||
POSTGRES_DB: immich
|
||||
POSTGRES_USER: immich
|
||||
POSTGRES_PASSWORD: immich
|
||||
POSTGRES_INITDB_ARGS: --data-checksums
|
||||
volumes:
|
||||
- ../.data/immich/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
59
joplin/compose.yml
Normal file
59
joplin/compose.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
services:
|
||||
joplin:
|
||||
image: joplin/server:latest
|
||||
container_name: joplin
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
APP_PORT: 22300
|
||||
APP_BASE_URL: https://${TRAEFIK_HOST}
|
||||
DB_CLIENT: pg
|
||||
POSTGRES_HOST: joplin_db
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DATABASE: joplin
|
||||
POSTGRES_USER: joplin
|
||||
POSTGRES_PASSWORD: joplin
|
||||
MAILER_ENABLED: 1
|
||||
MAILER_HOST: mailpit
|
||||
MAILER_PORT: 1025
|
||||
MAILER_SECURE: 0
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.joplin-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.joplin-web.middlewares=joplin-redirect-web-secure"
|
||||
- "traefik.http.routers.joplin-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.joplin-web.entrypoints=web"
|
||||
- "traefik.http.routers.joplin-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.joplin-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.joplin-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.joplin-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.joplin-web-secure.loadbalancer.server.port=22300"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: joplin_db
|
||||
environment:
|
||||
POSTGRES_DB: joplin
|
||||
POSTGRES_USER: joplin
|
||||
POSTGRES_PASSWORD: joplin
|
||||
volumes:
|
||||
- ../.data/joplin/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
29
mailpit/compose.yml
Normal file
29
mailpit/compose.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
services:
|
||||
mailpit:
|
||||
image: axllent/mailpit:latest
|
||||
container_name: mailpit
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
MP_SMTP_AUTH_ACCEPT_ANY: 1
|
||||
MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
||||
MP_MAX_MESSAGES: 5000
|
||||
MP_SMTP_RELAY_ALL: "true"
|
||||
MP_SMTP_RELAY_HOST: ${SMTP_RELAY_HOST}
|
||||
MP_SMTP_RELAY_PORT: ${SMTP_RELAY_PORT}
|
||||
MP_SMTP_RELAY_USERNAME: ${SMTP_RELAY_USERNAME}
|
||||
MP_SMTP_RELAY_PASSWORD: ${SMTP_RELAY_PASSWORD}
|
||||
MP_SMTP_RELAY_AUTH: plain
|
||||
MP_SMTP_RELAY_TLS: "true"
|
||||
MP_UI_BIND_ADDR: 0.0.0.0:0
|
||||
volumes:
|
||||
- ../.data/mailpit:/data
|
||||
restart: always
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
68
mattermost/compose.yml
Normal file
68
mattermost/compose.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
services:
|
||||
mattermost:
|
||||
image: mattermost/mattermost-team-edition:latest
|
||||
container_name: mattermost
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
pids_limit: 200
|
||||
tmpfs:
|
||||
- /tmp
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
MM_SQLSETTINGS_DRIVERNAME: postgres
|
||||
MM_SQLSETTINGS_DATASOURCE: postgres://mattermost:mattermost@mattermost_db:5432/mattermost?sslmode=disable&connect_timeout=10
|
||||
MM_BLEVESETTINGS_INDEXDIR: /mattermost/bleve-indexes
|
||||
MM_SERVICESETTINGS_SITEURL: https://${TRAEFIK_HOST}
|
||||
MM_SERVICESETTINGS_ENABLELOCALMODE: "true"
|
||||
MM_EMAILSETTINGS_ENABLESMTPAUTH: "false"
|
||||
MM_EMAILSETTINGS_SMTPSERVER: mailpit
|
||||
MM_EMAILSETTINGS_SMTPPORT: "1025"
|
||||
MM_EMAILSETTINGS_CONNECTIONSECURITY: ""
|
||||
MM_EMAILSETTINGS_FEEDBACKNAME: Mattermost
|
||||
volumes:
|
||||
- ../.data/mattermost/config:/mattermost/config:rw
|
||||
- ../.data/mattermost/data:/mattermost/data:rw
|
||||
- ../.data/mattermost/plugins:/mattermost/plugins:rw
|
||||
- ../.data/mattermost/client-plugins:/mattermost/client/plugins:rw
|
||||
- ../.data/mattermost/bleve:/mattermost/bleve-indexes:rw
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.mattermost-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.mattermost-web.middlewares=mattermost-redirect-web-secure"
|
||||
- "traefik.http.routers.mattermost-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.mattermost-web.entrypoints=web"
|
||||
- "traefik.http.routers.mattermost-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.mattermost-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.mattermost-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.mattermost-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.mattermost-web-secure.loadbalancer.server.port=8065"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: mattermost_db
|
||||
environment:
|
||||
POSTGRES_DB: mattermost
|
||||
POSTGRES_USER: mattermost
|
||||
POSTGRES_PASSWORD: mattermost
|
||||
volumes:
|
||||
- ../.data/mattermost/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
122
sexy/compose.yml
Normal file
122
sexy/compose.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
services:
|
||||
sexy:
|
||||
image: dev.pivoine.art/valknar/sexy:latest
|
||||
container_name: sexy
|
||||
user: node
|
||||
working_dir: /home/node/app/packages/frontend
|
||||
command: ["node", "build/index.js"]
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
NODE_ENV: production
|
||||
PUBLIC_API_URL: https://${TRAEFIK_HOST}/api
|
||||
PUBLIC_URL: https://${TRAEFIK_HOST}
|
||||
PUBLIC_UMAMI_ID: ""
|
||||
volumes:
|
||||
- ../.data/sexy/bundle:/home/node/app/packages/bundle
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.sexy-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.sexy-web.middlewares=sexy-redirect-web-secure"
|
||||
- "traefik.http.routers.sexy-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.sexy-web.entrypoints=web"
|
||||
- "traefik.http.routers.sexy-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.sexy-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.sexy-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.middlewares.sexy-compress.compress=true"
|
||||
- "traefik.http.routers.sexy-web-secure.middlewares=sexy-compress"
|
||||
- "traefik.http.services.sexy-web-secure.loadbalancer.server.port=3000"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
directus:
|
||||
image: directus/directus:11.12.0
|
||||
container_name: sexy_directus
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
SECRET: ${DIRECTUS_SECRET}
|
||||
DB_CLIENT: pg
|
||||
DB_HOST: sexy_db
|
||||
DB_PORT: 5432
|
||||
DB_DATABASE: directus
|
||||
DB_USER: directus
|
||||
DB_PASSWORD: directus
|
||||
CACHE_ENABLED: "true"
|
||||
CACHE_AUTO_PURGE: "true"
|
||||
CACHE_STORE: redis
|
||||
REDIS: redis://sexy_redis:6379
|
||||
WEBSOCKETS_ENABLED: "true"
|
||||
PUBLIC_URL: https://${TRAEFIK_HOST}/api
|
||||
CORS_ENABLED: "true"
|
||||
CORS_ORIGIN: https://${TRAEFIK_HOST}
|
||||
SESSION_COOKIE_SECURE: "true"
|
||||
SESSION_COOKIE_SAME_SITE: strict
|
||||
SESSION_COOKIE_DOMAIN: ${TRAEFIK_HOST}
|
||||
EXTENSIONS_PATH: ./extensions
|
||||
EXTENSIONS_AUTO_RELOAD: "false"
|
||||
CONTENT_SECURITY_POLICY_DIRECTIVES__FRAME_SRC: https://${TRAEFIK_HOST}
|
||||
EMAIL_TRANSPORT: smtp
|
||||
EMAIL_SMTP_HOST: mailpit
|
||||
EMAIL_SMTP_PORT: 1025
|
||||
USER_REGISTER_URL_ALLOW_LIST: https://${TRAEFIK_HOST}/signup/verify
|
||||
PASSWORD_RESET_URL_ALLOW_LIST: https://${TRAEFIK_HOST}/password/reset
|
||||
volumes:
|
||||
- ../.data/sexy/uploads:/directus/uploads
|
||||
- ../.data/sexy/bundle:/directus/extensions/sexy.pivoine.art
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.sexy-directus-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.sexy-directus-web.middlewares=sexy-directus-redirect-web-secure"
|
||||
- "traefik.http.routers.sexy-directus-web.rule=Host(`${TRAEFIK_HOST}`) && PathPrefix(`/api`)"
|
||||
- "traefik.http.routers.sexy-directus-web.entrypoints=web"
|
||||
- "traefik.http.routers.sexy-directus-web-secure.rule=Host(`${TRAEFIK_HOST}`) && PathPrefix(`/api`)"
|
||||
- "traefik.http.routers.sexy-directus-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.sexy-directus-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.middlewares.sexy-directus-compress.compress=true"
|
||||
- "traefik.http.middlewares.sexy-directus-strip.stripprefix.prefixes=/api"
|
||||
- "traefik.http.routers.sexy-directus-web-secure.middlewares=sexy-directus-strip,sexy-directus-compress"
|
||||
- "traefik.http.services.sexy-directus-web-secure.loadbalancer.server.port=8055"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: sexy_redis
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: sexy_db
|
||||
environment:
|
||||
POSTGRES_DB: directus
|
||||
POSTGRES_USER: directus
|
||||
POSTGRES_PASSWORD: directus
|
||||
volumes:
|
||||
- ../.data/sexy/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
48
traefik/compose.yml
Normal file
48
traefik/compose.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
container_name: traefik
|
||||
command:
|
||||
- "--api.dashboard=false"
|
||||
- "--ping=true"
|
||||
- "--log.level=INFO"
|
||||
- "--accesslog=true"
|
||||
- "--global.sendAnonymousUsage=false"
|
||||
- "--global.checkNewVersion=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--providers.docker.network=${NETWORK_NAME}"
|
||||
- "--providers.file.directory=/etc/traefik/dynamic"
|
||||
- "--providers.file.watch=true"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.web-secure.address=:443"
|
||||
- "--entrypoints.web.http.redirections.entryPoint.to=web-secure"
|
||||
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
|
||||
- "--entrypoints.web.http.redirections.entryPoint.permanent=true"
|
||||
- "--entrypoints.web-secure.http.middlewares=security-headers@file"
|
||||
- "--certificatesresolvers.resolver.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.resolver.acme.email=${ACME_EMAIL}"
|
||||
- "--certificatesresolvers.resolver.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ../.data/traefik/letsencrypt:/letsencrypt
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./dynamic:/etc/traefik/dynamic:ro
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "traefik", "healthcheck", "--ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
43
traefik/dynamic/security.yaml
Normal file
43
traefik/dynamic/security.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
tls:
|
||||
options:
|
||||
default:
|
||||
minVersion: VersionTLS12
|
||||
cipherSuites:
|
||||
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
|
||||
- TLS_AES_128_GCM_SHA256
|
||||
- TLS_AES_256_GCM_SHA384
|
||||
- TLS_CHACHA20_POLY1305_SHA256
|
||||
curvePreferences:
|
||||
- CurveP521
|
||||
- CurveP384
|
||||
sniStrict: true
|
||||
|
||||
http:
|
||||
middlewares:
|
||||
security-headers:
|
||||
headers:
|
||||
stsSeconds: 31536000
|
||||
stsIncludeSubdomains: true
|
||||
stsPreload: true
|
||||
forceSTSHeader: true
|
||||
customFrameOptionsValue: "SAMEORIGIN"
|
||||
browserXssFilter: true
|
||||
contentTypeNosniff: true
|
||||
referrerPolicy: "strict-origin-when-cross-origin"
|
||||
customResponseHeaders:
|
||||
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
|
||||
Permissions-Policy: "camera=(), microphone=(), geolocation=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()"
|
||||
X-Content-Type-Options: "nosniff"
|
||||
X-Frame-Options: "SAMEORIGIN"
|
||||
rate-limit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 50
|
||||
period: 1s
|
||||
api-rate-limit:
|
||||
rateLimit:
|
||||
average: 30
|
||||
burst: 15
|
||||
period: 1s
|
||||
55
umami/compose.yml
Normal file
55
umami/compose.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
services:
|
||||
umami:
|
||||
image: ghcr.io/umami-software/umami:latest
|
||||
container_name: umami
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
DATABASE_URL: postgresql://umami:umami@db:5432/umami
|
||||
APP_SECRET: ${APP_SECRET}
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
init: true
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.umami-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.umami-web.middlewares=umami-redirect-web-secure"
|
||||
- "traefik.http.routers.umami-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.umami-web.entrypoints=web"
|
||||
- "traefik.http.routers.umami-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.umami-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.umami-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.umami-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.umami-web-secure.loadbalancer.server.port=3000"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
db:
|
||||
image: postgres:15-alpine
|
||||
container_name: umami_db
|
||||
environment:
|
||||
POSTGRES_DB: umami
|
||||
POSTGRES_USER: umami
|
||||
POSTGRES_PASSWORD: umami
|
||||
volumes:
|
||||
- ../.data/umami/db:/var/lib/postgresql/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
38
vaultwarden/compose.yml
Normal file
38
vaultwarden/compose.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
services:
|
||||
vaultwarden:
|
||||
image: vaultwarden/server:latest
|
||||
container_name: vaultwarden
|
||||
environment:
|
||||
TZ: ${TIMEZONE:-Europe/Amsterdam}
|
||||
DOMAIN: https://${TRAEFIK_HOST}
|
||||
WEBSOCKET_ENABLED: "true"
|
||||
SIGNUPS_ALLOWED: "true"
|
||||
INVITATIONS_ALLOWED: "true"
|
||||
SHOW_PASSWORD_HINT: "false"
|
||||
SMTP_HOST: mailpit
|
||||
SMTP_FROM_NAME: Vaultwarden
|
||||
SMTP_SECURITY: off
|
||||
SMTP_PORT: 1025
|
||||
volumes:
|
||||
- ../.data/vaultwarden:/data
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.vaultwarden-redirect-web-secure.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.vaultwarden-web.middlewares=vaultwarden-redirect-web-secure"
|
||||
- "traefik.http.routers.vaultwarden-web.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.vaultwarden-web.entrypoints=web"
|
||||
- "traefik.http.routers.vaultwarden-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
|
||||
- "traefik.http.routers.vaultwarden-web-secure.tls.certresolver=resolver"
|
||||
- "traefik.http.routers.vaultwarden-web-secure.entrypoints=web-secure"
|
||||
- "traefik.http.routers.vaultwarden-web-secure.middlewares=security-headers@file"
|
||||
- "traefik.http.services.vaultwarden-web-secure.loadbalancer.server.port=80"
|
||||
- "traefik.docker.network=${NETWORK_NAME}"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
networks:
|
||||
- compose_network
|
||||
networks:
|
||||
compose_network:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
22
watchtower/compose.yml
Normal file
22
watchtower/compose.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
services:
|
||||
watchtower:
|
||||
image: containrrr/watchtower:latest
|
||||
container_name: watchtower
|
||||
environment:
|
||||
DOCKER_API_VERSION: "1.44"
|
||||
WATCHTOWER_POLL_INTERVAL: 300
|
||||
WATCHTOWER_LABEL_ENABLE: "true"
|
||||
WATCHTOWER_CLEANUP: "true"
|
||||
WATCHTOWER_INCLUDE_STOPPED: "false"
|
||||
WATCHTOWER_INCLUDE_RESTARTING: "true"
|
||||
WATCHTOWER_RUN_ONCE: "false"
|
||||
WATCHTOWER_NOTIFICATIONS: ${NOTIFICATIONS:-}
|
||||
WATCHTOWER_NOTIFICATION_URL: ${NOTIFICATION_URL:-}
|
||||
WATCHTOWER_LOG_LEVEL: info
|
||||
WATCHTOWER_ROLLING_RESTART: "false"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
restart: always
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
Reference in New Issue
Block a user