diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index 648a209..11a5755 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -1,97 +1,58 @@ -name: Build and Push Docker Images +name: Docker Build and Push -# Trigger: Wann soll der Workflow laufen? on: - workflow_dispatch: # Ermöglicht manuelles Starten über die GitHub UI + push: + branches: + - main # Löst den Workflow bei jedem Push auf den main-Branch aus jobs: build-and-push: - runs-on: ubuntu-latest # Verwendet den neuesten Ubuntu-Runner von GitHub - - # Berechtigungen für den GITHUB_TOKEN, um nach GHCR pushen zu können + runs-on: ubuntu-latest permissions: - contents: read # Zum Auschecken des Codes - packages: write # Zum Pushen nach GitHub Packages (GHCR) + contents: read + packages: write # Notwendig, um in die GHCR zu pushen steps: - # 1. Code auschecken - name: Checkout repository uses: actions/checkout@v4 - - # 2. Docker Metadaten extrahieren (Tags, Labels) - # Wir definieren hier die Namen für beide Images - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 with: - images: | - ghcr.io/${{ github.repository_owner }}/utools-backend - ghcr.io/${{ github.repository_owner }}/utools-frontend - # Tags generieren: - # - Typ 'sha' -> Kurzer Commit-Hash (z.B. sha-a1b2c3d) - # - Typ 'ref' für Events 'branch' -> Branch-Name (z.B. 'main' wird zu 'latest') - # - Typ 'ref' für Events 'tag' -> Git-Tag-Name (z.B. v1.0.0) - tags: | - type=sha,prefix=sha- - type=ref,event=branch - type=ref,event=tag - type=ref,event=pr # Nur für PR-Events + fetch-depth: 0 # Notwendig, um den Git-Hash zu bekommen - # 3. QEMU für Multi-Plattform Builds (optional, aber gute Praxis) - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - # 4. Docker Buildx einrichten (verbesserter Builder) - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # 5. Login bei GitHub Container Registry (GHCR) - # Verwendet den automatisch generierten GITHUB_TOKEN - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.actor }} # Benutzer oder Organisation, dem das Repo gehört - password: ${{ secrets.GHCR_PUSH_TOKEN }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - # 6. Backend Image bauen und pushen - - name: Build and push Backend image - id: build-backend - uses: docker/build-push-action@v5 - with: - context: ./backend # Pfad zum Backend-Dockerfile - # Nur pushen, wenn es ein Push zum main-Branch oder ein Git-Tag ist - push: ${{ github.event_name == 'push' || github.event_name == 'create' && startsWith(github.ref, 'refs/tags/') }} - # Tags und Labels aus dem Metadaten-Schritt verwenden (gefiltert für Backend) - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - # Filter für das spezifische Backend-Image (Index 0 in der 'images'-Liste oben) - # Wichtig: Passe den Index an, falls du die Reihenfolge änderst! - image-name-index: 0 # Index des Backend-Images in der 'images'-Liste - cache-from: type=gha # GitHub Actions Cache verwenden (Lesen) - cache-to: type=gha,mode=max # GitHub Actions Cache verwenden (Schreiben) + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - # 7. Frontend Image bauen und pushen - - name: Build and push Frontend image - id: build-frontend - uses: docker/build-push-action@v5 - with: - context: ./frontend # Pfad zum Frontend-Dockerfile - # Nur pushen, wenn es ein Push zum main-Branch oder ein Git-Tag ist - push: ${{ github.event_name == 'push' || github.event_name == 'create' && startsWith(github.ref, 'refs/tags/') }} - # Tags und Labels aus dem Metadaten-Schritt verwenden (gefiltert für Frontend) - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - # Filter für das spezifische Frontend-Image (Index 1 in der 'images'-Liste oben) - image-name-index: 1 # Index des Frontend-Images in der 'images'-Liste - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Get Git commit SHA + id: git_sha + run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - # 8. (Optional) Output der Image-Namen und Tags - - name: Print image names and tags - if: always() # Auch ausführen, wenn vorherige Schritte fehlschlagen (zum Debuggen) + - name: Define Image Names + id: image_names run: | - echo "Backend Image Tags: ${{ steps.meta.outputs.tags }}" - echo "Frontend Image Tags: ${{ steps.meta.outputs.tags }}" - echo "Backend Image Digest: ${{ steps.build-backend.outputs.digest }}" - echo "Frontend Image Digest: ${{ steps.build-frontend.outputs.digest }}" \ No newline at end of file + echo "backend_image=ghcr.io/${{ github.repository_owner }}/utools-backend" >> $GITHUB_OUTPUT + echo "frontend_image=ghcr.io/${{ github.repository_owner }}/utools-frontend" >> $GITHUB_OUTPUT + + - name: Build images using compose.build.yml + env: + GIT_COMMIT_SHA: ${{ steps.git_sha.outputs.sha }} + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} # Sentry DSN als Secret übergeben + run: | + docker compose -f compose.build.yml build + + - name: Tag images with Git SHA + run: | + docker tag ${{ steps.image_names.outputs.backend_image }}:latest ${{ steps.image_names.outputs.backend_image }}:${{ steps.git_sha.outputs.sha }} + docker tag ${{ steps.image_names.outputs.frontend_image }}:latest ${{ steps.image_names.outputs.frontend_image }}:${{ steps.git_sha.outputs.sha }} + + - name: Push images to GHCR (both tags) + run: | + docker push ${{ steps.image_names.outputs.backend_image }}:latest + docker push ${{ steps.image_names.outputs.backend_image }}:${{ steps.git_sha.outputs.sha }} + docker push ${{ steps.image_names.outputs.frontend_image }}:latest + docker push ${{ steps.image_names.outputs.frontend_image }}:${{ steps.git_sha.outputs.sha }} \ No newline at end of file diff --git a/README.md b/README.md index 162fb1e..233dae0 100755 --- a/README.md +++ b/README.md @@ -58,57 +58,56 @@ You can run this application easily using Docker and Docker Compose. This method uses the Docker images automatically built and pushed to GitHub Container Registry (GHCR) by the GitHub Actions workflow. -1. **Create `docker-compose.yml`:** - Save the following content as `docker-compose.yml` in a new directory on your machine: +1. **Create `compose.yml`:** + Save the following content as `compose.yml` in a new directory on your machine: ```yaml - version: '3.8' - services: + # Backend Service (Node.js App) backend: - # Use the pre-built image from GHCR - image: ghcr.io/mrunknownde/utools-backend:latest # Or specify a specific tag/sha + # Verwendet ein bereits gebautes Image + image: ghcr.io/mrunknownde/utools-backend:latest container_name: utools_backend restart: unless-stopped environment: - # Production environment settings - NODE_ENV: production - PORT: 3000 - LOG_LEVEL: info # Adjust log level if needed (e.g., 'debug', 'warn') + # Setze Umgebungsvariablen für das Backend + NODE_ENV: production # Wichtig für Performance und Logging + PORT: 3000 # Port innerhalb des Containers + LOG_LEVEL: info # Oder 'warn' für weniger Logs in Produktion PING_COUNT: 4 - # Optional: Set Sentry DSN for error tracking if you use Sentry - # SENTRY_DSN: "YOUR_SENTRY_DSN" + # Sentry DSN aus der Umgebung/ .env Datei übernehmen + SENTRY_DSN: "https://7ea70caba68f548fb96482a573006a7b@o447623.ingest.us.sentry.io/4509062020333568" # Wichtig für die Laufzeit dns: - # Explicitly set reliable public DNS servers for rDNS lookups inside the container - 1.1.1.1 # Cloudflare DNS - 1.0.0.1 # Cloudflare DNS - 8.8.8.8 # Google DNS - 8.8.4.4 # Google DNS networks: - - utools_network - # Note: No ports exposed directly, access is via frontend proxy + - utools_network # Verbinde mit unserem benutzerdefinierten Netzwerk + # Frontend Service (Nginx) frontend: - # Use the pre-built image from GHCR - image: ghcr.io/mrunknownde/utools-frontend:latest # Or specify a specific tag/sha + # Verwendet ein bereits gebautes Image + image: ghcr.io/mrunknownde/utools-frontend:latest container_name: utools_frontend restart: unless-stopped ports: - # Expose port 8080 on the host, mapping to port 80 in the container (Nginx) + # Mappe Port 8080 vom Host auf Port 80 im Container (wo Nginx lauscht) + # Zugriff von außen (Browser) erfolgt über localhost:8080 - "8080:80" depends_on: - - backend # Ensures backend service is started first + - backend # Stellt sicher, dass Backend gestartet wird (aber nicht unbedingt bereit ist) networks: - - utools_network + - utools_network # Verbinde mit unserem benutzerdefinierten Netzwerk + # Definiere ein benutzerdefiniertes Netzwerk (gute Praxis) networks: utools_network: driver: bridge - name: utools_network # Give the network a specific name ``` 2. **Start the Application:** - Open a terminal in the directory where you saved the `docker-compose.yml` file and run: + Open a terminal in the directory where you saved the `compose.yml` file and run: ```bash docker compose up -d ``` @@ -120,7 +119,7 @@ This method uses the Docker images automatically built and pushed to GitHub Cont ### Option 2: Building Images from Source -If you want to modify the code or build the images yourself: +If you want to modify the code or build the images yourself, the project is now split into a build and a run configuration. 1. **Clone the Repository:** ```bash @@ -128,20 +127,26 @@ If you want to modify the code or build the images yourself: cd utools ``` 2. **Build and Start:** - Use Docker Compose to build the images based on the `Dockerfile`s in the `backend` and `frontend` directories and then start the containers: + First, you build the images using `compose.build.yml`. Then, you start the services using the main `compose.yml`. + ```bash - # Optional: Set GIT_COMMIT_SHA for build args if needed - # export GIT_COMMIT_SHA=$(git rev-parse --short HEAD) - docker compose -f compose.yml up -d --build + # Set GIT_COMMIT_SHA for the build process + export GIT_COMMIT_SHA=$(git rev-parse --short HEAD) + + # 1. Build the images + docker compose -f compose.build.yml build + + # 2. Run the services using the newly built images + docker compose -f compose.yml up -d ``` - *(Note: Use `docker-compose` (with hyphen) if you have an older version. The `compose.yml` in the repository correctly uses `build:` directives)* + You can also use the provided `build.sh` script which does these steps for you. 3. **Access the Webapp:** Open your web browser and navigate to `http://localhost:8080`. ## ⚙️ Configuration -The application is configured mainly through environment variables set in the `docker-compose.yml` file for the `backend` service: +The application is configured mainly through environment variables set in the `compose.yml` file for the `backend` service: * `NODE_ENV`: Set to `production` for optimal performance and JSON logging. * `PORT`: The internal port the Node.js application listens on (default: `3000`). @@ -162,4 +167,4 @@ The MaxMind database paths (`GEOIP_CITY_DB`, `GEOIP_ASN_DB`) are set within the ## 📜 License -This project is licensed under the MIT License. See the `LICENSE` file for details. +This project is licensed under the MIT License. See the `LICENSE` file for details. \ No newline at end of file diff --git a/build.sh b/build.sh index eed7b17..8f55acb 100644 --- a/build.sh +++ b/build.sh @@ -1,3 +1,13 @@ docker compose down + +# Setzt die Git-Commit-Variable für den Build-Prozess export GIT_COMMIT_SHA=$(git rev-parse --short HEAD) -docker compose -f compose.yml up -d --build \ No newline at end of file +export SENTRY_DSN="https://7ea70caba68f548fb96482a573006a7b@o447623.ingest.us.sentry.io/4509062020333568" + +# Schritt 1: Baue die Images mit der compose.build.yml +echo "--- Building Docker images ---" +docker compose -f compose.build.yml build + +# Schritt 2: Starte die Container mit der compose.yml, die die gebauten Images verwendet +echo "--- Starting containers ---" +docker compose -f compose.yml up -d \ No newline at end of file diff --git a/compose.build.yml b/compose.build.yml new file mode 100644 index 0000000..faabf85 --- /dev/null +++ b/compose.build.yml @@ -0,0 +1,18 @@ +# compose.build.yml +services: + backend: + # Definiert, wie das Image gebaut wird + build: + context: ./backend + args: + - GIT_COMMIT_SHA=${GIT_COMMIT_SHA:-unknown} + - SENTRY_DSN=${SENTRY_DSN:-} + # Legt den Namen für das gebaute Image fest + image: ghcr.io/mrunknownde/utools-backend:latest + + frontend: + # Definiert, wie das Image gebaut wird + build: + context: ./frontend + # Legt den Namen für das gebaute Image fest + image: ghcr.io/mrunknownde/utools-frontend:latest \ No newline at end of file diff --git a/compose.yml b/compose.yml index 5e7b96a..b9d849b 100644 --- a/compose.yml +++ b/compose.yml @@ -1,15 +1,9 @@ services: # Backend Service (Node.js App) backend: - build: - context: ./backend # Pfad zum Verzeichnis mit dem Backend-Dockerfile - args: - # Übergibt den Git Commit Hash als Build-Argument. - # Erwartet, dass GIT_COMMIT_SHA in der Shell-Umgebung gesetzt ist (z.B. export GIT_COMMIT_SHA=$(git rev-parse --short HEAD)) - - GIT_COMMIT_SHA=${GIT_COMMIT_SHA:-unknown} - # Übergibt den Sentry DSN als Build-Argument (optional, falls im Code benötigt) - - SENTRY_DSN="https://7ea70caba68f548fb96482a573006a7b@o447623.ingest.us.sentry.io/4509062020333568" - container_name: utools_backend # Eindeutiger Name für den Container + # Verwendet ein bereits gebautes Image + image: ghcr.io/mrunknownde/utools-backend:latest + container_name: utools_backend restart: unless-stopped environment: # Setze Umgebungsvariablen für das Backend @@ -33,7 +27,8 @@ services: # Frontend Service (Nginx) frontend: - build: ./frontend # Pfad zum Verzeichnis mit dem Frontend-Dockerfile + # Verwendet ein bereits gebautes Image + image: ghcr.io/mrunknownde/utools-frontend:latest container_name: utools_frontend restart: unless-stopped ports: @@ -48,4 +43,4 @@ services: # Definiere ein benutzerdefiniertes Netzwerk (gute Praxis) networks: utools_network: - driver: bridge # Standard-Netzwerktreiber \ No newline at end of file + driver: bridge \ No newline at end of file