chore: configure docker-compose for homelab with task2.beetech.dev domain
- Replace archived MinIO images with community-maintained pgsty images - Change routing domain to task2.beetech.dev across frontend, backend, and minio - Avoid port collisions with existing homelab services (postgres port 5434) - Add .env and *.pem to .gitignore - Remove legacy deploy/ directory and deploy-main.yml workflow
This commit is contained in:
parent
437dbbe052
commit
791d184954
7 changed files with 86 additions and 284 deletions
158
.github/workflows/deploy-main.yml
vendored
158
.github/workflows/deploy-main.yml
vendored
|
|
@ -1,158 +0,0 @@
|
|||
name: Deploy to Hostinger
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
FRONTEND_IMAGE_NAME: ${{ github.repository }}-frontend
|
||||
BACKEND_IMAGE_NAME: ${{ github.repository }}-backend
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
cache: maven
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
# - name: Run backend tests
|
||||
# working-directory: backend
|
||||
# run: ./mvnw -B test
|
||||
|
||||
- name: Run frontend build
|
||||
working-directory: frontend
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract Docker metadata for frontend
|
||||
id: meta-frontend
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha
|
||||
|
||||
- name: Extract Docker metadata for backend
|
||||
id: meta-backend
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push frontend image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./frontend
|
||||
file: ./frontend/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta-frontend.outputs.tags }}
|
||||
labels: ${{ steps.meta-frontend.outputs.labels }}
|
||||
build-args: |
|
||||
VITE_API_URL=${{ secrets.FRONTEND_VITE_API_URL }}
|
||||
|
||||
- name: Build and push backend image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./backend
|
||||
file: ./backend/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta-backend.outputs.tags }}
|
||||
labels: ${{ steps.meta-backend.outputs.labels }}
|
||||
|
||||
- name: Copy deploy files to server
|
||||
uses: appleboy/scp-action@v0.1.7
|
||||
with:
|
||||
host: ${{ secrets.HOSTINGER_HOST }}
|
||||
username: ${{ secrets.HOSTINGER_USER }}
|
||||
key: ${{ secrets.HOSTINGER_SSH_KEY }}
|
||||
port: ${{ secrets.HOSTINGER_PORT || 22 }}
|
||||
source: "deploy/docker-compose.prod.yml"
|
||||
target: "${{ secrets.HOSTINGER_APP_PATH }}"
|
||||
strip_components: 1
|
||||
|
||||
- name: Deploy on Hostinger
|
||||
uses: appleboy/ssh-action@v1.2.0
|
||||
env:
|
||||
FRONTEND_IMAGE: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest
|
||||
BACKEND_IMAGE: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest
|
||||
POSTGRES_USER: ${{ secrets.POSTGRES_USER }}
|
||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
DB_URL: ${{ secrets.DB_URL }}
|
||||
MP_JWT_VERIFY_ISSUER: ${{ secrets.MP_JWT_VERIFY_ISSUER }}
|
||||
SMALLRYE_JWT_SIGN_KEY: ${{ secrets.SMALLRYE_JWT_SIGN_KEY }}
|
||||
MP_JWT_VERIFY_PUBLICKEY: ${{ secrets.MP_JWT_VERIFY_PUBLICKEY }}
|
||||
GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }}
|
||||
GHCR_TOKEN: ${{ secrets.GHCR_READ_TOKEN }}
|
||||
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
|
||||
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
|
||||
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
||||
MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
|
||||
MINIO_BUCKET: ${{ secrets.MINIO_BUCKET }}
|
||||
with:
|
||||
host: ${{ secrets.HOSTINGER_HOST }}
|
||||
username: ${{ secrets.HOSTINGER_USER }}
|
||||
key: ${{ secrets.HOSTINGER_SSH_KEY }}
|
||||
port: ${{ secrets.HOSTINGER_PORT || 22 }}
|
||||
envs: FRONTEND_IMAGE,BACKEND_IMAGE,POSTGRES_USER,POSTGRES_PASSWORD,DB_URL,MP_JWT_VERIFY_ISSUER,SMALLRYE_JWT_SIGN_KEY,MP_JWT_VERIFY_PUBLICKEY,GHCR_USERNAME,GHCR_TOKEN,MINIO_ROOT_USER,MINIO_ROOT_PASSWORD,MINIO_ENDPOINT,MINIO_PUBLIC_URL,MINIO_BUCKET
|
||||
script: |
|
||||
set -eu
|
||||
APP_DIR="${{ secrets.HOSTINGER_APP_PATH }}"
|
||||
mkdir -p "$APP_DIR"
|
||||
cd "$APP_DIR"
|
||||
|
||||
{
|
||||
echo "POSTGRES_USER=${POSTGRES_USER}"
|
||||
echo "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}"
|
||||
echo "DB_URL=${DB_URL}"
|
||||
echo "FRONTEND_IMAGE=${FRONTEND_IMAGE}"
|
||||
echo "BACKEND_IMAGE=${BACKEND_IMAGE}"
|
||||
echo "MP_JWT_VERIFY_ISSUER=${MP_JWT_VERIFY_ISSUER}"
|
||||
echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}"
|
||||
echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}"
|
||||
echo "MINIO_ENDPOINT=${MINIO_ENDPOINT}"
|
||||
echo "MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}"
|
||||
echo "MINIO_BUCKET=${MINIO_BUCKET}"
|
||||
|
||||
printf 'SMALLRYE_JWT_SIGN_KEY="%s"\n' "$SMALLRYE_JWT_SIGN_KEY"
|
||||
printf 'MP_JWT_VERIFY_PUBLICKEY="%s"\n' "$MP_JWT_VERIFY_PUBLICKEY"
|
||||
} > .env.production
|
||||
|
||||
echo "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
|
||||
docker compose --env-file .env.production -f docker-compose.prod.yml pull
|
||||
docker compose --env-file .env.production -f docker-compose.prod.yml up -d
|
||||
docker image prune -f
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
|||
.agents
|
||||
.DS_Store
|
||||
.vscode
|
||||
.env
|
||||
*.pem
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
quarkus.http.port=8081
|
||||
|
||||
quarkus.http.cors.enabled=true
|
||||
quarkus.http.cors.origins=https://task.beetech.dev
|
||||
quarkus.http.cors.origins=https://task2.beetech.dev
|
||||
quarkus.http.cors.methods=GET,PUT,POST,DELETE,PATCH,OPTIONS
|
||||
quarkus.http.cors.exposed-headers=Content-Disposition
|
||||
quarkus.http.cors.access-control-max-age=24H
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
POSTGRES_USER=beetask
|
||||
POSTGRES_PASSWORD=change-me
|
||||
DB_URL=jdbc:postgresql://203.0.113.10:5432/beetask
|
||||
|
||||
BACKEND_IMAGE=ghcr.io/owner/repo-backend:latest
|
||||
FRONTEND_IMAGE=ghcr.io/owner/repo-frontend:latest
|
||||
|
||||
QUARKUS_HTTP_CORS_ORIGINS=https://app.example.com
|
||||
MP_JWT_VERIFY_ISSUER=https://beetech.net
|
||||
SMALLRYE_JWT_SIGN_KEY_LOCATION=privateKey.pem
|
||||
MP_JWT_VERIFY_PUBLICKEY_LOCATION=publicKey.pem
|
||||
|
||||
# MinIO (object storage for user avatars)
|
||||
# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are used both by the MinIO service
|
||||
# and by the backend as access/secret keys.
|
||||
MINIO_ROOT_USER=change-me
|
||||
MINIO_ROOT_PASSWORD=change-me
|
||||
MINIO_ENDPOINT=http://minio:9000
|
||||
MINIO_PUBLIC_URL=https://minio.task.beetech.dev
|
||||
MINIO_BUCKET=avatars
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
container_name: bee-task-postgres
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-beetask}
|
||||
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
backend:
|
||||
image: ${BACKEND_IMAGE}
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
DB_USER: ${POSTGRES_USER}
|
||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
DB_URL: ${DB_URL}
|
||||
MP_JWT_VERIFY_ISSUER: ${MP_JWT_VERIFY_ISSUER}
|
||||
SMALLRYE_JWT_SIGN_KEY: ${SMALLRYE_JWT_SIGN_KEY}
|
||||
MP_JWT_VERIFY_PUBLICKEY: ${MP_JWT_VERIFY_PUBLICKEY}
|
||||
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
|
||||
MINIO_ACCESS_KEY: ${MINIO_ROOT_USER}
|
||||
MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
MINIO_PUBLIC_URL: ${MINIO_PUBLIC_URL}
|
||||
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.backend.rule=Host(`api.task.beetech.dev`)"
|
||||
- "traefik.http.routers.backend.entrypoints=websecure"
|
||||
- "traefik.http.routers.backend.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.backend.loadbalancer.server.port=8081"
|
||||
|
||||
frontend:
|
||||
image: ${FRONTEND_IMAGE}
|
||||
restart: unless-stopped
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.frontend.rule=Host(`task.beetech.dev`)"
|
||||
- "traefik.http.routers.frontend.entrypoints=websecure"
|
||||
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.frontend.loadbalancer.server.port=80"
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
restart: unless-stopped
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.minio.rule=Host(`minio.task.beetech.dev`)"
|
||||
- "traefik.http.routers.minio.entrypoints=websecure"
|
||||
- "traefik.http.routers.minio.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.minio.loadbalancer.server.port=9000"
|
||||
|
||||
minio-init:
|
||||
image: minio/mc:latest
|
||||
depends_on:
|
||||
- minio
|
||||
restart: on-failure
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
sleep 3 &&
|
||||
mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD &&
|
||||
mc mb --ignore-existing local/avatars &&
|
||||
mc anonymous set download local/avatars
|
||||
"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
|
|
@ -3,42 +3,49 @@ services:
|
|||
image: postgres:16
|
||||
container_name: bee-task-postgres
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
POSTGRES_USER: beetask
|
||||
POSTGRES_PASSWORD: beetask
|
||||
POSTGRES_DB: beetask
|
||||
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
- "5434:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U beetask"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- internal
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
image: pgsty/minio:latest
|
||||
restart: unless-stopped
|
||||
command: server /data --console-address ":9001"
|
||||
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-beetask123}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-beetaskpassword}
|
||||
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
networks:
|
||||
- proxy
|
||||
- internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.routers.minio.rule=Host(`minio.task2.beetech.dev`)"
|
||||
- "traefik.http.routers.minio.entrypoints=web"
|
||||
- "traefik.http.services.minio.loadbalancer.server.port=9000"
|
||||
- "traefik.http.routers.minio-console.rule=Host(`console.minio.task2.beetech.dev`)"
|
||||
- "traefik.http.routers.minio-console.entrypoints=web"
|
||||
- "traefik.http.services.minio-console.loadbalancer.server.port=9001"
|
||||
|
||||
minio-init:
|
||||
image: minio/mc:latest
|
||||
image: pgsty/mc:latest
|
||||
depends_on:
|
||||
- minio
|
||||
restart: on-failure
|
||||
|
|
@ -52,7 +59,71 @@ services:
|
|||
mc mb --ignore-existing local/avatars &&
|
||||
mc anonymous set download local/avatars
|
||||
"
|
||||
networks:
|
||||
- internal
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: bee-task-backend
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "8081"
|
||||
environment:
|
||||
DB_USER: beetask
|
||||
DB_PASSWORD: beetask
|
||||
DB_URL: jdbc:postgresql://postgres:5432/beetask
|
||||
QUARKUS_HTTP_CORS_ORIGINS: https://task2.beetech.dev
|
||||
MP_JWT_VERIFY_ISSUER: ${MP_JWT_VERIFY_ISSUER}
|
||||
SMALLRYE_JWT_SIGN_KEY: ${SMALLRYE_JWT_SIGN_KEY}
|
||||
MP_JWT_VERIFY_PUBLICKEY: ${MP_JWT_VERIFY_PUBLICKEY}
|
||||
MINIO_ENDPOINT: http://minio:9000
|
||||
MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-beetask123}
|
||||
MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-beetaskpassword}
|
||||
MINIO_BUCKET: avatars
|
||||
MINIO_PUBLIC_URL: http://localhost:9000
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- proxy
|
||||
- internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.routers.backend.rule=Host(`api.task2.beetech.dev`)"
|
||||
- "traefik.http.routers.backend.entrypoints=web"
|
||||
- "traefik.http.services.backend.loadbalancer.server.port=8081"
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
VITE_API_URL: ${VITE_API_URL:-https://api.task2.beetech.dev}
|
||||
container_name: bee-task-frontend
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "80"
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- proxy
|
||||
- internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=proxy"
|
||||
- "traefik.http.routers.frontend.rule=Host(`task2.beetech.dev`)"
|
||||
- "traefik.http.routers.frontend.entrypoints=web"
|
||||
- "traefik.http.services.frontend.loadbalancer.server.port=80"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
minio_data:
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
internal:
|
||||
driver: bridge
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
VITE_API_URL=https://api.task.beetech.dev
|
||||
VITE_API_URL=https://api.task2.beetech.dev
|
||||
|
|
|
|||
Loading…
Reference in a new issue