mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-07-27 15:45:21 +00:00
V2 docker support react version2 (#3930)
# Description of Changes <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: a <a>
This commit is contained in:
parent
50d745225c
commit
21210850ec
310
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
Normal file
310
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
name: Auto PR V2 Deployment
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
should_deploy: ${{ steps.check-conditions.outputs.should_deploy }}
|
||||||
|
pr_number: ${{ github.event.number }}
|
||||||
|
pr_repository: ${{ steps.get-pr-info.outputs.repository }}
|
||||||
|
pr_ref: ${{ steps.get-pr-info.outputs.ref }}
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Check deployment conditions
|
||||||
|
id: check-conditions
|
||||||
|
env:
|
||||||
|
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||||
|
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||||
|
PR_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||||
|
run: |
|
||||||
|
echo "PR Title: $PR_TITLE"
|
||||||
|
echo "PR Author: $PR_AUTHOR"
|
||||||
|
echo "PR Branch: $PR_BRANCH"
|
||||||
|
|
||||||
|
# Check if author is authorized
|
||||||
|
authorized_users=(
|
||||||
|
"Frooodle"
|
||||||
|
"sf298"
|
||||||
|
"Ludy87"
|
||||||
|
"LaserKaspar"
|
||||||
|
"sbplat"
|
||||||
|
"reecebrowne"
|
||||||
|
"DarioGii"
|
||||||
|
"ConnorYoh"
|
||||||
|
)
|
||||||
|
|
||||||
|
is_authorized=false
|
||||||
|
for user in "${authorized_users[@]}"; do
|
||||||
|
if [[ "$PR_AUTHOR" == "$user" ]]; then
|
||||||
|
is_authorized=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if title contains V2/version2 keywords (case insensitive)
|
||||||
|
has_v2_keyword=false
|
||||||
|
if [[ "$PR_TITLE" =~ [Vv]2 ]] || [[ "$PR_TITLE" =~ [Vv]ersion.?2 ]] || [[ "$PR_TITLE" =~ [Vv]ersion.?[Tt]wo ]]; then
|
||||||
|
has_v2_keyword=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if branch name contains V2 or react keywords (case insensitive)
|
||||||
|
has_branch_keyword=false
|
||||||
|
if [[ "$PR_BRANCH" =~ [Vv]2 ]] || [[ "$PR_BRANCH" =~ [Rr]eact ]]; then
|
||||||
|
has_branch_keyword=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$is_authorized" == "true" ]] && [[ "$has_v2_keyword" == "true" || "$has_branch_keyword" == "true" ]]; then
|
||||||
|
echo "✅ Deployment conditions met"
|
||||||
|
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "❌ Deployment conditions not met"
|
||||||
|
echo " - Authorized user: $is_authorized"
|
||||||
|
echo " - Has V2 keyword in title: $has_v2_keyword"
|
||||||
|
echo " - Has V2/React keyword in branch: $has_branch_keyword"
|
||||||
|
echo "should_deploy=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Get PR repository and ref
|
||||||
|
id: get-pr-info
|
||||||
|
if: steps.check-conditions.outputs.should_deploy == 'true'
|
||||||
|
run: |
|
||||||
|
# For forks, use the full repository name, for internal PRs use the current repo
|
||||||
|
if [[ "${{ github.event.pull_request.head.repo.fork }}" == "true" ]]; then
|
||||||
|
repository="${{ github.event.pull_request.head.repo.full_name }}"
|
||||||
|
else
|
||||||
|
repository="${{ github.repository }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "repository=$repository" >> $GITHUB_OUTPUT
|
||||||
|
echo "ref=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
deploy-v2-pr:
|
||||||
|
needs: check-pr
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: needs.check-pr.outputs.should_deploy == 'true'
|
||||||
|
# Concurrency control - only one deployment per PR at a time
|
||||||
|
concurrency:
|
||||||
|
group: v2-deploy-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Generate GitHub App Token
|
||||||
|
id: generate-token
|
||||||
|
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Add deployment started comment
|
||||||
|
id: deployment-started
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = ${{ needs.check-pr.outputs.pr_number }};
|
||||||
|
|
||||||
|
// Delete previous V2 deployment comments to avoid clutter
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
per_page: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
const v2Comments = comments.filter(comment =>
|
||||||
|
comment.body.includes('🚀 **Auto-deploying V2 version**') ||
|
||||||
|
comment.body.includes('## 🚀 V2 Auto-Deployment Complete!') ||
|
||||||
|
comment.body.includes('❌ **V2 Auto-deployment failed**')
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const comment of v2Comments) {
|
||||||
|
console.log(`Deleting old V2 comment: ${comment.id}`);
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
comment_id: comment.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new deployment started comment
|
||||||
|
const { data: newComment } = await github.rest.issues.createComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
body: `🚀 **Auto-deploying V2 version** for PR #${prNumber}...\n\n_This is an automated deployment triggered by V2/version2 keywords in the PR title or V2/React keywords in the branch name._\n\n⚠️ **Note:** If new commits are pushed during deployment, this build will be cancelled and replaced with the latest version.`
|
||||||
|
});
|
||||||
|
|
||||||
|
return newComment.id;
|
||||||
|
|
||||||
|
- name: Checkout PR
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
repository: ${{ needs.check-pr.outputs.pr_repository }}
|
||||||
|
ref: ${{ needs.check-pr.outputs.pr_ref }}
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- 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
|
||||||
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
|
|
||||||
|
- name: Get version number
|
||||||
|
id: versionNumber
|
||||||
|
run: |
|
||||||
|
VERSION=$(grep "^version =" build.gradle | awk -F'"' '{print $2}')
|
||||||
|
echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_API }}
|
||||||
|
|
||||||
|
- name: Build and push V2 monolith image
|
||||||
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/monolith/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
build-args: VERSION_TAG=v2-alpha
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Set up SSH
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh/
|
||||||
|
echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key
|
||||||
|
sudo chmod 600 ../private.key
|
||||||
|
|
||||||
|
- name: Deploy V2 to VPS
|
||||||
|
id: deploy
|
||||||
|
run: |
|
||||||
|
# Use same port strategy as regular PRs - just the PR number
|
||||||
|
V2_PORT=${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
|
||||||
|
# Create docker-compose for V2 monolith
|
||||||
|
cat > docker-compose.yml << EOF
|
||||||
|
version: '3.3'
|
||||||
|
services:
|
||||||
|
stirling-pdf-v2:
|
||||||
|
container_name: stirling-pdf-v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
ports:
|
||||||
|
- "${V2_PORT}:80" # Frontend port (same as regular PRs)
|
||||||
|
volumes:
|
||||||
|
- /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 }}/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
SYSTEM_DEFAULTLOCALE: en-GB
|
||||||
|
UI_APPNAME: "Stirling-PDF V2 PR#${{ needs.check-pr.outputs.pr_number }}"
|
||||||
|
UI_HOMEDESCRIPTION: "V2 PR#${{ needs.check-pr.outputs.pr_number }} - Frontend/Backend Split Architecture"
|
||||||
|
UI_APPNAMENAVBAR: "V2 PR#${{ needs.check-pr.outputs.pr_number }}"
|
||||||
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "false"
|
||||||
|
restart: on-failure:5
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Deploy to VPS
|
||||||
|
scp -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null docker-compose.yml ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }}:/tmp/docker-compose-v2.yml
|
||||||
|
|
||||||
|
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << ENDSSH
|
||||||
|
# Create V2 PR-specific directories
|
||||||
|
mkdir -p /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/{data,config,logs}
|
||||||
|
|
||||||
|
# Move docker-compose file to correct location
|
||||||
|
mv /tmp/docker-compose-v2.yml /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/docker-compose.yml
|
||||||
|
|
||||||
|
# Stop any existing container and clean up
|
||||||
|
cd /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
docker-compose down --remove-orphans 2>/dev/null || true
|
||||||
|
|
||||||
|
# Start the new container
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Clean up unused Docker resources to save space
|
||||||
|
docker system prune -af --volumes
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
|
# Set port for output
|
||||||
|
echo "v2_port=${V2_PORT}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Post V2 deployment URL to PR
|
||||||
|
if: success()
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = ${{ needs.check-pr.outputs.pr_number }};
|
||||||
|
const v2Port = ${{ steps.deploy.outputs.v2_port }};
|
||||||
|
|
||||||
|
// Delete the "deploying..." comment since we're posting the final result
|
||||||
|
const deploymentStartedId = ${{ steps.deployment-started.outputs.result }};
|
||||||
|
if (deploymentStartedId) {
|
||||||
|
console.log(`Deleting deployment started comment: ${deploymentStartedId}`);
|
||||||
|
try {
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
comment_id: deploymentStartedId
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`Could not delete deployment started comment: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deploymentUrl = `http://${{ secrets.VPS_HOST }}:${v2Port}`;
|
||||||
|
|
||||||
|
const commentBody = `## 🚀 V2 Auto-Deployment Complete!\n\n` +
|
||||||
|
`Your V2 PR with the new frontend/backend split architecture has been deployed!\n\n` +
|
||||||
|
`🔗 **V2 Test URL:** [${deploymentUrl}](${deploymentUrl})\n\n` +
|
||||||
|
`_This deployment will be automatically cleaned up when the PR is closed._\n\n` +
|
||||||
|
`🔄 **Auto-deployed** because PR title or branch name contains V2/version2/React keywords.`;
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
body: commentBody
|
||||||
|
});
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,6 +27,7 @@ clientWebUI/
|
|||||||
!cucumber/exampleFiles/
|
!cucumber/exampleFiles/
|
||||||
!cucumber/exampleFiles/example_html.zip
|
!cucumber/exampleFiles/example_html.zip
|
||||||
exampleYmlFiles/stirling/
|
exampleYmlFiles/stirling/
|
||||||
|
stirling/
|
||||||
/testing/file_snapshots
|
/testing/file_snapshots
|
||||||
SwaggerDoc.json
|
SwaggerDoc.json
|
||||||
|
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
# dockerfile.dev
|
|
||||||
|
|
||||||
# Basisimage: Gradle mit JDK 17 (Debian-basiert)
|
|
||||||
FROM gradle:8.14-jdk17
|
|
||||||
|
|
||||||
# Als Root-Benutzer arbeiten, um benötigte Pakete zu installieren
|
|
||||||
USER root
|
|
||||||
|
|
||||||
# Set GRADLE_HOME und füge Gradle zum PATH hinzu
|
|
||||||
ENV GRADLE_HOME=/opt/gradle
|
|
||||||
ENV PATH="$GRADLE_HOME/bin:$PATH"
|
|
||||||
|
|
||||||
# Update und Installation zusätzlicher Pakete (Debian/Ubuntu-basiert)
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
sudo \
|
|
||||||
libreoffice \
|
|
||||||
poppler-utils \
|
|
||||||
qpdf \
|
|
||||||
# settings.yml | tessdataDir: /usr/share/tesseract-ocr/5/tessdata
|
|
||||||
tesseract-ocr \
|
|
||||||
tesseract-ocr-eng \
|
|
||||||
fonts-terminus fonts-dejavu fonts-font-awesome fonts-noto fonts-noto-core fonts-noto-cjk fonts-noto-extra fonts-liberation fonts-linuxlibertine \
|
|
||||||
python3-uno \
|
|
||||||
python3-venv \
|
|
||||||
# ss -tln
|
|
||||||
iproute2 \
|
|
||||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Setze die Environment Variable für setuptools
|
|
||||||
ENV SETUPTOOLS_USE_DISTUTILS=local \
|
|
||||||
STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \
|
|
||||||
TMPDIR=/tmp/stirling-pdf \
|
|
||||||
TEMP=/tmp/stirling-pdf \
|
|
||||||
TMP=/tmp/stirling-pdf
|
|
||||||
|
|
||||||
# Installation der benötigten Python-Pakete
|
|
||||||
RUN python3 -m venv --system-site-packages /opt/venv \
|
|
||||||
&& . /opt/venv/bin/activate \
|
|
||||||
&& pip install --upgrade pip setuptools \
|
|
||||||
&& pip install --no-cache-dir WeasyPrint pdf2image pillow unoserver opencv-python-headless pre-commit
|
|
||||||
|
|
||||||
# Füge den venv-Pfad zur globalen PATH-Variable hinzu, damit die Tools verfügbar sind
|
|
||||||
ENV PATH="/opt/venv/bin:$PATH"
|
|
||||||
|
|
||||||
COPY . /workspace
|
|
||||||
|
|
||||||
RUN mkdir -p /tmp/stirling-pdf \
|
|
||||||
&& adduser --disabled-password --gecos '' devuser \
|
|
||||||
&& chown -R devuser:devuser /home/devuser /workspace /tmp/stirling-pdf
|
|
||||||
RUN echo "devuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/devuser \
|
|
||||||
&& chmod 0440 /etc/sudoers.d/devuser
|
|
||||||
|
|
||||||
# Setze das Arbeitsverzeichnis (wird später per Bind-Mount überschrieben)
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
RUN chmod +x /workspace/.devcontainer/git-init.sh
|
|
||||||
RUN sudo chmod +x /workspace/.devcontainer/init-setup.sh
|
|
||||||
|
|
||||||
# Wechsel zum Nicht‑Root Benutzer
|
|
||||||
USER devuser
|
|
67
docker/README.md
Normal file
67
docker/README.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Docker Setup for Stirling-PDF
|
||||||
|
|
||||||
|
This directory contains the organized Docker configurations for the split frontend/backend architecture.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
docker/
|
||||||
|
├── backend/ # Backend Docker files
|
||||||
|
│ ├── Dockerfile # Standard backend
|
||||||
|
│ ├── Dockerfile.ultra-lite # Minimal backend
|
||||||
|
│ └── Dockerfile.fat # Full-featured backend
|
||||||
|
├── frontend/ # Frontend Docker files
|
||||||
|
│ ├── Dockerfile # React/Vite frontend with nginx
|
||||||
|
│ ├── nginx.conf # Nginx configuration
|
||||||
|
│ └── 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
|
||||||
|
├── docker-compose.yml # Standard setup
|
||||||
|
├── docker-compose.ultra-lite.yml # Ultra-lite setup
|
||||||
|
├── docker-compose.fat.yml # Full-featured setup
|
||||||
|
└── docker-compose.monolith.yml # Single container setup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Separate Containers (Recommended)
|
||||||
|
|
||||||
|
From the project root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard version
|
||||||
|
docker-compose -f docker/compose/docker-compose.yml up --build
|
||||||
|
|
||||||
|
# Ultra-lite version
|
||||||
|
docker-compose -f docker/compose/docker-compose.ultra-lite.yml up --build
|
||||||
|
|
||||||
|
# Fat version
|
||||||
|
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
|
||||||
|
|
||||||
|
- **Frontend**: http://localhost:3000
|
||||||
|
- **Backend API (debugging)**: http://localhost:8080 (TODO: Remove in production)
|
||||||
|
- **Backend API (via frontend)**: http://localhost:3000/api/*
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- **Backend URL**: Set `BACKEND_URL` environment variable for custom backend locations
|
||||||
|
- **Custom Ports**: Modify port mappings in docker-compose files
|
||||||
|
- **Memory Limits**: Adjust memory limits per variant (2G ultra-lite, 4G standard, 6G fat)
|
||||||
|
|
||||||
|
## Development vs Production
|
||||||
|
|
||||||
|
- **Development**: Keep backend port 8080 exposed for debugging
|
||||||
|
- **Production**: Remove backend port exposure, use only frontend proxy
|
@ -1,4 +1,4 @@
|
|||||||
# Main stage
|
# Backend Dockerfile - Java Spring Boot with all dependencies
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
@ -9,8 +9,8 @@ COPY stirling-pdf/build/libs/*.jar app.jar
|
|||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
|
|
||||||
LABEL org.opencontainers.image.title="Stirling-PDF"
|
LABEL org.opencontainers.image.title="Stirling-PDF Backend"
|
||||||
LABEL org.opencontainers.image.description="A powerful locally hosted web-based PDF manipulation tool supporting 50+ operations including merging, splitting, conversion, OCR, watermarking, and more."
|
LABEL org.opencontainers.image.description="Backend service for Stirling-PDF - Java Spring Boot with PDF processing capabilities"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF"
|
LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF"
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
LABEL org.opencontainers.image.licenses="MIT"
|
||||||
LABEL org.opencontainers.image.vendor="Stirling-Tools"
|
LABEL org.opencontainers.image.vendor="Stirling-Tools"
|
||||||
@ -19,7 +19,7 @@ LABEL org.opencontainers.image.documentation="https://docs.stirlingpdf.com"
|
|||||||
LABEL maintainer="Stirling-Tools"
|
LABEL maintainer="Stirling-Tools"
|
||||||
LABEL org.opencontainers.image.authors="Stirling-Tools"
|
LABEL org.opencontainers.image.authors="Stirling-Tools"
|
||||||
LABEL org.opencontainers.image.version="${VERSION_TAG}"
|
LABEL org.opencontainers.image.version="${VERSION_TAG}"
|
||||||
LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark"
|
LABEL org.opencontainers.image.keywords="PDF, manipulation, backend, API, Spring Boot"
|
||||||
|
|
||||||
# Set Environment Variables
|
# Set Environment Variables
|
||||||
ENV DISABLE_ADDITIONAL_FEATURES=true \
|
ENV DISABLE_ADDITIONAL_FEATURES=true \
|
||||||
@ -39,8 +39,7 @@ ENV DISABLE_ADDITIONAL_FEATURES=true \
|
|||||||
TEMP=/tmp/stirling-pdf \
|
TEMP=/tmp/stirling-pdf \
|
||||||
TMP=/tmp/stirling-pdf
|
TMP=/tmp/stirling-pdf
|
||||||
|
|
||||||
|
# JDK for app and all dependencies
|
||||||
# JDK for app
|
|
||||||
RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
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 "@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 && \
|
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
|
||||||
@ -95,4 +94,4 @@ EXPOSE 8080/tcp
|
|||||||
|
|
||||||
# Set user and run command
|
# Set user and run command
|
||||||
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
||||||
CMD ["sh", "-c", "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"]
|
CMD ["sh", "-c", "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"]
|
@ -1,3 +1,4 @@
|
|||||||
|
# Backend fat Dockerfile - Java Spring Boot with all dependencies and build stage
|
||||||
# Build the application
|
# Build the application
|
||||||
FROM gradle:8.14-jdk21 AS build
|
FROM gradle:8.14-jdk21 AS build
|
||||||
|
|
||||||
@ -52,7 +53,6 @@ ENV DISABLE_ADDITIONAL_FEATURES=true \
|
|||||||
TEMP=/tmp/stirling-pdf \
|
TEMP=/tmp/stirling-pdf \
|
||||||
TMP=/tmp/stirling-pdf
|
TMP=/tmp/stirling-pdf
|
||||||
|
|
||||||
|
|
||||||
# JDK for app
|
# JDK for app
|
||||||
RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
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 "@community https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
||||||
@ -108,4 +108,4 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
EXPOSE 8080/tcp
|
EXPOSE 8080/tcp
|
||||||
# Set user and run command
|
# Set user and run command
|
||||||
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
||||||
CMD ["sh", "-c", "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"]
|
CMD ["sh", "-c", "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"]
|
@ -1,4 +1,4 @@
|
|||||||
# use alpine
|
# Backend ultra-lite Dockerfile - Java Spring Boot with minimal dependencies
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
@ -52,4 +52,4 @@ EXPOSE 8080/tcp
|
|||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
ENTRYPOINT ["tini", "--", "/scripts/init-without-ocr.sh"]
|
ENTRYPOINT ["tini", "--", "/scripts/init-without-ocr.sh"]
|
||||||
CMD ["java", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=/tmp/stirling-pdf", "-jar", "/app.jar"]
|
CMD ["java", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=/tmp/stirling-pdf", "-jar", "/app.jar"]
|
66
docker/compose/docker-compose.fat.yml
Normal file
66
docker/compose/docker-compose.fat.yml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile.fat
|
||||||
|
container_name: stirling-pdf-backend-fat
|
||||||
|
restart: on-failure:5
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 6G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # TODO: Remove in production - for debugging only
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
volumes:
|
||||||
|
- ../../stirling/latest/data:/usr/share/tessdata:rw
|
||||||
|
- ../../stirling/latest/config:/configs:rw
|
||||||
|
- ../../stirling/latest/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
FAT_DOCKER: "true"
|
||||||
|
INSTALL_BOOK_AND_ADVANCED_HTML_OPS: "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: Full-featured Stirling-PDF with all capabilities
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Fat
|
||||||
|
SYSTEM_MAXFILESIZE: "200"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
|
SHOW_SURVEY: "true"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../../frontend
|
||||||
|
dockerfile: ../docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend-fat
|
||||||
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
stirling-data:
|
||||||
|
stirling-config:
|
||||||
|
stirling-logs:
|
42
docker/compose/docker-compose.monolith.yml
Normal file
42
docker/compose/docker-compose.monolith.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
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:
|
56
docker/compose/docker-compose.ultra-lite.yml
Normal file
56
docker/compose/docker-compose.ultra-lite.yml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile.ultra-lite
|
||||||
|
container_name: stirling-pdf-backend-ultra-lite
|
||||||
|
restart: on-failure:5
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 2G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # TODO: Remove in production - for debugging only
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
volumes:
|
||||||
|
- ../../stirling/latest/config:/configs:rw
|
||||||
|
- ../../stirling/latest/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
ENDPOINTS_GROUPS_TO_REMOVE: "CLI"
|
||||||
|
LANGS: "en_GB,en_US"
|
||||||
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
|
UI_APPNAME: Stirling-PDF
|
||||||
|
UI_HOMEDESCRIPTION: Ultra-lite version of Stirling-PDF
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Ultra-lite
|
||||||
|
SYSTEM_MAXFILESIZE: "50"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../../frontend
|
||||||
|
dockerfile: ../docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend-ultra-lite
|
||||||
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
64
docker/compose/docker-compose.yml
Normal file
64
docker/compose/docker-compose.yml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile
|
||||||
|
container_name: stirling-pdf-backend
|
||||||
|
restart: on-failure:5
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # TODO: Remove in production - for debugging only
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
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: Demo site for Stirling-PDF Latest
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
||||||
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
|
SHOW_SURVEY: "true"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../../frontend
|
||||||
|
dockerfile: ../docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend
|
||||||
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
stirling-data:
|
||||||
|
stirling-config:
|
||||||
|
stirling-logs:
|
38
docker/frontend/Dockerfile
Normal file
38
docker/frontend/Dockerfile
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Frontend Dockerfile - React/Vite application
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# Copy built files from build stage
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Copy nginx configuration and entrypoint
|
||||||
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
# Make entrypoint executable
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
# Expose port 80 (standard HTTP port)
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Environment variables for flexibility
|
||||||
|
ENV BACKEND_URL=http://backend:8080
|
||||||
|
|
||||||
|
# Use custom entrypoint
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
10
docker/frontend/entrypoint.sh
Normal file
10
docker/frontend/entrypoint.sh
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Set default backend URL if not provided
|
||||||
|
BACKEND_URL=${BACKEND_URL:-"http://backend:8080"}
|
||||||
|
|
||||||
|
# Replace the placeholder in nginx.conf with the actual backend URL
|
||||||
|
sed -i "s|\${BACKEND_URL}|${BACKEND_URL}|g" /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
# Start nginx
|
||||||
|
exec nginx -g "daemon off;"
|
49
docker/frontend/nginx.conf
Normal file
49
docker/frontend/nginx.conf
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass ${BACKEND_URL}/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;
|
||||||
|
}
|
||||||
|
}
|
128
docker/monolith/Dockerfile
Normal file
128
docker/monolith/Dockerfile
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
# Monolith Dockerfile - Frontend + Backend in same container
|
||||||
|
# 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 stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||||
|
COPY stirling-pdf/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 \
|
||||||
|
qpdf \
|
||||||
|
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)
|
||||||
|
tesseract-ocr-data-eng \
|
||||||
|
tesseract-ocr-data-chi_sim \
|
||||||
|
tesseract-ocr-data-deu \
|
||||||
|
tesseract-ocr-data-fra \
|
||||||
|
tesseract-ocr-data-por \
|
||||||
|
# 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"]
|
49
docker/monolith/nginx-monolith.conf
Normal file
49
docker/monolith/nginx-monolith.conf
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
20
docker/monolith/start-monolith.sh
Normal file
20
docker/monolith/start-monolith.sh
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/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;"
|
Loading…
x
Reference in New Issue
Block a user