refactor(docker): build and ship a single API + UI image
Collapse the separate backend (Node) and frontend (nginx) images into one image where the Express backend serves the built React app in addition to the API and game content, so deployment is a single container and one origin. - Add a root Dockerfile with frontend-builder + backend-builder stages producing one runtime image; remove backend/ and frontend/ Dockerfiles, the nginx config, and the frontend entrypoint - Serve the frontend dist and SPA fallback from Express (config.serveFrontend / FRONTEND_DIST_PATH), before auth/maintenance so the shell always loads and before the API 404 so client routes resolve to index.html - Port the SPA-oriented CSP from nginx into Helmet, gated on serveFrontend; keep the strict API-only policy otherwise - Reduce both compose files to a single flashpoint-web service on WEB_PORT -> 3100; drop API_PORT, BACKEND_HOST, BACKEND_PORT - Build one image in the release workflow instead of a two-service matrix - Update .env.example, README, workflow README, and env var docs Also add .gitattributes (*.sh eol=lf) and normalize the entrypoint line endings — without it, Windows checkouts bake CRLF into the image and the shebang fails with "no such file or directory".
This commit is contained in:
+21
-42
@@ -6,18 +6,17 @@ This directory contains automated workflows for the Flashpoint Web project.
|
||||
|
||||
### 1. Docker Build and Push (`docker-build-push.yml`)
|
||||
|
||||
Builds and pushes Docker images for all three services to container registries.
|
||||
Builds and pushes the single Docker image to the container registry.
|
||||
|
||||
#### Triggers
|
||||
|
||||
- **Version tags** (`v*.*.*`): Builds and pushes images with version tags and `latest` tag
|
||||
- **Version tags** (`v*.*.*`): Builds and pushes the image with version tags and `latest` tag
|
||||
- **Manual dispatch**: Can be triggered manually from GitHub Actions tab
|
||||
|
||||
#### Services Built
|
||||
#### Image Built
|
||||
|
||||
- `flashpoint-backend` - REST API server
|
||||
- `flashpoint-frontend` - React web UI (Nginx)
|
||||
- `flashpoint-game-service` - Game content proxy and ZIP server
|
||||
- `flashpoint-web` - Single image serving both the REST API (including game
|
||||
content) and the React web UI
|
||||
|
||||
#### Container Registry
|
||||
|
||||
@@ -43,11 +42,9 @@ The workflow pushes images to **Docker Hub**.
|
||||
- `DOCKERHUB_USERNAME`: Your Docker Hub username
|
||||
- `DOCKERHUB_TOKEN`: The access token from step 2
|
||||
|
||||
4. **Images will be pushed to**:
|
||||
4. **Image will be pushed to**:
|
||||
```
|
||||
docker.io/darkraise/flashpoint-backend:latest
|
||||
docker.io/darkraise/flashpoint-frontend:latest
|
||||
docker.io/darkraise/flashpoint-game-service:latest
|
||||
docker.io/darkraise/flashpoint-web:latest
|
||||
```
|
||||
|
||||
#### Image Tags
|
||||
@@ -98,51 +95,34 @@ The workflow uses GitHub Actions cache to speed up builds:
|
||||
|
||||
#### Usage Examples
|
||||
|
||||
##### Pull and Run Images
|
||||
##### Pull and Run the Image
|
||||
|
||||
```bash
|
||||
# Pull latest images
|
||||
docker pull darkraise/flashpoint-backend:latest
|
||||
docker pull darkraise/flashpoint-frontend:latest
|
||||
docker pull darkraise/flashpoint-game-service:latest
|
||||
# Pull the latest image
|
||||
docker pull darkraise/flashpoint-web:latest
|
||||
|
||||
# Or use a specific version
|
||||
docker pull darkraise/flashpoint-backend:1.0.0
|
||||
docker pull darkraise/flashpoint-web:1.0.0
|
||||
```
|
||||
|
||||
##### Use in Docker Compose
|
||||
|
||||
Update your `docker-compose.yml` to use pre-built images:
|
||||
Update your `docker-compose.yml` to use the pre-built image:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
image: darkraise/flashpoint-backend:latest
|
||||
flashpoint-web:
|
||||
image: darkraise/flashpoint-web:latest
|
||||
# Remove build section
|
||||
ports:
|
||||
- "3100:3100"
|
||||
# ... rest of config
|
||||
|
||||
frontend:
|
||||
image: darkraise/flashpoint-frontend:latest
|
||||
ports:
|
||||
- "80:8080"
|
||||
# ... rest of config
|
||||
|
||||
game-service:
|
||||
image: darkraise/flashpoint-game-service:latest
|
||||
ports:
|
||||
- "22500:22500"
|
||||
- "22501:22501"
|
||||
- "80:3100"
|
||||
# ... rest of config
|
||||
```
|
||||
|
||||
Then simply run:
|
||||
```bash
|
||||
docker-compose pull # Pull latest images
|
||||
docker-compose up -d # Start services
|
||||
docker compose pull # Pull the latest image
|
||||
docker compose up -d # Start the service
|
||||
```
|
||||
|
||||
#### Making Images Public
|
||||
@@ -150,7 +130,7 @@ docker-compose up -d # Start services
|
||||
By default, Docker Hub images are private. To make them public:
|
||||
|
||||
1. Go to https://hub.docker.com/repositories
|
||||
2. Click on the repository (e.g., `flashpoint-backend`)
|
||||
2. Click on the repository (e.g., `flashpoint-web`)
|
||||
3. Click "Settings"
|
||||
4. Change visibility to "Public"
|
||||
|
||||
@@ -179,10 +159,9 @@ docker login docker.io
|
||||
#### Performance
|
||||
|
||||
Typical build times (optimized for amd64 only):
|
||||
- First build: 3-5 minutes per service
|
||||
- Subsequent builds (with cache): 1-2 minutes per service
|
||||
- Parallel execution: All 3 services build simultaneously
|
||||
- Total workflow time: ~6-10 minutes (down from 12+ minutes)
|
||||
- First build: 3-5 minutes
|
||||
- Subsequent builds (with cache): 1-2 minutes
|
||||
- Frontend and backend build stages run within a single image build
|
||||
|
||||
**Optimizations applied:**
|
||||
- Single platform (amd64) instead of multi-platform
|
||||
|
||||
@@ -13,16 +13,6 @@ jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
service:
|
||||
- name: backend
|
||||
context: .
|
||||
dockerfile: ./backend/Dockerfile
|
||||
- name: frontend
|
||||
context: .
|
||||
dockerfile: ./frontend/Dockerfile
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -52,7 +42,7 @@ jobs:
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_DOCKERHUB }}/${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-${{ matrix.service.name }}
|
||||
images: ${{ env.REGISTRY_DOCKERHUB }}/${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-web
|
||||
tags: |
|
||||
# Tag with full version (v1.0.0 -> 1.0.0)
|
||||
type=semver,pattern={{version}}
|
||||
@@ -63,16 +53,16 @@ jobs:
|
||||
# Latest tag
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push Docker images
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ${{ matrix.service.context }}
|
||||
file: ${{ matrix.service.dockerfile }}
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha,scope=${{ matrix.service.name }}
|
||||
cache-to: type=gha,scope=${{ matrix.service.name }},mode=max
|
||||
cache-from: type=gha,scope=flashpoint-web
|
||||
cache-to: type=gha,scope=flashpoint-web,mode=max
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
|
||||
@@ -90,17 +80,15 @@ jobs:
|
||||
run: |
|
||||
echo "## Docker Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Images Built:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`flashpoint-backend\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`flashpoint-frontend\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Image Built:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`flashpoint-web\` (API + UI)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Registry:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Docker Hub: \`${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-*\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Docker Hub: \`${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-web\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Pull Commands:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Pull Command:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-backend:latest" >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-frontend:latest" >> $GITHUB_STEP_SUMMARY
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-web:latest" >> $GITHUB_STEP_SUMMARY
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
create-release:
|
||||
@@ -127,13 +115,12 @@ jobs:
|
||||
# Get the previous tag
|
||||
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
||||
|
||||
echo "## Docker Images" >> release_notes.md
|
||||
echo "## Docker Image" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "Pull the images from Docker Hub:" >> release_notes.md
|
||||
echo "Pull the image from Docker Hub:" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "\`\`\`bash" >> release_notes.md
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-backend:${{ steps.version.outputs.version }}" >> release_notes.md
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-frontend:${{ steps.version.outputs.version }}" >> release_notes.md
|
||||
echo "docker pull ${{ secrets.DOCKERHUB_USERNAME }}/flashpoint-web:${{ steps.version.outputs.version }}" >> release_notes.md
|
||||
echo "\`\`\`" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
|
||||
|
||||
Reference in New Issue
Block a user