fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
48
deployment/legacy/stacks/stacks/semaphore/.env.example
Normal file
48
deployment/legacy/stacks/stacks/semaphore/.env.example
Normal file
@@ -0,0 +1,48 @@
|
||||
# Semaphore CI Stack - Environment Configuration
|
||||
# Copy this file to .env and adjust values as needed
|
||||
|
||||
# ============================================
|
||||
# MySQL Database Configuration
|
||||
# ============================================
|
||||
MYSQL_ROOT_PASSWORD=semaphore_root
|
||||
MYSQL_DATABASE=semaphore
|
||||
MYSQL_USER=semaphore
|
||||
MYSQL_PASSWORD=semaphore
|
||||
|
||||
# ============================================
|
||||
# Semaphore Configuration
|
||||
# ============================================
|
||||
|
||||
# Port binding (default: 3000)
|
||||
# Only accessible via localhost (127.0.0.1)
|
||||
SEMAPHORE_PORT=3000
|
||||
|
||||
# Admin User Configuration
|
||||
SEMAPHORE_ADMIN=admin
|
||||
SEMAPHORE_ADMIN_NAME=Administrator
|
||||
SEMAPHORE_ADMIN_EMAIL=admin@localhost
|
||||
SEMAPHORE_ADMIN_PASSWORD=admin
|
||||
|
||||
# Playbook Storage Path (inside container)
|
||||
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
|
||||
|
||||
# Access Key Encryption
|
||||
# Generate with: head -c32 /dev/urandom | base64
|
||||
# IMPORTANT: Change this in production!
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
|
||||
|
||||
# ============================================
|
||||
# Optional: LDAP Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_LDAP_ENABLED=false
|
||||
# SEMAPHORE_LDAP_HOST=ldap.example.com
|
||||
# SEMAPHORE_LDAP_PORT=389
|
||||
# SEMAPHORE_LDAP_DN=cn=admin,dc=example,dc=com
|
||||
# SEMAPHORE_LDAP_PASSWORD=ldap_password
|
||||
# SEMAPHORE_LDAP_BASE_DN=dc=example,dc=com
|
||||
# SEMAPHORE_LDAP_USER_FILTER=(uid=%s)
|
||||
|
||||
# ============================================
|
||||
# Optional: Webhook Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
|
||||
201
deployment/legacy/stacks/stacks/semaphore/QUICKSTART.md
Normal file
201
deployment/legacy/stacks/stacks/semaphore/QUICKSTART.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# ?? Quick Start: Semaphore mit Repository verbinden
|
||||
|
||||
Kurze Schritt-f?r-Schritt-Anleitung, um Semaphore mit deinem Git-Repository zu verbinden.
|
||||
|
||||
## Schritt 1: Semaphore starten
|
||||
|
||||
```bash
|
||||
cd deployment/stacks/semaphore
|
||||
cp env.example .env
|
||||
```
|
||||
|
||||
**WICHTIG**: Generiere einen Encryption Key:
|
||||
```bash
|
||||
head -c32 /dev/urandom | base64
|
||||
```
|
||||
Kopiere den Key und setze ihn in `.env`:
|
||||
```env
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=<dein-generierter-key>
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Schritt 2: Semaphore ?ffnen
|
||||
|
||||
?ffne im Browser: **http://localhost:9300**
|
||||
|
||||
**Login**:
|
||||
- Username: `admin`
|
||||
- Password: `admin`
|
||||
|
||||
## Schritt 3: Projekt erstellen
|
||||
|
||||
1. Klicke auf **"New Project"** oder **"Create Project"**
|
||||
2. Name: **"michaelschiemer"**
|
||||
3. Klicke auf **"Create"**
|
||||
|
||||
## Schritt 4: Inventory erstellen (Hosts definieren)
|
||||
|
||||
### 4.1 Inventory anlegen
|
||||
|
||||
1. Gehe zu **Inventories** ? **New Inventory**
|
||||
2. Name: **"Production Hosts"**
|
||||
3. Klicke auf **"Create"**
|
||||
|
||||
### 4.2 Host hinzuf?gen
|
||||
|
||||
1. Klicke auf dein Inventory ? **"Add Host"**
|
||||
2. F?lle aus:
|
||||
|
||||
```
|
||||
Name: production
|
||||
Address: 94.16.110.151
|
||||
SSH Username: deploy
|
||||
SSH Port: 22
|
||||
```
|
||||
|
||||
3. Klicke auf **"Save"**
|
||||
|
||||
### 4.3 SSH-Key hinzuf?gen
|
||||
|
||||
1. Gehe zu **Keys** (in der Seitenleiste)
|
||||
2. Klicke auf **"New Key"**
|
||||
3. Name: **"Deployment Key"**
|
||||
4. F?ge deinen SSH Private Key ein (aus `~/.ssh/production`):
|
||||
```bash
|
||||
cat ~/.ssh/production
|
||||
```
|
||||
5. Klicke auf **"Save"**
|
||||
6. Gehe zur?ck zu deinem Inventory und w?hle den Key bei deinem Host aus
|
||||
|
||||
## Schritt 5: Template erstellen (Playbook verwenden)
|
||||
|
||||
### 5.1 Template f?r CI Tests
|
||||
|
||||
1. Gehe zu **Templates** ? **New Template**
|
||||
2. **Name**: "Run CI Tests"
|
||||
3. **Inventory**: W?hle "Production Hosts"
|
||||
4. **Playbook Path**: `/tmp/semaphore/playbooks/ci-tests.yml`
|
||||
5. **Variables** (klicke auf "Variables"):
|
||||
```yaml
|
||||
repo_url: https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
repo_branch: main
|
||||
```
|
||||
6. Klicke auf **"Save"**
|
||||
|
||||
### 5.2 Template f?r Docker Build
|
||||
|
||||
1. **Templates** ? **New Template**
|
||||
2. **Name**: "Build Docker Image"
|
||||
3. **Inventory**: "Production Hosts"
|
||||
4. **Playbook Path**: `/tmp/semaphore/playbooks/docker-build.yml`
|
||||
5. **Variables**:
|
||||
```yaml
|
||||
repo_url: https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
repo_branch: main
|
||||
registry_url: registry.michaelschiemer.de
|
||||
registry_user: admin
|
||||
registry_password: <dein-registry-passwort>
|
||||
image_name: framework
|
||||
image_tag: latest
|
||||
```
|
||||
6. **Save**
|
||||
|
||||
### 5.3 Template f?r Staging Deployment
|
||||
|
||||
1. **Templates** ? **New Template**
|
||||
2. **Name**: "Deploy to Staging"
|
||||
3. **Inventory**: "Production Hosts"
|
||||
4. **Playbook Path**: `/tmp/semaphore/playbooks/deploy-staging.yml`
|
||||
5. **Variables**:
|
||||
```yaml
|
||||
registry_url: registry.michaelschiemer.de
|
||||
registry_user: admin
|
||||
registry_password: <dein-registry-passwort>
|
||||
image_name: framework
|
||||
image_tag: latest
|
||||
```
|
||||
6. **Save**
|
||||
|
||||
### 5.4 Template f?r Production Deployment
|
||||
|
||||
1. **Templates** ? **New Template**
|
||||
2. **Name**: "Deploy to Production"
|
||||
3. **Inventory**: "Production Hosts"
|
||||
4. **Playbook Path**: `/tmp/semaphore/playbooks/deploy-production.yml`
|
||||
5. **Variables**:
|
||||
```yaml
|
||||
registry_url: registry.michaelschiemer.de
|
||||
registry_user: admin
|
||||
registry_password: <dein-registry-passwort>
|
||||
image_name: framework
|
||||
image_tag: latest
|
||||
```
|
||||
6. **Save**
|
||||
|
||||
## Schritt 6: Task ausf?hren
|
||||
|
||||
1. Gehe zu **Templates**
|
||||
2. Klicke auf ein Template (z.B. "Run CI Tests")
|
||||
3. Klicke auf **"Run"**
|
||||
4. Beobachte die Ausf?hrung in Echtzeit
|
||||
|
||||
## ? Fertig!
|
||||
|
||||
Semaphore ist jetzt mit deinem Repository verbunden! Du kannst:
|
||||
|
||||
- ? CI/CD-Tasks manuell starten
|
||||
- ? Playbooks aus dem Repository verwenden
|
||||
- ? Deployments auf deine Server ausf?hren
|
||||
|
||||
## ?? Verf?gbare Playbooks
|
||||
|
||||
Die folgenden Playbooks sind bereits im Repository und k?nnen in Semaphore verwendet werden:
|
||||
|
||||
1. **`/tmp/semaphore/playbooks/ci-tests.yml`** - PHP Tests & Quality Checks
|
||||
2. **`/tmp/semaphore/playbooks/docker-build.yml`** - Docker Image Build & Push
|
||||
3. **`/tmp/semaphore/playbooks/deploy-staging.yml`** - Staging Deployment
|
||||
4. **`/tmp/semaphore/playbooks/deploy-production.yml`** - Production Deployment
|
||||
|
||||
## ?? Vorhandene Ansible-Playbooks
|
||||
|
||||
Die vorhandenen Ansible-Playbooks aus `deployment/ansible/playbooks/` sind auch verf?gbar unter:
|
||||
- `/tmp/semaphore/repo-playbooks/`
|
||||
|
||||
Zum Beispiel:
|
||||
- `/tmp/semaphore/repo-playbooks/deploy-update.yml`
|
||||
- `/tmp/semaphore/repo-playbooks/rollback.yml`
|
||||
|
||||
## ?? Tipps
|
||||
|
||||
### Docker Socket f?r Build-Tasks
|
||||
|
||||
Falls Docker-Build-Tasks ausgef?hrt werden sollen, f?ge den Docker Socket hinzu:
|
||||
|
||||
In `docker-compose.yml` bei Semaphore-Service:
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
```
|
||||
|
||||
Dann Semaphore neu starten:
|
||||
```bash
|
||||
docker compose restart semaphore
|
||||
```
|
||||
|
||||
### Git-Integration
|
||||
|
||||
Die Playbooks k?nnen direkt auf das Git-Repository zugreifen (HTTPS). F?r private Repositories oder SSH-Zugriff:
|
||||
|
||||
1. Erstelle einen SSH-Key f?r Git in Semaphore (Keys ? New Key)
|
||||
2. F?ge den Public Key zu deinem Git-Repository hinzu
|
||||
3. Verwende SSH-URL in Playbook-Variablen:
|
||||
```yaml
|
||||
repo_url: git@git.michaelschiemer.de:michael/michaelschiemer.git
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Hilfe**: Weitere Details in `SETUP_REPOSITORY.md` und `README.md`
|
||||
576
deployment/legacy/stacks/stacks/semaphore/README.md
Normal file
576
deployment/legacy/stacks/stacks/semaphore/README.md
Normal file
@@ -0,0 +1,576 @@
|
||||
# Semaphore CI Stack - Lokale Entwicklung
|
||||
|
||||
## Übersicht
|
||||
|
||||
Selbst-gehostete Semaphore CI/CD-Plattform für lokale Entwicklung, die es ermöglicht, CI/CD-Pipelines und Ansible-Playbooks lokal zu testen und auszuführen, ohne Abhängigkeit von externen CI-Services.
|
||||
|
||||
**Features**:
|
||||
- **Selbst-gehostet**: Läuft vollständig lokal auf dem Entwicklungsrechner
|
||||
- **Lokal isoliert**: NUR über localhost (127.0.0.1) erreichbar - KEIN externer Zugriff aus Sicherheitsgründen!
|
||||
- **MySQL-Backend**: Persistente Datenbank für Projekte, Tasks und Templates
|
||||
- **Web-UI**: Intuitive Benutzeroberfläche für Pipeline-Management (nur lokal)
|
||||
- **Ansible-Integration**: Native Unterstützung für Ansible-Playbooks
|
||||
- **Docker-basiert**: Einfaches Setup und Wartung
|
||||
|
||||
**Einsatzzweck**:
|
||||
- Lokales Testen von CI/CD-Pipelines
|
||||
- Entwicklung und Test von Ansible-Playbooks
|
||||
- Experimentieren mit Deployment-Workflows
|
||||
- Keine Abhängigkeit von externen CI-Services
|
||||
|
||||
## Services
|
||||
|
||||
- **mysql** - MySQL 8.0 Datenbank für Semaphore-Daten
|
||||
- **semaphore** - Semaphore CI/CD Web-UI und API
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Docker und Docker Compose installiert
|
||||
- Port 9300 auf localhost frei verfügbar (3000 wird von Gitea verwendet)
|
||||
- Ausreichend Speicherplatz für Docker Volumes (~500MB initial)
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
```
|
||||
semaphore/
|
||||
├── docker-compose.yml # Service-Definitionen
|
||||
├── env.example # Environment-Variablen Template
|
||||
├── .env # Environment-Konfiguration (aus env.example erstellen)
|
||||
└── README.md # Diese Datei
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Environment-Datei erstellen
|
||||
|
||||
```bash
|
||||
cd deployment/stacks/semaphore
|
||||
cp env.example .env
|
||||
```
|
||||
|
||||
### 2. Konfiguration anpassen (Optional)
|
||||
|
||||
Bearbeite `.env` und passe die Werte an:
|
||||
|
||||
```bash
|
||||
nano .env
|
||||
```
|
||||
|
||||
**Wichtig**: Generiere einen sicheren Encryption Key:
|
||||
```bash
|
||||
# Linux/WSL
|
||||
head -c32 /dev/urandom | base64
|
||||
|
||||
# Windows PowerShell
|
||||
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | % {[char]$_}) | ConvertTo-Base64
|
||||
```
|
||||
|
||||
Aktualisiere `SEMAPHORE_ACCESS_KEY_ENCRYPTION` in der `.env`-Datei.
|
||||
|
||||
### 3. Stack starten
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 4. Semaphore Web-UI öffnen
|
||||
|
||||
Öffne im Browser: **http://localhost:9300**
|
||||
|
||||
⚠️ **WICHTIG**: Semaphore ist NUR lokal zugänglich (127.0.0.1). Es gibt KEINEN externen Zugriff aus Sicherheitsgründen.
|
||||
|
||||
**Standard-Login**:
|
||||
- **Username**: `admin` (oder Wert aus `SEMAPHORE_ADMIN`)
|
||||
- **Password**: `admin` (oder Wert aus `SEMAPHORE_ADMIN_PASSWORD`)
|
||||
|
||||
### 5. Erste Schritte in Semaphore
|
||||
|
||||
1. **Projekt erstellen**: Klicke auf "New Project" und erstelle ein neues Projekt
|
||||
2. **Inventory anlegen**: Erstelle ein Inventory mit lokalen Hosts oder Docker-Containern
|
||||
3. **Template erstellen**: Erstelle ein Template mit einem Ansible-Playbook
|
||||
4. **Task ausführen**: Starte einen Task und beobachte die Ausführung
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Environment-Variablen (.env)
|
||||
|
||||
#### MySQL-Datenbank
|
||||
|
||||
```env
|
||||
MYSQL_ROOT_PASSWORD=semaphore_root
|
||||
MYSQL_DATABASE=semaphore
|
||||
MYSQL_USER=semaphore
|
||||
MYSQL_PASSWORD=semaphore
|
||||
```
|
||||
|
||||
#### Semaphore-Konfiguration
|
||||
|
||||
```env
|
||||
# Port-Binding (Standard: 9300)
|
||||
SEMAPHORE_PORT=9300
|
||||
|
||||
# Admin-Benutzer
|
||||
SEMAPHORE_ADMIN=admin
|
||||
SEMAPHORE_ADMIN_NAME=Administrator
|
||||
SEMAPHORE_ADMIN_EMAIL=admin@localhost
|
||||
SEMAPHORE_ADMIN_PASSWORD=admin
|
||||
|
||||
# Playbook-Pfad (im Container)
|
||||
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
|
||||
|
||||
# Encryption Key (WICHTIG: Für Produktion ändern!)
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
|
||||
```
|
||||
|
||||
#### Optionale Konfiguration
|
||||
|
||||
**LDAP-Integration** (Standard: deaktiviert):
|
||||
```env
|
||||
SEMAPHORE_LDAP_ENABLED=true
|
||||
SEMAPHORE_LDAP_HOST=ldap.example.com
|
||||
SEMAPHORE_LDAP_PORT=389
|
||||
SEMAPHORE_LDAP_DN=cn=admin,dc=example,dc=com
|
||||
SEMAPHORE_LDAP_PASSWORD=ldap_password
|
||||
SEMAPHORE_LDAP_BASE_DN=dc=example,dc=com
|
||||
SEMAPHORE_LDAP_USER_FILTER=(uid=%s)
|
||||
```
|
||||
|
||||
**Webhook-Integration**:
|
||||
```env
|
||||
SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
|
||||
```
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Stack starten
|
||||
|
||||
```bash
|
||||
# Services im Hintergrund starten
|
||||
docker compose up -d
|
||||
|
||||
# Logs anzeigen
|
||||
docker compose logs -f
|
||||
|
||||
# Nur Semaphore-Logs
|
||||
docker compose logs -f semaphore
|
||||
|
||||
# Nur MySQL-Logs
|
||||
docker compose logs -f mysql
|
||||
```
|
||||
|
||||
### Stack stoppen
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### Stack neu starten
|
||||
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### Status prüfen
|
||||
|
||||
```bash
|
||||
# Container-Status anzeigen
|
||||
docker compose ps
|
||||
|
||||
# Health-Check-Status
|
||||
docker compose ps --format "table {{.Name}}\t{{.Status}}"
|
||||
|
||||
# Semaphore-Health-Check manuell
|
||||
docker compose exec semaphore wget --no-verbose --spider http://localhost:3000/api/health
|
||||
```
|
||||
|
||||
### Datenbank-Backup
|
||||
|
||||
```bash
|
||||
# MySQL-Dump erstellen
|
||||
docker compose exec mysql mysqldump -u semaphore -psemaphore semaphore > semaphore-backup-$(date +%Y%m%d).sql
|
||||
|
||||
# Backup wiederherstellen
|
||||
docker compose exec -T mysql mysql -u semaphore -psemaphore semaphore < semaphore-backup-YYYYMMDD.sql
|
||||
```
|
||||
|
||||
### Daten löschen und neu starten
|
||||
|
||||
```bash
|
||||
# ⚠️ WARNUNG: Löscht alle Daten!
|
||||
docker compose down -v
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Erste Schritte mit Semaphore
|
||||
|
||||
### 1. Projekt erstellen
|
||||
|
||||
1. Öffne http://localhost:9300 im Browser
|
||||
2. Melde dich mit Admin-Credentials an
|
||||
3. Klicke auf "New Project"
|
||||
4. Gib einen Projektnamen ein (z.B. "My Project")
|
||||
5. Klicke auf "Create"
|
||||
|
||||
### 2. Inventory anlegen
|
||||
|
||||
Ein Inventory definiert die Hosts, auf denen Playbooks ausgeführt werden sollen.
|
||||
|
||||
**Option A: Lokaler Host**
|
||||
1. Gehe zu Projekt → Inventories → New Inventory
|
||||
2. Name: "Local Hosts"
|
||||
3. Hinzufügen von Host:
|
||||
- Name: `localhost`
|
||||
- Address: `127.0.0.1`
|
||||
- SSH Username: `your-username`
|
||||
- SSH Key: Füge deinen privaten SSH-Key hinzu
|
||||
|
||||
**Option B: Docker-Container**
|
||||
1. Erstelle ein Inventory mit Docker-Hosts
|
||||
2. Für Docker-in-Docker Support benötigst du zusätzliche Konfiguration
|
||||
|
||||
### 3. Template erstellen
|
||||
|
||||
Templates definieren welche Playbooks ausgeführt werden sollen.
|
||||
|
||||
1. Gehe zu Projekt → Templates → New Template
|
||||
2. Template-Name: "Hello World"
|
||||
3. Inventory: Wähle dein Inventory
|
||||
4. Playbook: Erstelle ein einfaches Playbook:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: all
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Print hello world
|
||||
debug:
|
||||
msg: "Hello from Semaphore CI!"
|
||||
```
|
||||
|
||||
5. Speichere das Template
|
||||
|
||||
### 4. Task ausführen
|
||||
|
||||
1. Gehe zu Templates
|
||||
2. Klicke auf dein Template
|
||||
3. Klicke auf "Run"
|
||||
4. Beobachte die Ausführung in Echtzeit
|
||||
|
||||
## Integration mit bestehenden Stacks
|
||||
|
||||
### Verwendung mit lokaler Docker-Registry
|
||||
|
||||
Semaphore kann Docker-Images aus der lokalen Registry verwenden:
|
||||
|
||||
**In Ansible-Playbooks**:
|
||||
```yaml
|
||||
- name: Pull image from local registry
|
||||
docker_image:
|
||||
name: registry.michaelschiemer.de/framework:latest
|
||||
source: pull
|
||||
register: image_result
|
||||
```
|
||||
|
||||
**Voraussetzung**: Der Semaphore-Container muss Zugriff auf den Docker-Socket oder die Registry haben.
|
||||
|
||||
### Verwendung mit bestehenden Ansible-Playbooks
|
||||
|
||||
1. Mounte deine Playbooks als Volume:
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/your/playbooks:/tmp/semaphore/playbooks:ro
|
||||
```
|
||||
|
||||
2. Oder kopiere Playbooks in den Container:
|
||||
```bash
|
||||
docker compose exec semaphore mkdir -p /tmp/semaphore/my-playbook
|
||||
docker cp my-playbook.yml semaphore:/tmp/semaphore/my-playbook/playbook.yml
|
||||
```
|
||||
|
||||
3. Verweise im Template auf den Playbook-Pfad
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port-Konflikt (Port 3000 vs 9300)
|
||||
|
||||
**Problem**: Port 3000 ist standardmäßig von Gitea belegt, daher verwendet Semaphore Port 9300.
|
||||
|
||||
**Lösung**: Wenn du einen anderen Port verwenden möchtest, setze `SEMAPHORE_PORT` in der `.env` Datei:
|
||||
```env
|
||||
SEMAPHORE_PORT=8080 # Oder ein anderer freier Port
|
||||
```
|
||||
|
||||
**Wichtig**: Der interne Container-Port bleibt immer 3000 - nur der externe Host-Port ändert sich.
|
||||
|
||||
### Semaphore startet nicht
|
||||
|
||||
**Prüfe Logs**:
|
||||
```bash
|
||||
docker compose logs semaphore
|
||||
```
|
||||
|
||||
**Häufige Ursachen**:
|
||||
- MySQL ist noch nicht bereit (warte auf Health-Check)
|
||||
- Port 9300 ist bereits belegt: `netstat -tuln | grep 9300` (oder auf Windows: `netstat -ano | findstr :9300`)
|
||||
- Falsche Datenbank-Credentials
|
||||
|
||||
**Lösung**:
|
||||
```bash
|
||||
# Prüfe MySQL-Status
|
||||
docker compose ps mysql
|
||||
|
||||
# Prüfe Semaphore-Logs für DB-Verbindungsfehler
|
||||
docker compose logs semaphore | grep -i database
|
||||
|
||||
# Restart wenn nötig
|
||||
docker compose restart semaphore
|
||||
```
|
||||
|
||||
### MySQL startet nicht
|
||||
|
||||
**Prüfe MySQL-Logs**:
|
||||
```bash
|
||||
docker compose logs mysql
|
||||
```
|
||||
|
||||
**Häufige Ursachen**:
|
||||
- Volume-Permissions-Probleme
|
||||
- Port-Konflikte (unwahrscheinlich, da kein Port-Mapping)
|
||||
|
||||
**Lösung**:
|
||||
```bash
|
||||
# Prüfe Volume
|
||||
docker volume inspect semaphore-mysql-data
|
||||
|
||||
# Cleanup und Neu-Start (⚠️ Datenverlust!)
|
||||
docker compose down -v
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Login funktioniert nicht
|
||||
|
||||
**Standard-Credentials**:
|
||||
- Username: `admin` (oder `SEMAPHORE_ADMIN` Wert)
|
||||
- Password: `admin` (oder `SEMAPHORE_ADMIN_PASSWORD` Wert)
|
||||
|
||||
**Admin-Passwort zurücksetzen**:
|
||||
1. Stoppe Semaphore: `docker compose stop semaphore`
|
||||
2. Setze `SEMAPHORE_ADMIN_PASSWORD` in `.env` auf neues Passwort
|
||||
3. Starte Semaphore: `docker compose up -d`
|
||||
|
||||
### Playbooks werden nicht gefunden
|
||||
|
||||
**Prüfe Playbook-Pfad**:
|
||||
```bash
|
||||
docker compose exec semaphore ls -la /tmp/semaphore
|
||||
```
|
||||
|
||||
**Lösung**:
|
||||
- Stelle sicher, dass `SEMAPHORE_PLAYBOOK_PATH` korrekt gesetzt ist
|
||||
- Prüfe, ob Playbooks im richtigen Pfad liegen
|
||||
- Stelle sicher, dass Datei-Berechtigungen korrekt sind
|
||||
|
||||
### Health-Check schlägt fehl
|
||||
|
||||
**Prüfe Health-Check**:
|
||||
```bash
|
||||
docker compose exec semaphore wget --no-verbose --spider http://localhost:3000/api/health
|
||||
```
|
||||
|
||||
**Lösung**:
|
||||
- Warte auf vollständigen Start (kann 1-2 Minuten dauern)
|
||||
- Prüfe Logs: `docker compose logs semaphore`
|
||||
- Restart wenn nötig: `docker compose restart semaphore`
|
||||
|
||||
## Sicherheit
|
||||
|
||||
### 🔒 Lokaler Zugriff (Nur localhost)
|
||||
|
||||
Semaphore ist absichtlich NUR lokal zugänglich aus Sicherheitsgründen:
|
||||
|
||||
- ✅ **Nur localhost-Zugriff**: Port 9300 gebunden an 127.0.0.1 (nicht 0.0.0.0)
|
||||
- ✅ **Keine externen Netzwerke**: Kein externer Zugriff möglich
|
||||
- ✅ **Keine Traefik-Integration**: Keine öffentliche Route konfiguriert
|
||||
- ✅ **Isoliertes Netzwerk**: Nur internes Docker-Netzwerk
|
||||
- ⚠️ **Standard-Passwörter**: Nur für lokale Entwicklung - ändern bei Bedarf
|
||||
|
||||
### ⚠️ KEINE Produktions-Nutzung über Internet!
|
||||
|
||||
**Semaphore sollte NICHT öffentlich zugänglich gemacht werden!**
|
||||
|
||||
Gründe:
|
||||
1. **Sicherheitsrisiko**: Semaphore hat Zugriff auf SSH-Keys und Deployment-Credentials
|
||||
2. **Privilegierter Zugriff**: Kann auf Produktions-Server zugreifen
|
||||
3. **Keine Multi-Factor-Authentication**: Standardmäßig keine 2FA
|
||||
4. **Exploits**: Selbst-gehostete Software kann Sicherheitslücken haben
|
||||
|
||||
### Für lokale Entwicklung (Empfohlen)
|
||||
|
||||
Wenn du Semaphore lokal nutzen willst:
|
||||
|
||||
1. **Starke Passwörter**: Ändere alle Passwörter in `.env`:
|
||||
```env
|
||||
SEMAPHORE_ADMIN_PASSWORD=<starkes-passwort>
|
||||
MYSQL_PASSWORD=<starkes-passwort>
|
||||
MYSQL_ROOT_PASSWORD=<starkes-passwort>
|
||||
```
|
||||
2. **Encryption Key**: Generiere einen sicheren Key:
|
||||
```bash
|
||||
head -c32 /dev/urandom | base64
|
||||
```
|
||||
Setze in `.env`: `SEMAPHORE_ACCESS_KEY_ENCRYPTION=<generierter-key>`
|
||||
3. **SSH-Keys**: Stelle sicher, dass SSH-Keys sicher gespeichert sind
|
||||
4. **Backup-Strategie**: Regelmäßige MySQL-Backups einrichten
|
||||
5. **Resource Limits**: Füge Memory/CPU-Limits hinzu (optional)
|
||||
|
||||
## Wartung
|
||||
|
||||
### Regelmäßige Aufgaben
|
||||
|
||||
**Wöchentlich**:
|
||||
- Logs auf Fehler prüfen: `docker compose logs --tail=100`
|
||||
- Disk-Space prüfen: `docker system df`
|
||||
- Backup erstellen (wenn wichtige Daten vorhanden)
|
||||
|
||||
**Monatlich**:
|
||||
- Images aktualisieren: `docker compose pull && docker compose up -d`
|
||||
- Alte Tasks in Semaphore aufräumen (über Web-UI)
|
||||
|
||||
### Updates
|
||||
|
||||
```bash
|
||||
# Aktuelle Images herunterladen
|
||||
docker compose pull
|
||||
|
||||
# Mit neuen Images neu starten
|
||||
docker compose up -d
|
||||
|
||||
# Logs prüfen
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Daten bereinigen
|
||||
|
||||
```bash
|
||||
# Alte Docker-Images löschen
|
||||
docker image prune -a
|
||||
|
||||
# Alte Volumes prüfen
|
||||
docker volume ls
|
||||
|
||||
# ⚠️ Vorsicht: Löscht alle Semaphore-Daten!
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## Backup und Wiederherstellung
|
||||
|
||||
### Backup erstellen
|
||||
|
||||
```bash
|
||||
# MySQL-Dump
|
||||
docker compose exec mysql mysqldump \
|
||||
-u semaphore -psemaphore semaphore \
|
||||
> semaphore-backup-$(date +%Y%m%d-%H%M%S).sql
|
||||
|
||||
# Volume-Backup (komplett)
|
||||
docker run --rm \
|
||||
-v semaphore-mysql-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/semaphore-mysql-backup-$(date +%Y%m%d).tar.gz /data
|
||||
```
|
||||
|
||||
### Wiederherstellung
|
||||
|
||||
```bash
|
||||
# MySQL-Dump wiederherstellen
|
||||
docker compose exec -T mysql mysql \
|
||||
-u semaphore -psemaphore semaphore \
|
||||
< semaphore-backup-YYYYMMDD.sql
|
||||
|
||||
# Volume wiederherstellen (⚠️ stoppt Container)
|
||||
docker compose down
|
||||
docker run --rm \
|
||||
-v semaphore-mysql-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine sh -c "cd /data && tar xzf /backup/semaphore-mysql-backup-YYYYMMDD.tar.gz"
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Performance-Optimierung
|
||||
|
||||
### MySQL-Optimierung
|
||||
|
||||
Für bessere Performance kannst du MySQL-Konfiguration anpassen:
|
||||
|
||||
1. Erstelle `mysql/conf.d/my.cnf`:
|
||||
```ini
|
||||
[mysqld]
|
||||
innodb_buffer_pool_size = 256M
|
||||
max_connections = 100
|
||||
```
|
||||
|
||||
2. Mounte in `docker-compose.yml`:
|
||||
```yaml
|
||||
volumes:
|
||||
- ./mysql/conf.d:/etc/mysql/conf.d:ro
|
||||
```
|
||||
|
||||
### Resource Limits
|
||||
|
||||
Füge Limits in `docker-compose.yml` hinzu:
|
||||
|
||||
```yaml
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
cpus: '0.5'
|
||||
```
|
||||
|
||||
## Unterstützung
|
||||
|
||||
### Dokumentation
|
||||
|
||||
- **Semaphore CI Docs**: https://docs.semaphoreui.com/
|
||||
- **Semaphore GitHub**: https://github.com/semaphoreui/semaphore
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# Alle Logs
|
||||
docker compose logs -f
|
||||
|
||||
# Semaphore-Logs
|
||||
docker compose logs -f semaphore
|
||||
|
||||
# MySQL-Logs
|
||||
docker compose logs -f mysql
|
||||
|
||||
# Letzte 100 Zeilen
|
||||
docker compose logs --tail=100
|
||||
```
|
||||
|
||||
### Health-Checks
|
||||
|
||||
```bash
|
||||
# Container-Status
|
||||
docker compose ps
|
||||
|
||||
# Semaphore-Health
|
||||
curl http://localhost:9300/api/health
|
||||
|
||||
# MySQL-Health
|
||||
docker compose exec mysql mysqladmin ping -h localhost -u root -psemaphore_root
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Setup-Status**: ✅ Bereit für lokale Entwicklung
|
||||
|
||||
**Nächste Schritte**:
|
||||
1. `cp env.example .env` ausführen
|
||||
2. `docker compose up -d` starten
|
||||
3. http://localhost:9300 öffnen
|
||||
4. Mit Admin-Credentials anmelden
|
||||
5. Erstes Projekt und Template erstellen
|
||||
|
||||
355
deployment/legacy/stacks/stacks/semaphore/SETUP_REPOSITORY.md
Normal file
355
deployment/legacy/stacks/stacks/semaphore/SETUP_REPOSITORY.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# Git-Repository in Semaphore Self-Hosted integrieren
|
||||
|
||||
Diese Anleitung beschreibt, wie du dein Git-Repository in Semaphore Self-Hosted (Ansible-UI) integrierst.
|
||||
|
||||
## ?? ?bersicht
|
||||
|
||||
Semaphore Self-Hosted ist eine Web-UI f?r Ansible, die es erm?glicht:
|
||||
- Ansible-Playbooks ?ber eine grafische Oberfl?che auszuf?hren
|
||||
- CI/CD-Workflows mit Ansible zu automatisieren
|
||||
- Git-Repositories als Playbook-Quellen zu verwenden
|
||||
|
||||
## ?? Schritt 1: Semaphore starten
|
||||
|
||||
### 1.1 Environment-Datei erstellen
|
||||
|
||||
```bash
|
||||
cd deployment/stacks/semaphore
|
||||
cp env.example .env
|
||||
```
|
||||
|
||||
### 1.2 Encryption Key generieren (WICHTIG!)
|
||||
|
||||
```bash
|
||||
# Linux/WSL
|
||||
head -c32 /dev/urandom | base64
|
||||
|
||||
# Windows PowerShell
|
||||
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 32 | % {[char]$_}) | ConvertTo-Base64
|
||||
```
|
||||
|
||||
Kopiere den generierten Key und setze ihn in `.env`:
|
||||
```env
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=<dein-generierter-key>
|
||||
```
|
||||
|
||||
### 1.3 Stack starten
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 1.4 Web-UI ?ffnen
|
||||
|
||||
?ffne im Browser: **http://localhost:9300**
|
||||
|
||||
?? **WICHTIG**: Semaphore ist NUR lokal zug?nglich (127.0.0.1). Es gibt KEINEN externen Zugriff aus Sicherheitsgr?nden!
|
||||
|
||||
**Standard-Login**:
|
||||
- Username: `admin`
|
||||
- Password: `admin`
|
||||
|
||||
## ?? Schritt 2: Projekt in Semaphore erstellen
|
||||
|
||||
### 2.1 Neues Projekt anlegen
|
||||
|
||||
1. Melde dich in Semaphore an
|
||||
2. Klicke auf **"New Project"** oder **"Create Project"**
|
||||
3. Gib einen Projektnamen ein: **"michaelschiemer"**
|
||||
4. Klicke auf **"Create"**
|
||||
|
||||
### 2.2 Git-Repository als Playbook-Quelle hinzuf?gen
|
||||
|
||||
Semaphore Self-Hosted kann Playbooks direkt aus Git-Repositories laden. Du hast zwei Optionen:
|
||||
|
||||
**Option A: Playbooks aus Repository-Clone verwenden** (Empfohlen)
|
||||
|
||||
1. Clone dein Repository lokal:
|
||||
```bash
|
||||
git clone https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
cd michaelschiemer
|
||||
```
|
||||
|
||||
2. Erstelle ein Playbook-Verzeichnis f?r Semaphore:
|
||||
```bash
|
||||
mkdir -p deployment/stacks/semaphore/playbooks
|
||||
cp deployment/ansible/playbooks/*.yml deployment/stacks/semaphore/playbooks/
|
||||
```
|
||||
|
||||
**Option B: Playbooks direkt in Semaphore einf?gen**
|
||||
|
||||
Semaphore kann auch Playbooks direkt im Web-UI erstellen/bearbeiten. F?r Git-Integration ist Option A besser.
|
||||
|
||||
## ??? Schritt 3: Inventory erstellen
|
||||
|
||||
Ein Inventory definiert die Hosts, auf denen Playbooks ausgef?hrt werden.
|
||||
|
||||
### 3.1 Inventory anlegen
|
||||
|
||||
1. Gehe zu deinem Projekt ? **Inventories** ? **New Inventory**
|
||||
2. Name: **"Production Hosts"** oder **"Local Hosts"**
|
||||
3. Klicke auf **"Create"**
|
||||
|
||||
### 3.2 Host hinzuf?gen
|
||||
|
||||
1. Klicke auf dein Inventory ? **Add Host**
|
||||
2. F?lle folgende Felder aus:
|
||||
|
||||
**F?r Production-Deployment:**
|
||||
```
|
||||
Name: production
|
||||
Address: 94.16.110.151
|
||||
SSH Username: deploy
|
||||
SSH Port: 22
|
||||
```
|
||||
|
||||
**F?r Staging-Deployment:**
|
||||
```
|
||||
Name: staging
|
||||
Address: 94.16.110.151 # oder dein Staging-Host
|
||||
SSH Username: deploy
|
||||
SSH Port: 22
|
||||
```
|
||||
|
||||
### 3.3 SSH-Key hinzuf?gen
|
||||
|
||||
1. Gehe zu **Keys** (Seitenleiste)
|
||||
2. Klicke auf **"New Key"**
|
||||
3. Gib einen Namen ein: **"Deployment Key"**
|
||||
4. F?ge deinen SSH Private Key ein (aus `~/.ssh/production` oder ?hnlich)
|
||||
5. W?hle den Key im Host-Inventory aus
|
||||
|
||||
## ?? Schritt 4: Template erstellen
|
||||
|
||||
Templates verbinden Playbooks mit Inventories und definieren Parameter.
|
||||
|
||||
### 4.1 Template f?r Tests erstellen
|
||||
|
||||
1. Gehe zu **Templates** ? **New Template**
|
||||
2. Template-Name: **"Run PHP Tests"**
|
||||
3. Inventory: W?hle dein Inventory
|
||||
4. Playbook: Erstelle ein Playbook oder verwende ein vorhandenes:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Run PHP Tests
|
||||
hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Checkout repository
|
||||
git:
|
||||
repo: https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
dest: /tmp/ci-build
|
||||
version: main
|
||||
|
||||
- name: Install dependencies
|
||||
command: composer install --no-interaction --prefer-dist
|
||||
args:
|
||||
chdir: /tmp/ci-build
|
||||
|
||||
- name: Run tests
|
||||
command: ./vendor/bin/pest
|
||||
args:
|
||||
chdir: /tmp/ci-build
|
||||
register: test_result
|
||||
|
||||
- name: Show test results
|
||||
debug:
|
||||
var: test_result.stdout_lines
|
||||
```
|
||||
|
||||
5. Speichere das Template
|
||||
|
||||
### 4.2 Template f?r Build erstellen
|
||||
|
||||
Erstelle ein Template f?r Docker Image Build:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Build and Push Docker Image
|
||||
hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Checkout repository
|
||||
git:
|
||||
repo: https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
dest: /tmp/ci-build
|
||||
version: main
|
||||
|
||||
- name: Login to Docker registry
|
||||
docker_login:
|
||||
username: "{{ registry_user }}"
|
||||
password: "{{ registry_password }}"
|
||||
registry_url: "{{ registry_url }}"
|
||||
vars:
|
||||
registry_user: "admin"
|
||||
registry_url: "registry.michaelschiemer.de"
|
||||
|
||||
- name: Build Docker image
|
||||
docker_image:
|
||||
name: "{{ registry_url }}/framework:{{ image_tag }}"
|
||||
tag: "{{ image_tag }}"
|
||||
source: build
|
||||
build:
|
||||
path: /tmp/ci-build
|
||||
dockerfile: Dockerfile.production
|
||||
push: yes
|
||||
vars:
|
||||
registry_url: "registry.michaelschiemer.de"
|
||||
image_tag: "latest"
|
||||
```
|
||||
|
||||
### 4.3 Template f?r Deployment erstellen
|
||||
|
||||
Erstelle ein Template f?r Production-Deployment (verwendet die vorhandenen Ansible-Playbooks):
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Deploy to Production
|
||||
hosts: production
|
||||
gather_facts: yes
|
||||
become: yes
|
||||
tasks:
|
||||
- name: Checkout deployment scripts
|
||||
git:
|
||||
repo: https://git.michaelschiemer.de/michael/michaelschiemer.git
|
||||
dest: /tmp/deployment
|
||||
version: main
|
||||
|
||||
- name: Include deployment playbook
|
||||
include_role:
|
||||
name: deployment/ansible/playbooks/deploy-update.yml
|
||||
```
|
||||
|
||||
Oder verwende die vorhandenen Ansible-Playbooks direkt:
|
||||
|
||||
**Vorteil**: Die vorhandenen Playbooks in `deployment/ansible/playbooks/` k?nnen direkt verwendet werden!
|
||||
|
||||
1. Erstelle ein Template: **"Deploy to Production"**
|
||||
2. W?hle Inventory: **"Production Hosts"**
|
||||
3. Playbook-Pfad: **`deployment/ansible/playbooks/deploy-update.yml`**
|
||||
4. Speichere
|
||||
|
||||
## ?? Schritt 5: CI/CD-Workflow einrichten
|
||||
|
||||
### 5.1 Git-Webhook konfigurieren (Optional)
|
||||
|
||||
Semaphore kann Webhooks von Git-Repositories empfangen, um automatisch Tasks zu starten.
|
||||
|
||||
1. Gehe zu deinem Git-Repository (Gitea)
|
||||
2. Settings ? Webhooks ? Add Webhook
|
||||
3. Webhook-URL: `http://localhost:9300/api/hook/git` (nur lokal!)
|
||||
4. Content-Type: `application/json`
|
||||
5. Secret: Optional, aber empfohlen
|
||||
|
||||
### 5.2 Task manuell starten
|
||||
|
||||
1. Gehe zu **Templates**
|
||||
2. Klicke auf dein Template (z.B. "Run PHP Tests")
|
||||
3. Klicke auf **"Run"**
|
||||
4. Beobachte die Ausf?hrung in Echtzeit
|
||||
|
||||
### 5.3 Task automatisch starten
|
||||
|
||||
Semaphore kann Tasks basierend auf Git-Events starten:
|
||||
|
||||
1. Gehe zu Template ? **Settings**
|
||||
2. Aktiviere **"Auto Run on Push"**
|
||||
3. W?hle Branch: `main` oder `staging`
|
||||
4. Speichere
|
||||
|
||||
## ?? Verwendung vorhandener Ansible-Playbooks
|
||||
|
||||
### Vorhandene Playbooks verwenden
|
||||
|
||||
Die vorhandenen Ansible-Playbooks in `deployment/ansible/playbooks/` k?nnen direkt in Semaphore verwendet werden:
|
||||
|
||||
1. **Mounte Playbooks als Volume** (in `docker-compose.yml`):
|
||||
```yaml
|
||||
volumes:
|
||||
- ./../../ansible/playbooks:/tmp/semaphore/playbooks:ro
|
||||
```
|
||||
|
||||
2. **Erstelle Templates**, die auf diese Playbooks verweisen:
|
||||
- Playbook-Pfad: `/tmp/semaphore/playbooks/deploy-update.yml`
|
||||
- Inventory: W?hle dein Production-Inventory
|
||||
|
||||
### Beispiel-Templates
|
||||
|
||||
#### Template: Deploy Update
|
||||
- Name: "Deploy Update"
|
||||
- Inventory: "Production Hosts"
|
||||
- Playbook: `/tmp/semaphore/playbooks/deploy-update.yml`
|
||||
- Variables:
|
||||
```yaml
|
||||
registry_url: registry.michaelschiemer.de
|
||||
image_name: framework
|
||||
image_tag: latest
|
||||
```
|
||||
|
||||
#### Template: Rollback
|
||||
- Name: "Rollback"
|
||||
- Inventory: "Production Hosts"
|
||||
- Playbook: `/tmp/semaphore/playbooks/rollback.yml`
|
||||
- Variables:
|
||||
```yaml
|
||||
registry_url: registry.michaelschiemer.de
|
||||
image_name: framework
|
||||
```
|
||||
|
||||
## ?? Erweiterte Konfiguration
|
||||
|
||||
### Docker Socket f?r Build-Tasks
|
||||
|
||||
F?r Docker-Build-Tasks muss der Semaphore-Container Zugriff auf den Docker-Socket haben:
|
||||
|
||||
**In `docker-compose.yml` hinzuf?gen:**
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
```
|
||||
|
||||
### Environment-Variablen f?r Templates
|
||||
|
||||
Du kannst Environment-Variablen in Templates verwenden:
|
||||
|
||||
1. Gehe zu Template ? **Variables**
|
||||
2. F?ge Variablen hinzu:
|
||||
- `registry_url`: `registry.michaelschiemer.de`
|
||||
- `registry_user`: `admin`
|
||||
- `image_name`: `framework`
|
||||
|
||||
### Git-Integration mit SSH-Keys
|
||||
|
||||
F?r private Repositories:
|
||||
|
||||
1. Gehe zu **Keys**
|
||||
2. Erstelle einen SSH-Key f?r Git-Access
|
||||
3. F?ge den Public Key zu deinem Git-Repository hinzu (Deploy Keys)
|
||||
4. Verwende SSH-URL in Git-Tasks:
|
||||
```yaml
|
||||
git:
|
||||
repo: git@git.michaelschiemer.de:michael/michaelschiemer.git
|
||||
```
|
||||
|
||||
## ?? N?tzliche Links
|
||||
|
||||
- [Semaphore Self-Hosted Dokumentation](https://docs.ansible-semaphore.com/)
|
||||
- [Ansible Semaphore GitHub](https://github.com/ansible-semaphore/semaphore)
|
||||
- [Ansible Playbook Dokumentation](https://docs.ansible.com/ansible/latest/playbook_guide/index.html)
|
||||
|
||||
## ? Checkliste
|
||||
|
||||
- [ ] Semaphore gestartet (http://localhost:9300)
|
||||
- [ ] Projekt erstellt
|
||||
- [ ] Inventory mit Hosts erstellt
|
||||
- [ ] SSH-Keys f?r Host-Zugriff konfiguriert
|
||||
- [ ] Template f?r Tests erstellt
|
||||
- [ ] Template f?r Build erstellt
|
||||
- [ ] Template f?r Deployment erstellt
|
||||
- [ ] Erstes Template erfolgreich ausgef?hrt
|
||||
- [ ] Git-Webhook konfiguriert (optional)
|
||||
|
||||
---
|
||||
|
||||
**N?chste Schritte**: Starte Semaphore und erstelle dein erstes Template!
|
||||
93
deployment/legacy/stacks/stacks/semaphore/docker-compose.yml
Normal file
93
deployment/legacy/stacks/stacks/semaphore/docker-compose.yml
Normal file
@@ -0,0 +1,93 @@
|
||||
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 (127.0.0.1) - NOT accessible externally!
|
||||
# Default port 9300 to avoid conflict with Gitea (port 3000)
|
||||
# SECURITY: This ensures Semaphore is only accessible locally
|
||||
- "127.0.0.1:${SEMAPHORE_PORT:-9300}:3000"
|
||||
# NO Traefik labels - Semaphore should only be accessible locally!
|
||||
# External access is disabled for security reasons.
|
||||
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
|
||||
# Mount playbooks from repository so Semaphore can access them
|
||||
- ../../../deployment/stacks/semaphore/playbooks:/tmp/semaphore/playbooks:ro
|
||||
- ../../../deployment/ansible/playbooks:/tmp/semaphore/repo-playbooks:ro
|
||||
- /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
|
||||
|
||||
51
deployment/legacy/stacks/stacks/semaphore/env.example
Normal file
51
deployment/legacy/stacks/stacks/semaphore/env.example
Normal file
@@ -0,0 +1,51 @@
|
||||
# Semaphore CI Stack - Environment Configuration
|
||||
# Copy this file to .env and adjust values as needed
|
||||
# Note: Rename this file to .env.example if you prefer the standard naming
|
||||
|
||||
# ============================================
|
||||
# MySQL Database Configuration
|
||||
# ============================================
|
||||
MYSQL_ROOT_PASSWORD=semaphore_root
|
||||
MYSQL_DATABASE=semaphore
|
||||
MYSQL_USER=semaphore
|
||||
MYSQL_PASSWORD=semaphore
|
||||
|
||||
# ============================================
|
||||
# Semaphore Configuration
|
||||
# ============================================
|
||||
|
||||
# Port binding (default: 9300)
|
||||
# Only accessible via localhost (127.0.0.1)
|
||||
# Note: Changed from 3000 to avoid conflict with Gitea
|
||||
SEMAPHORE_PORT=9300
|
||||
|
||||
# Admin User Configuration
|
||||
SEMAPHORE_ADMIN=admin
|
||||
SEMAPHORE_ADMIN_NAME=Administrator
|
||||
SEMAPHORE_ADMIN_EMAIL=admin@localhost
|
||||
SEMAPHORE_ADMIN_PASSWORD=admin
|
||||
|
||||
# Playbook Storage Path (inside container)
|
||||
SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore
|
||||
|
||||
# Access Key Encryption
|
||||
# Generate with: head -c32 /dev/urandom | base64
|
||||
# IMPORTANT: Change this in production!
|
||||
SEMAPHORE_ACCESS_KEY_ENCRYPTION=change-me-in-production
|
||||
|
||||
# ============================================
|
||||
# Optional: LDAP Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_LDAP_ENABLED=false
|
||||
# SEMAPHORE_LDAP_HOST=ldap.example.com
|
||||
# SEMAPHORE_LDAP_PORT=389
|
||||
# SEMAPHORE_LDAP_DN=cn=admin,dc=example,dc=com
|
||||
# SEMAPHORE_LDAP_PASSWORD=ldap_password
|
||||
# SEMAPHORE_LDAP_BASE_DN=dc=example,dc=com
|
||||
# SEMAPHORE_LDAP_USER_FILTER=(uid=%s)
|
||||
|
||||
# ============================================
|
||||
# Optional: Webhook Configuration
|
||||
# ============================================
|
||||
# SEMAPHORE_WEBHOOK_URL=http://localhost:8080/webhook
|
||||
|
||||
103
deployment/legacy/stacks/stacks/semaphore/playbooks/ci-tests.yml
Normal file
103
deployment/legacy/stacks/stacks/semaphore/playbooks/ci-tests.yml
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
# CI Tests Playbook f?r Semaphore
|
||||
# F?hrt PHP Tests und Quality Checks aus
|
||||
|
||||
- name: Run CI Tests and Quality Checks
|
||||
hosts: localhost
|
||||
gather_facts: no
|
||||
vars:
|
||||
repo_url: "{{ repo_url | default('https://git.michaelschiemer.de/michael/michaelschiemer.git') }}"
|
||||
repo_branch: "{{ repo_branch | default('main') }}"
|
||||
build_dir: "/tmp/ci-build"
|
||||
|
||||
tasks:
|
||||
- name: Clean up build directory
|
||||
file:
|
||||
path: "{{ build_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Checkout repository
|
||||
git:
|
||||
repo: "{{ repo_url }}"
|
||||
dest: "{{ build_dir }}"
|
||||
version: "{{ repo_branch }}"
|
||||
force: yes
|
||||
register: git_result
|
||||
|
||||
- name: Display checked out commit
|
||||
debug:
|
||||
msg: "Checked out commit: {{ git_result.after }}"
|
||||
|
||||
- name: Install Composer if not present
|
||||
get_url:
|
||||
url: https://getcomposer.org/installer
|
||||
dest: /tmp/composer-installer.php
|
||||
mode: '0755'
|
||||
when: ansible_facts.os_family == "Debian"
|
||||
|
||||
- name: Install Composer (Debian)
|
||||
shell: php /tmp/composer-installer.php && mv composer.phar /usr/local/bin/composer
|
||||
when: ansible_facts.os_family == "Debian"
|
||||
args:
|
||||
creates: /usr/local/bin/composer
|
||||
|
||||
- name: Install PHP dependencies
|
||||
command: composer install --no-interaction --prefer-dist --optimize-autoloader --ignore-platform-req=php
|
||||
args:
|
||||
chdir: "{{ build_dir }}"
|
||||
register: composer_result
|
||||
|
||||
- name: Display composer output
|
||||
debug:
|
||||
var: composer_result.stdout_lines
|
||||
when: composer_result.stdout_lines is defined
|
||||
|
||||
- name: Run PHP tests
|
||||
command: ./vendor/bin/pest
|
||||
args:
|
||||
chdir: "{{ build_dir }}"
|
||||
register: test_result
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display test results
|
||||
debug:
|
||||
msg: "{{ test_result.stdout_lines }}"
|
||||
when: test_result.stdout_lines is defined
|
||||
|
||||
- name: Run PHPStan
|
||||
command: composer phpstan
|
||||
args:
|
||||
chdir: "{{ build_dir }}"
|
||||
register: phpstan_result
|
||||
ignore_errors: yes
|
||||
when: test_result.rc == 0
|
||||
|
||||
- name: Display PHPStan results
|
||||
debug:
|
||||
msg: "{{ phpstan_result.stdout_lines }}"
|
||||
when: phpstan_result.stdout_lines is defined and phpstan_result.rc == 0
|
||||
|
||||
- name: Run code style check
|
||||
command: composer cs
|
||||
args:
|
||||
chdir: "{{ build_dir }}"
|
||||
register: cs_result
|
||||
ignore_errors: yes
|
||||
when: test_result.rc == 0
|
||||
|
||||
- name: Display code style results
|
||||
debug:
|
||||
msg: "{{ cs_result.stdout_lines }}"
|
||||
when: cs_result.stdout_lines is defined
|
||||
|
||||
- name: Fail if tests failed
|
||||
fail:
|
||||
msg: "Tests failed! Check output above."
|
||||
when: test_result.rc != 0
|
||||
|
||||
- name: Summary
|
||||
debug:
|
||||
msg:
|
||||
- "? CI Tests completed successfully!"
|
||||
- "Commit: {{ git_result.after }}"
|
||||
- "Branch: {{ repo_branch }}"
|
||||
@@ -0,0 +1,129 @@
|
||||
---
|
||||
# Production Deployment Playbook f?r Semaphore
|
||||
# Deployed die Anwendung auf Production-Server
|
||||
|
||||
- name: Deploy to Production
|
||||
hosts: production
|
||||
gather_facts: yes
|
||||
become: yes
|
||||
vars:
|
||||
registry_url: "{{ registry_url | default('registry.michaelschiemer.de') }}"
|
||||
image_name: "{{ image_name | default('framework') }}"
|
||||
image_tag: "{{ image_tag | default('latest') }}"
|
||||
registry_user: "{{ registry_user | default('admin') }}"
|
||||
registry_password: "{{ registry_password | required }}"
|
||||
deployment_path: "{{ deployment_path | default('~/deployment/stacks/application') }}"
|
||||
repo_url: "{{ repo_url | default('https://git.michaelschiemer.de/michael/michaelschiemer.git') }}"
|
||||
|
||||
tasks:
|
||||
- name: Display deployment info
|
||||
debug:
|
||||
msg:
|
||||
- "?? Starting production deployment..."
|
||||
- "Host: {{ inventory_hostname }}"
|
||||
- "Registry: {{ registry_url }}"
|
||||
- "Image: {{ image_name }}:{{ image_tag }}"
|
||||
- "Path: {{ deployment_path }}"
|
||||
|
||||
- name: Ensure deployment directory exists
|
||||
file:
|
||||
path: "{{ deployment_path }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Login to Docker registry
|
||||
docker_login:
|
||||
username: "{{ registry_user }}"
|
||||
password: "{{ registry_password }}"
|
||||
registry_url: "{{ registry_url }}"
|
||||
|
||||
- name: Pull Docker image
|
||||
docker_image:
|
||||
name: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
source: pull
|
||||
|
||||
- name: Check if docker-compose files exist
|
||||
stat:
|
||||
path: "{{ deployment_path }}/docker-compose.base.yml"
|
||||
register: base_compose_exists
|
||||
|
||||
- name: Check if docker-compose.production.yml exists
|
||||
stat:
|
||||
path: "{{ deployment_path }}/docker-compose.production.yml"
|
||||
register: production_compose_exists
|
||||
|
||||
- name: Copy docker-compose files if missing
|
||||
copy:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ deployment_path }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: "docker-compose.base.yml", dest: "docker-compose.base.yml" }
|
||||
- { src: "docker-compose.production.yml", dest: "docker-compose.production.yml" }
|
||||
when: not (item.dest == "docker-compose.base.yml" and base_compose_exists.stat.exists) or
|
||||
not (item.dest == "docker-compose.production.yml" and production_compose_exists.stat.exists)
|
||||
delegate_to: localhost
|
||||
become: no
|
||||
|
||||
- name: Update docker-compose.production.yml with new image
|
||||
replace:
|
||||
path: "{{ deployment_path }}/docker-compose.production.yml"
|
||||
regexp: 'image:.*{{ image_name }}:.*'
|
||||
replace: 'image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}'
|
||||
|
||||
- name: Update docker-compose.production.yml with new image (alternative format)
|
||||
replace:
|
||||
path: "{{ deployment_path }}/docker-compose.production.yml"
|
||||
regexp: 'image:.*{{ image_name }}@.*'
|
||||
replace: 'image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}'
|
||||
|
||||
- name: Ensure Docker networks exist
|
||||
docker_network:
|
||||
name: traefik-public
|
||||
state: present
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Deploy services
|
||||
docker_compose_v2:
|
||||
project_src: "{{ deployment_path }}"
|
||||
files:
|
||||
- "{{ deployment_path }}/docker-compose.base.yml"
|
||||
- "{{ deployment_path }}/docker-compose.production.yml"
|
||||
pull: missing
|
||||
state: present
|
||||
recreate: always
|
||||
|
||||
- name: Wait for services to start
|
||||
pause:
|
||||
seconds: 15
|
||||
|
||||
- name: Check container status
|
||||
command: docker compose -f {{ deployment_path }}/docker-compose.base.yml -f {{ deployment_path }}/docker-compose.production.yml ps
|
||||
register: container_status
|
||||
|
||||
- name: Display container status
|
||||
debug:
|
||||
var: container_status.stdout_lines
|
||||
|
||||
- name: Health check
|
||||
uri:
|
||||
url: https://michaelschiemer.de/health
|
||||
method: GET
|
||||
status_code: [200, 201, 204]
|
||||
validate_certs: no
|
||||
register: health_result
|
||||
retries: 10
|
||||
delay: 10
|
||||
until: health_result.status == 200
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Display health check result
|
||||
debug:
|
||||
msg: "? Health check passed!" if health_result.status == 200 else "?? Health check failed"
|
||||
|
||||
- name: Summary
|
||||
debug:
|
||||
msg:
|
||||
- "? Production deployment completed!"
|
||||
- "Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
- "URL: https://michaelschiemer.de"
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
# Staging Deployment Playbook f?r Semaphore
|
||||
# Deployed die Anwendung auf Staging-Server
|
||||
|
||||
- name: Deploy to Staging
|
||||
hosts: staging
|
||||
gather_facts: yes
|
||||
become: yes
|
||||
vars:
|
||||
registry_url: "{{ registry_url | default('registry.michaelschiemer.de') }}"
|
||||
image_name: "{{ image_name | default('framework') }}"
|
||||
image_tag: "{{ image_tag | default('latest') }}"
|
||||
registry_user: "{{ registry_user | default('admin') }}"
|
||||
registry_password: "{{ registry_password | required }}"
|
||||
deployment_path: "{{ deployment_path | default('~/deployment/stacks/staging') }}"
|
||||
repo_url: "{{ repo_url | default('https://git.michaelschiemer.de/michael/michaelschiemer.git') }}"
|
||||
|
||||
tasks:
|
||||
- name: Display deployment info
|
||||
debug:
|
||||
msg:
|
||||
- "?? Starting staging deployment..."
|
||||
- "Host: {{ inventory_hostname }}"
|
||||
- "Registry: {{ registry_url }}"
|
||||
- "Image: {{ image_name }}:{{ image_tag }}"
|
||||
- "Path: {{ deployment_path }}"
|
||||
|
||||
- name: Ensure deployment directory exists
|
||||
file:
|
||||
path: "{{ deployment_path }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Login to Docker registry
|
||||
docker_login:
|
||||
username: "{{ registry_user }}"
|
||||
password: "{{ registry_password }}"
|
||||
registry_url: "{{ registry_url }}"
|
||||
|
||||
- name: Pull Docker image
|
||||
docker_image:
|
||||
name: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
source: pull
|
||||
|
||||
- name: Check if docker-compose files exist
|
||||
stat:
|
||||
path: "{{ deployment_path }}/docker-compose.base.yml"
|
||||
register: base_compose_exists
|
||||
|
||||
- name: Check if docker-compose.staging.yml exists
|
||||
stat:
|
||||
path: "{{ deployment_path }}/docker-compose.staging.yml"
|
||||
register: staging_compose_exists
|
||||
|
||||
- name: Copy docker-compose files (always update)
|
||||
copy:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ deployment_path }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
force: yes
|
||||
loop:
|
||||
- { src: "docker-compose.base.yml", dest: "docker-compose.base.yml" }
|
||||
- { src: "docker-compose.staging.yml", dest: "docker-compose.staging.yml" }
|
||||
delegate_to: localhost
|
||||
become: no
|
||||
|
||||
- name: Update docker-compose.staging.yml with new image
|
||||
replace:
|
||||
path: "{{ deployment_path }}/docker-compose.staging.yml"
|
||||
regexp: 'image:.*{{ image_name }}:.*'
|
||||
replace: 'image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}'
|
||||
|
||||
- name: Ensure Docker networks exist
|
||||
docker_network:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- traefik-public
|
||||
- staging-internal
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Deploy services
|
||||
docker_compose_v2:
|
||||
project_src: "{{ deployment_path }}"
|
||||
files:
|
||||
- "{{ deployment_path }}/docker-compose.base.yml"
|
||||
- "{{ deployment_path }}/docker-compose.staging.yml"
|
||||
pull: missing
|
||||
state: present
|
||||
recreate: always
|
||||
|
||||
- name: Wait for services to start
|
||||
pause:
|
||||
seconds: 15
|
||||
|
||||
- name: Check container status
|
||||
command: docker compose -f {{ deployment_path }}/docker-compose.base.yml -f {{ deployment_path }}/docker-compose.staging.yml ps
|
||||
register: container_status
|
||||
|
||||
- name: Display container status
|
||||
debug:
|
||||
var: container_status.stdout_lines
|
||||
|
||||
- name: Summary
|
||||
debug:
|
||||
msg:
|
||||
- "? Staging deployment completed!"
|
||||
- "Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
- "URL: https://staging.michaelschiemer.de"
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
# Docker Build Playbook f?r Semaphore
|
||||
# Baut Docker Image und pusht es zur Registry
|
||||
|
||||
- name: Build and Push Docker Image
|
||||
hosts: localhost
|
||||
gather_facts: no
|
||||
vars:
|
||||
repo_url: "{{ repo_url | default('https://git.michaelschiemer.de/michael/michaelschiemer.git') }}"
|
||||
repo_branch: "{{ repo_branch | default('main') }}"
|
||||
build_dir: "/tmp/ci-build"
|
||||
registry_url: "{{ registry_url | default('registry.michaelschiemer.de') }}"
|
||||
image_name: "{{ image_name | default('framework') }}"
|
||||
image_tag: "{{ image_tag | default('latest') }}"
|
||||
registry_user: "{{ registry_user | default('admin') }}"
|
||||
registry_password: "{{ registry_password | required }}"
|
||||
|
||||
tasks:
|
||||
- name: Clean up build directory
|
||||
file:
|
||||
path: "{{ build_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Checkout repository
|
||||
git:
|
||||
repo: "{{ repo_url }}"
|
||||
dest: "{{ build_dir }}"
|
||||
version: "{{ repo_branch }}"
|
||||
force: yes
|
||||
register: git_result
|
||||
|
||||
- name: Get short commit SHA
|
||||
shell: echo "{{ git_result.after }}" | cut -c1-7
|
||||
register: short_sha
|
||||
|
||||
- name: Generate image tags
|
||||
set_fact:
|
||||
tags:
|
||||
- "{{ registry_url }}/{{ image_name }}:latest"
|
||||
- "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
- "{{ registry_url }}/{{ image_name }}:git-{{ short_sha.stdout }}"
|
||||
|
||||
- name: Display image tags
|
||||
debug:
|
||||
msg:
|
||||
- "??? Building Docker image..."
|
||||
- "Registry: {{ registry_url }}"
|
||||
- "Image: {{ image_name }}"
|
||||
- "Tags: {{ tags | join(', ') }}"
|
||||
|
||||
- name: Ensure Docker is available
|
||||
command: docker --version
|
||||
register: docker_version
|
||||
|
||||
- name: Display Docker version
|
||||
debug:
|
||||
msg: "Docker version: {{ docker_version.stdout }}"
|
||||
|
||||
- name: Login to Docker registry
|
||||
docker_login:
|
||||
username: "{{ registry_user }}"
|
||||
password: "{{ registry_password }}"
|
||||
registry_url: "{{ registry_url }}"
|
||||
register: login_result
|
||||
|
||||
- name: Verify registry login
|
||||
debug:
|
||||
msg: "? Successfully logged in to {{ registry_url }}"
|
||||
when: login_result.failed == false
|
||||
|
||||
- name: Build Docker image
|
||||
docker_image:
|
||||
name: "{{ registry_url }}/{{ image_name }}"
|
||||
tag: "{{ image_tag }}"
|
||||
source: build
|
||||
build:
|
||||
path: "{{ build_dir }}"
|
||||
dockerfile: Dockerfile.production
|
||||
push: yes
|
||||
state: present
|
||||
register: build_result
|
||||
|
||||
- name: Tag image with additional tags
|
||||
docker_image:
|
||||
name: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
||||
repository: "{{ registry_url }}/{{ image_name }}"
|
||||
tag: "{{ item }}"
|
||||
source: local
|
||||
push: yes
|
||||
state: present
|
||||
loop:
|
||||
- "latest"
|
||||
- "git-{{ short_sha.stdout }}"
|
||||
when: build_result.changed
|
||||
|
||||
- name: Summary
|
||||
debug:
|
||||
msg:
|
||||
- "? Docker image built and pushed successfully!"
|
||||
- "Registry: {{ registry_url }}"
|
||||
- "Image: {{ image_name }}"
|
||||
- "Tags: {{ tags | join(', ') }}"
|
||||
- "Commit: {{ git_result.after }}"
|
||||
Reference in New Issue
Block a user