Fix nginx serving blank page by baking client into its own image
The runtime cp from etsy-tracker to a shared volume silently failed because the nodejs user lacked write permissions on the root-owned volume. Now a dedicated nginx-frontend Docker stage is built and pushed to GHCR with the React client baked in, eliminating the volume-sharing approach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
89ee6e69fc
commit
1ef51b1e37
3 changed files with 33 additions and 25 deletions
26
.github/workflows/docker-build.yml
vendored
26
.github/workflows/docker-build.yml
vendored
|
|
@ -72,7 +72,7 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build and push Docker image
|
||||
- name: Build and push API image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
|
|
@ -83,6 +83,30 @@ jobs:
|
|||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Extract metadata for Nginx image
|
||||
id: nginx-meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-nginx
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix=sha-
|
||||
|
||||
- name: Build and push Nginx image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
target: nginx-frontend
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.nginx-meta.outputs.tags }}
|
||||
labels: ${{ steps.nginx-meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Make package public
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -63,3 +63,8 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|||
# Start the API server
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
CMD ["node", "server/index.js"]
|
||||
|
||||
# Stage 4: Nginx server with pre-built client
|
||||
FROM nginx:alpine AS nginx-frontend
|
||||
COPY --from=client-build /app/client/dist /usr/share/nginx/html
|
||||
COPY nginx.deploy.conf /etc/nginx/nginx.conf
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
services:
|
||||
# Nginx reverse proxy and static file server
|
||||
# Nginx reverse proxy and static file server (client baked into image)
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
image: ghcr.io/dlawler489/etsy-finance-tracker-nginx:main
|
||||
container_name: etsy-nginx
|
||||
ports:
|
||||
- "3000:80"
|
||||
volumes:
|
||||
- ./nginx.deploy.conf:/etc/nginx/nginx.conf:ro
|
||||
- client_dist:/usr/share/nginx/html:ro
|
||||
depends_on:
|
||||
- etsy-tracker
|
||||
restart: unless-stopped
|
||||
|
|
@ -31,12 +28,8 @@ services:
|
|||
- PORT=8080
|
||||
- CLIENT_URL=http://nginx
|
||||
volumes:
|
||||
# Mount data directory for persistent storage
|
||||
- etsy_data:/app/data
|
||||
# Optional: Mount uploads directory if needed
|
||||
- etsy_uploads:/app/uploads
|
||||
# Share client build with nginx
|
||||
- client_dist:/usr/share/nginx/html
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- etsy-network
|
||||
|
|
@ -46,24 +39,10 @@ services:
|
|||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
# Copy client files to shared volume and start server
|
||||
command: >
|
||||
sh -c "
|
||||
echo 'Starting Etsy Finance Tracker API Server...';
|
||||
if [ ! -f /usr/share/nginx/html/index.html ]; then
|
||||
echo 'Copying client files to shared volume...';
|
||||
cp -r /app/client/dist/* /usr/share/nginx/html/ 2>/dev/null || true;
|
||||
echo 'Client files copied successfully';
|
||||
fi;
|
||||
echo 'Starting Node.js server...';
|
||||
exec node server/dist/index.js
|
||||
"
|
||||
|
||||
volumes:
|
||||
etsy_uploads:
|
||||
driver: local
|
||||
client_dist:
|
||||
driver: local
|
||||
etsy_data:
|
||||
driver: local
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue