103 lines
3.7 KiB
YAML
103 lines
3.7 KiB
YAML
services:
|
|
# MySQL Database for Semaphore
|
|
mysql:
|
|
image: mysql:8.0
|
|
container_name: semaphore-mysql
|
|
restart: unless-stopped
|
|
networks:
|
|
- semaphore-internal
|
|
environment:
|
|
- TZ=Europe/Berlin
|
|
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-semaphore_root}
|
|
- MYSQL_DATABASE=${MYSQL_DATABASE:-semaphore}
|
|
- MYSQL_USER=${MYSQL_USER:-semaphore}
|
|
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-semaphore}
|
|
volumes:
|
|
- semaphore-mysql-data:/var/lib/mysql
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
healthcheck:
|
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-semaphore_root}"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
command: >
|
|
--default-authentication-plugin=mysql_native_password
|
|
--character-set-server=utf8mb4
|
|
--collation-server=utf8mb4_unicode_ci
|
|
|
|
# Semaphore CI/CD Platform
|
|
semaphore:
|
|
image: semaphoreui/semaphore:latest
|
|
container_name: semaphore
|
|
restart: unless-stopped
|
|
depends_on:
|
|
mysql:
|
|
condition: service_healthy
|
|
networks:
|
|
- semaphore-internal
|
|
ports:
|
|
# Only bind to localhost, not external interfaces
|
|
# Default port 3001 to avoid conflict with Gitea (port 3000)
|
|
- "127.0.0.1:${SEMAPHORE_PORT:-3001}:3000"
|
|
labels:
|
|
# Traefik configuration
|
|
- "traefik.enable=true"
|
|
# HTTP Router (redirects to HTTPS)
|
|
- "traefik.http.routers.semaphore.rule=Host(`semaphore.michaelschiemer.de`)"
|
|
- "traefik.http.routers.semaphore.entrypoints=web"
|
|
- "traefik.http.routers.semaphore.middlewares=redirect-to-https"
|
|
# HTTPS Router
|
|
- "traefik.http.routers.semaphore-secure.rule=Host(`semaphore.michaelschiemer.de`)"
|
|
- "traefik.http.routers.semaphore-secure.entrypoints=websecure"
|
|
- "traefik.http.routers.semaphore-secure.tls=true"
|
|
- "traefik.http.routers.semaphore-secure.tls.certresolver=letsencrypt"
|
|
- "traefik.http.routers.semaphore-secure.service=semaphore"
|
|
# Service definition (use localhost port binding)
|
|
# Note: Dynamic config in traefik/dynamic/semaphore.yml takes precedence
|
|
environment:
|
|
- TZ=Europe/Berlin
|
|
# Database Configuration
|
|
- SEMAPHORE_DB_DIALECT=mysql
|
|
- SEMAPHORE_DB_HOST=mysql
|
|
- SEMAPHORE_DB_PORT=3306
|
|
- SEMAPHORE_DB=${MYSQL_DATABASE:-semaphore}
|
|
- SEMAPHORE_DB_USER=${MYSQL_USER:-semaphore}
|
|
- SEMAPHORE_DB_PASS=${MYSQL_PASSWORD:-semaphore}
|
|
# Admin Configuration
|
|
- SEMAPHORE_ADMIN=${SEMAPHORE_ADMIN:-admin}
|
|
- SEMAPHORE_ADMIN_NAME=${SEMAPHORE_ADMIN_NAME:-Administrator}
|
|
- SEMAPHORE_ADMIN_EMAIL=${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}
|
|
- SEMAPHORE_ADMIN_PASSWORD=${SEMAPHORE_ADMIN_PASSWORD:-admin}
|
|
# Playbook Path
|
|
- SEMAPHORE_PLAYBOOK_PATH=${SEMAPHORE_PLAYBOOK_PATH:-/tmp/semaphore}
|
|
# Encryption Key (generate with: head -c32 /dev/urandom | base64)
|
|
- SEMAPHORE_ACCESS_KEY_ENCRYPTION=${SEMAPHORE_ACCESS_KEY_ENCRYPTION:-change-me-in-production}
|
|
# Optional: LDAP Configuration (disabled by default)
|
|
- SEMAPHORE_LDAP_ENABLED=${SEMAPHORE_LDAP_ENABLED:-false}
|
|
# Optional: Webhook Configuration
|
|
- SEMAPHORE_WEBHOOK_URL=${SEMAPHORE_WEBHOOK_URL:-}
|
|
volumes:
|
|
- semaphore-data:/etc/semaphore
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
volumes:
|
|
semaphore-mysql-data:
|
|
name: semaphore-mysql-data
|
|
semaphore-data:
|
|
name: semaphore-data
|
|
|
|
networks:
|
|
semaphore-internal:
|
|
name: semaphore-internal
|
|
driver: bridge
|
|
|