mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-07-27 07:35:22 +00:00
testing and docker replacements (#3968)
This PR restructures testing scripts and Docker configurations to use centralized compose files, introduces new Docker Compose variants with integrated frontend services, and updates related CI workflows. Migrate test scripts to reference testing/compose files and streamline test flows with forced rebuilds and direct curl checks. Add ultra-lite, security, and security-with-login compose files under testing/compose, each defining both backend and frontend services. Rename and adjust frontend imports and update CI workflows to build and validate the frontend separately.
This commit is contained in:
parent
0742364a03
commit
0549c5b191
214
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
214
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
@ -2,7 +2,7 @@ name: Auto PR V2 Deployment
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened, closed]
|
||||||
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@ -12,6 +12,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-pr:
|
check-pr:
|
||||||
|
if: github.event.action != 'closed'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_deploy: ${{ steps.check-conditions.outputs.should_deploy }}
|
should_deploy: ${{ steps.check-conditions.outputs.should_deploy }}
|
||||||
@ -183,19 +184,8 @@ jobs:
|
|||||||
repository: ${{ needs.check-pr.outputs.pr_repository }}
|
repository: ${{ needs.check-pr.outputs.pr_repository }}
|
||||||
ref: ${{ needs.check-pr.outputs.pr_ref }}
|
ref: ${{ needs.check-pr.outputs.pr_ref }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
fetch-depth: 0 # Fetch full history for commit hash detection
|
||||||
|
|
||||||
- name: Set up JDK
|
|
||||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with:
|
|
||||||
java-version: "17"
|
|
||||||
distribution: "temurin"
|
|
||||||
|
|
||||||
- name: Build backend
|
|
||||||
run: |
|
|
||||||
export DISABLE_ADDITIONAL_FEATURES=true
|
|
||||||
./gradlew clean build
|
|
||||||
env:
|
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
@ -212,13 +202,81 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_API }}
|
password: ${{ secrets.DOCKER_HUB_API }}
|
||||||
|
|
||||||
- name: Build and push V2 monolith image
|
- name: Get commit hashes for frontend and backend
|
||||||
|
id: commit-hashes
|
||||||
|
run: |
|
||||||
|
# Get last commit that touched the frontend folder, docker/frontend, or docker/compose
|
||||||
|
FRONTEND_HASH=$(git log -1 --format="%H" -- frontend/ docker/frontend/ docker/compose/ 2>/dev/null || echo "")
|
||||||
|
if [ -z "$FRONTEND_HASH" ]; then
|
||||||
|
FRONTEND_HASH="no-frontend-changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get last commit that touched backend code, docker/backend, or docker/compose
|
||||||
|
BACKEND_HASH=$(git log -1 --format="%H" -- app/ docker/backend/ docker/compose/ 2>/dev/null || echo "")
|
||||||
|
if [ -z "$BACKEND_HASH" ]; then
|
||||||
|
BACKEND_HASH="no-backend-changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Frontend hash: $FRONTEND_HASH"
|
||||||
|
echo "Backend hash: $BACKEND_HASH"
|
||||||
|
|
||||||
|
echo "frontend_hash=$FRONTEND_HASH" >> $GITHUB_OUTPUT
|
||||||
|
echo "backend_hash=$BACKEND_HASH" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Short hashes for tags
|
||||||
|
if [ "$FRONTEND_HASH" = "no-frontend-changes" ]; then
|
||||||
|
echo "frontend_short=no-frontend" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "frontend_short=${FRONTEND_HASH:0:8}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$BACKEND_HASH" = "no-backend-changes" ]; then
|
||||||
|
echo "backend_short=no-backend" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "backend_short=${BACKEND_HASH:0:8}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check if frontend image exists
|
||||||
|
id: check-frontend
|
||||||
|
run: |
|
||||||
|
if docker manifest inspect ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} >/dev/null 2>&1; then
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Frontend image already exists, skipping build"
|
||||||
|
else
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "Frontend image needs to be built"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check if backend image exists
|
||||||
|
id: check-backend
|
||||||
|
run: |
|
||||||
|
if docker manifest inspect ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} >/dev/null 2>&1; then
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Backend image already exists, skipping build"
|
||||||
|
else
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "Backend image needs to be built"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build and push V2 frontend image
|
||||||
|
if: steps.check-frontend.outputs.exists == 'false'
|
||||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/monolith/Dockerfile
|
file: ./docker/frontend/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }}
|
||||||
|
build-args: VERSION_TAG=v2-alpha
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Build and push V2 backend image
|
||||||
|
if: steps.check-backend.outputs.exists == 'false'
|
||||||
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/backend/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }}
|
||||||
build-args: VERSION_TAG=v2-alpha
|
build-args: VERSION_TAG=v2-alpha
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
@ -233,16 +291,17 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Use same port strategy as regular PRs - just the PR number
|
# Use same port strategy as regular PRs - just the PR number
|
||||||
V2_PORT=${{ needs.check-pr.outputs.pr_number }}
|
V2_PORT=${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
BACKEND_PORT=$((V2_PORT + 10000)) # Backend on higher port to avoid conflicts
|
||||||
|
|
||||||
# Create docker-compose for V2 monolith
|
# Create docker-compose for V2 with separate frontend and backend
|
||||||
cat > docker-compose.yml << EOF
|
cat > docker-compose.yml << EOF
|
||||||
version: '3.3'
|
version: '3.3'
|
||||||
services:
|
services:
|
||||||
stirling-pdf-v2:
|
stirling-pdf-v2-backend:
|
||||||
container_name: stirling-pdf-v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
container_name: stirling-pdf-v2-backend-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }}
|
||||||
ports:
|
ports:
|
||||||
- "${V2_PORT}:80" # Frontend port (same as regular PRs)
|
- "${BACKEND_PORT}:8080" # Backend API port
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/data:/usr/share/tessdata:rw
|
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/data:/usr/share/tessdata:rw
|
||||||
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/config:/configs:rw
|
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/config:/configs:rw
|
||||||
@ -258,6 +317,17 @@ jobs:
|
|||||||
METRICS_ENABLED: "true"
|
METRICS_ENABLED: "true"
|
||||||
SYSTEM_GOOGLEVISIBILITY: "false"
|
SYSTEM_GOOGLEVISIBILITY: "false"
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
|
|
||||||
|
stirling-pdf-v2-frontend:
|
||||||
|
container_name: stirling-pdf-v2-frontend-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }}
|
||||||
|
ports:
|
||||||
|
- "${V2_PORT}:80" # Frontend port (same as regular PRs)
|
||||||
|
environment:
|
||||||
|
VITE_API_BASE_URL: "http://${{ secrets.VPS_HOST }}:${BACKEND_PORT}"
|
||||||
|
depends_on:
|
||||||
|
- stirling-pdf-v2-backend
|
||||||
|
restart: on-failure:5
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Deploy to VPS
|
# Deploy to VPS
|
||||||
@ -280,6 +350,9 @@ jobs:
|
|||||||
|
|
||||||
# Clean up unused Docker resources to save space
|
# Clean up unused Docker resources to save space
|
||||||
docker system prune -af --volumes
|
docker system prune -af --volumes
|
||||||
|
|
||||||
|
# Clean up old backend/frontend images (older than 2 weeks)
|
||||||
|
docker image prune -af --filter "until=336h" --filter "label!=keep=true"
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
# Set port for output
|
# Set port for output
|
||||||
@ -325,3 +398,102 @@ jobs:
|
|||||||
body: commentBody
|
body: commentBody
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cleanup-v2-deployment:
|
||||||
|
if: github.event.action == 'closed'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Setup GitHub App Bot
|
||||||
|
if: github.actor != 'dependabot[bot]'
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Clean up V2 deployment comments
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = ${{ github.event.pull_request.number }};
|
||||||
|
|
||||||
|
// Find and delete V2 deployment comments
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
const v2Comments = comments.filter(c =>
|
||||||
|
c.body?.includes("## 🚀 V2 Auto-Deployment Complete!") &&
|
||||||
|
c.user?.type === "Bot"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const comment of v2Comments) {
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
comment_id: comment.id
|
||||||
|
});
|
||||||
|
console.log(`Deleted V2 deployment comment (ID: ${comment.id})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Set up SSH
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh/
|
||||||
|
echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key
|
||||||
|
sudo chmod 600 ../private.key
|
||||||
|
|
||||||
|
- name: Cleanup V2 deployment
|
||||||
|
run: |
|
||||||
|
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH'
|
||||||
|
if [ -d "/stirling/V2-PR-${{ github.event.pull_request.number }}" ]; then
|
||||||
|
echo "Found V2 PR directory, proceeding with cleanup..."
|
||||||
|
|
||||||
|
# Stop and remove V2 containers
|
||||||
|
cd /stirling/V2-PR-${{ github.event.pull_request.number }}
|
||||||
|
docker-compose down || true
|
||||||
|
|
||||||
|
# Go back to root before removal
|
||||||
|
cd /
|
||||||
|
|
||||||
|
# Remove V2 PR-specific directories
|
||||||
|
rm -rf /stirling/V2-PR-${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
# Clean up V2 containers by name (in case compose cleanup missed them)
|
||||||
|
docker rm -f stirling-pdf-v2-frontend-pr-${{ github.event.pull_request.number }} || true
|
||||||
|
docker rm -f stirling-pdf-v2-backend-pr-${{ github.event.pull_request.number }} || true
|
||||||
|
|
||||||
|
echo "V2 cleanup completed"
|
||||||
|
else
|
||||||
|
echo "V2 PR directory not found, nothing to clean up"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up old unused images (older than 2 weeks) but keep recent ones for reuse
|
||||||
|
docker image prune -af --filter "until=336h" --filter "label!=keep=true"
|
||||||
|
|
||||||
|
# Note: We don't remove the commit-based images since they can be reused across PRs
|
||||||
|
# Only remove PR-specific containers and directories
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
|
- name: Cleanup temporary files
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
rm -f ../private.key
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
@ -14,15 +14,10 @@ docker/
|
|||||||
│ ├── Dockerfile # React/Vite frontend with nginx
|
│ ├── Dockerfile # React/Vite frontend with nginx
|
||||||
│ ├── nginx.conf # Nginx configuration
|
│ ├── nginx.conf # Nginx configuration
|
||||||
│ └── entrypoint.sh # Dynamic backend URL setup
|
│ └── entrypoint.sh # Dynamic backend URL setup
|
||||||
├── monolith/ # Single container setup
|
|
||||||
│ ├── Dockerfile # Combined frontend + backend
|
|
||||||
│ ├── nginx-monolith.conf # Nginx config for monolith
|
|
||||||
│ └── start-monolith.sh # Startup script
|
|
||||||
└── compose/ # Docker Compose files
|
└── compose/ # Docker Compose files
|
||||||
├── docker-compose.yml # Standard setup
|
├── docker-compose.yml # Standard setup
|
||||||
├── docker-compose.ultra-lite.yml # Ultra-lite setup
|
├── docker-compose.ultra-lite.yml # Ultra-lite setup
|
||||||
├── docker-compose.fat.yml # Full-featured setup
|
└── docker-compose.fat.yml # Full-featured setup
|
||||||
└── docker-compose.monolith.yml # Single container setup
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -42,12 +37,6 @@ docker-compose -f docker/compose/docker-compose.ultra-lite.yml up --build
|
|||||||
docker-compose -f docker/compose/docker-compose.fat.yml up --build
|
docker-compose -f docker/compose/docker-compose.fat.yml up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Single Container (Monolith)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Single container with both frontend and backend
|
|
||||||
docker-compose -f docker/compose/docker-compose.monolith.yml up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Access Points
|
## Access Points
|
||||||
|
|
||||||
@ -57,7 +46,7 @@ docker-compose -f docker/compose/docker-compose.monolith.yml up --build
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
- **Backend URL**: Set `BACKEND_URL` environment variable for custom backend locations
|
- **Backend URL**: Set `VITE_API_BASE_URL` environment variable for custom backend locations
|
||||||
- **Custom Ports**: Modify port mappings in docker-compose files
|
- **Custom Ports**: Modify port mappings in docker-compose files
|
||||||
- **Memory Limits**: Adjust memory limits per variant (2G ultra-lite, 4G standard, 6G fat)
|
- **Memory Limits**: Adjust memory limits per variant (2G ultra-lite, 4G standard, 6G fat)
|
||||||
|
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf-monolith:
|
|
||||||
build:
|
|
||||||
context: ../..
|
|
||||||
dockerfile: docker/monolith/Dockerfile
|
|
||||||
container_name: stirling-pdf-monolith
|
|
||||||
restart: on-failure:5
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:80/ && curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "3000:80" # Frontend access
|
|
||||||
- "8080:8080" # Direct backend access (for debugging)
|
|
||||||
volumes:
|
|
||||||
- ../../stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ../../stirling/latest/config:/configs:rw
|
|
||||||
- ../../stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "true"
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Single container Stirling-PDF
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Monolith
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
stirling-data:
|
|
||||||
stirling-config:
|
|
||||||
stirling-logs:
|
|
@ -32,7 +32,7 @@ RUN chmod +x /entrypoint.sh
|
|||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
# Environment variables for flexibility
|
# Environment variables for flexibility
|
||||||
ENV BACKEND_URL=http://backend:8080
|
ENV VITE_API_BASE_URL=http://backend:8080
|
||||||
|
|
||||||
# Use custom entrypoint
|
# Use custom entrypoint
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
@ -1,10 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Set default backend URL if not provided
|
# Set default backend URL if not provided
|
||||||
BACKEND_URL=${BACKEND_URL:-"http://backend:8080"}
|
VITE_API_BASE_URL=${VITE_API_BASE_URL:-"http://backend:8080"}
|
||||||
|
|
||||||
# Replace the placeholder in nginx.conf with the actual backend URL
|
# Replace the placeholder in nginx.conf with the actual backend URL
|
||||||
sed -i "s|\${BACKEND_URL}|${BACKEND_URL}|g" /etc/nginx/nginx.conf
|
sed -i "s|\${VITE_API_BASE_URL}|${VITE_API_BASE_URL}|g" /etc/nginx/nginx.conf
|
||||||
|
|
||||||
# Start nginx
|
# Start nginx
|
||||||
exec nginx -g "daemon off;"
|
exec nginx -g "daemon off;"
|
@ -28,7 +28,7 @@ http {
|
|||||||
|
|
||||||
# Proxy API calls to backend
|
# Proxy API calls to backend
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_pass ${BACKEND_URL}/api/;
|
proxy_pass ${VITE_API_BASE_URL}/api/;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
# Monolith Dockerfile - Frontend + Backend in same container
|
|
||||||
# Build the application
|
|
||||||
FROM gradle:8.14-jdk21 AS build
|
|
||||||
|
|
||||||
COPY build.gradle .
|
|
||||||
COPY settings.gradle .
|
|
||||||
COPY gradlew .
|
|
||||||
COPY gradle gradle/
|
|
||||||
COPY app/core/build.gradle core/.
|
|
||||||
COPY app/common/build.gradle common/.
|
|
||||||
COPY app/proprietary/build.gradle proprietary/.
|
|
||||||
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0
|
|
||||||
|
|
||||||
# Set the working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy the entire project to the working directory
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the application with DISABLE_ADDITIONAL_FEATURES=true
|
|
||||||
RUN DISABLE_ADDITIONAL_FEATURES=true \
|
|
||||||
STIRLING_PDF_DESKTOP_UI=false \
|
|
||||||
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
|
|
||||||
|
|
||||||
# Build frontend
|
|
||||||
FROM node:20-alpine AS frontend-build
|
|
||||||
|
|
||||||
WORKDIR /app/frontend
|
|
||||||
|
|
||||||
# Copy frontend package files
|
|
||||||
COPY frontend/package*.json ./
|
|
||||||
|
|
||||||
# Install frontend dependencies
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copy frontend source
|
|
||||||
COPY frontend/ ./
|
|
||||||
|
|
||||||
# Build frontend
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Main stage - Backend with frontend files
|
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
|
||||||
|
|
||||||
# Copy necessary files
|
|
||||||
COPY scripts /scripts
|
|
||||||
COPY pipeline /pipeline
|
|
||||||
COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
|
||||||
# first /app directory is for the build stage, second is for the final image
|
|
||||||
COPY --from=build /app/app/core/build/libs/*.jar app.jar
|
|
||||||
|
|
||||||
# Copy built frontend files
|
|
||||||
COPY --from=frontend-build /app/frontend/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
ARG VERSION_TAG
|
|
||||||
|
|
||||||
LABEL org.opencontainers.image.title="Stirling-PDF Monolith"
|
|
||||||
LABEL org.opencontainers.image.description="Single container with both frontend and backend for Stirling-PDF"
|
|
||||||
LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF"
|
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
|
||||||
LABEL org.opencontainers.image.vendor="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.url="https://www.stirlingpdf.com"
|
|
||||||
LABEL org.opencontainers.image.documentation="https://docs.stirlingpdf.com"
|
|
||||||
LABEL maintainer="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.authors="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.version="${VERSION_TAG}"
|
|
||||||
LABEL org.opencontainers.image.keywords="PDF, manipulation, monolith, single-container"
|
|
||||||
|
|
||||||
# Set Environment Variables
|
|
||||||
ENV DISABLE_ADDITIONAL_FEATURES=true \
|
|
||||||
VERSION_TAG=$VERSION_TAG \
|
|
||||||
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
|
|
||||||
JAVA_CUSTOM_OPTS="" \
|
|
||||||
HOME=/home/stirlingpdfuser \
|
|
||||||
PUID=1000 \
|
|
||||||
PGID=1000 \
|
|
||||||
UMASK=022 \
|
|
||||||
PYTHONPATH=/usr/lib/libreoffice/program:/opt/venv/lib/python3.12/site-packages \
|
|
||||||
UNO_PATH=/usr/lib/libreoffice/program \
|
|
||||||
URE_BOOTSTRAP=file:///usr/lib/libreoffice/program/fundamentalrc \
|
|
||||||
PATH=$PATH:/opt/venv/bin \
|
|
||||||
STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \
|
|
||||||
TMPDIR=/tmp/stirling-pdf \
|
|
||||||
TEMP=/tmp/stirling-pdf \
|
|
||||||
TMP=/tmp/stirling-pdf
|
|
||||||
|
|
||||||
# Install nginx and all dependencies
|
|
||||||
RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
|
||||||
echo "@community https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
|
||||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
|
|
||||||
apk upgrade --no-cache -a && \
|
|
||||||
apk add --no-cache \
|
|
||||||
ca-certificates \
|
|
||||||
tzdata \
|
|
||||||
tini \
|
|
||||||
bash \
|
|
||||||
curl \
|
|
||||||
shadow \
|
|
||||||
su-exec \
|
|
||||||
openssl \
|
|
||||||
openssl-dev \
|
|
||||||
openjdk21-jre \
|
|
||||||
nginx \
|
|
||||||
# Doc conversion
|
|
||||||
gcompat \
|
|
||||||
libc6-compat \
|
|
||||||
libreoffice \
|
|
||||||
# pdftohtml
|
|
||||||
poppler-utils \
|
|
||||||
# OCR MY PDF (unpaper for descew and other advanced features)
|
|
||||||
unpaper \
|
|
||||||
tesseract-ocr-data-eng \
|
|
||||||
tesseract-ocr-data-chi_sim \
|
|
||||||
tesseract-ocr-data-deu \
|
|
||||||
tesseract-ocr-data-fra \
|
|
||||||
tesseract-ocr-data-por \
|
|
||||||
ocrmypdf \
|
|
||||||
# CV
|
|
||||||
py3-opencv \
|
|
||||||
python3 \
|
|
||||||
py3-pip \
|
|
||||||
py3-pillow@testing \
|
|
||||||
py3-pdf2image@testing && \
|
|
||||||
python3 -m venv /opt/venv && \
|
|
||||||
/opt/venv/bin/pip install --upgrade pip setuptools && \
|
|
||||||
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
|
||||||
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
|
||||||
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
|
||||||
ln -s /usr/lib/libreoffice/program /opt/venv/lib/python3.12/site-packages/LibreOffice && \
|
|
||||||
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
|
||||||
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders /tmp/stirling-pdf && \
|
|
||||||
fc-cache -f -v && \
|
|
||||||
chmod +x /scripts/* && \
|
|
||||||
chmod +x /scripts/init.sh && \
|
|
||||||
# User permissions
|
|
||||||
addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
|
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /tmp/stirling-pdf && \
|
|
||||||
chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
|
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/nginx/html
|
|
||||||
|
|
||||||
# Copy nginx configuration for monolith
|
|
||||||
COPY docker/monolith/nginx-monolith.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
# Copy startup script
|
|
||||||
COPY docker/monolith/start-monolith.sh /start-monolith.sh
|
|
||||||
RUN chmod +x /start-monolith.sh
|
|
||||||
|
|
||||||
# Expose both ports
|
|
||||||
EXPOSE 80 8080
|
|
||||||
|
|
||||||
# Set user and run command
|
|
||||||
ENTRYPOINT ["tini", "--"]
|
|
||||||
CMD ["/start-monolith.sh"]
|
|
@ -1,49 +0,0 @@
|
|||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
# Gzip compression
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name _;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
|
|
||||||
# Handle client-side routing - support subpaths
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Proxy API calls to backend running on same container
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:8080/api/;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Port $server_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Cache static assets
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
|
||||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Start the Java backend in the background
|
|
||||||
echo "Starting Java backend..."
|
|
||||||
su-exec stirlingpdfuser:stirlingpdfgroup bash -c "
|
|
||||||
cd /home/stirlingpdfuser && \
|
|
||||||
java -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/tmp/stirling-pdf -jar /app.jar &
|
|
||||||
/opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1 &
|
|
||||||
"
|
|
||||||
|
|
||||||
# Wait for backend to start
|
|
||||||
echo "Waiting for backend to start..."
|
|
||||||
until curl -f http://localhost:8080/api/v1/info/status >/dev/null 2>&1; do
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Backend started, starting nginx..."
|
|
||||||
|
|
||||||
# Start nginx in the foreground
|
|
||||||
nginx -g "daemon off;"
|
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||||
|
|
||||||
|
## Docker Setup
|
||||||
|
|
||||||
|
For Docker deployments and configuration, see the [Docker README](../docker/README.md).
|
||||||
|
|
||||||
## Available Scripts
|
## Available Scripts
|
||||||
|
|
||||||
In the project directory, you can run:
|
In the project directory, you can run:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user