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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push API image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|
@ -83,6 +83,30 @@ jobs:
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
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
|
- name: Make package public
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
|
|
@ -62,4 +62,9 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
|
||||||
# Start the API server
|
# Start the API server
|
||||||
ENTRYPOINT ["dumb-init", "--"]
|
ENTRYPOINT ["dumb-init", "--"]
|
||||||
CMD ["node", "server/index.js"]
|
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:
|
services:
|
||||||
# Nginx reverse proxy and static file server
|
# Nginx reverse proxy and static file server (client baked into image)
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine
|
image: ghcr.io/dlawler489/etsy-finance-tracker-nginx:main
|
||||||
container_name: etsy-nginx
|
container_name: etsy-nginx
|
||||||
ports:
|
ports:
|
||||||
- "3000:80"
|
- "3000:80"
|
||||||
volumes:
|
|
||||||
- ./nginx.deploy.conf:/etc/nginx/nginx.conf:ro
|
|
||||||
- client_dist:/usr/share/nginx/html:ro
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- etsy-tracker
|
- etsy-tracker
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
@ -31,12 +28,8 @@ services:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- CLIENT_URL=http://nginx
|
- CLIENT_URL=http://nginx
|
||||||
volumes:
|
volumes:
|
||||||
# Mount data directory for persistent storage
|
|
||||||
- etsy_data:/app/data
|
- etsy_data:/app/data
|
||||||
# Optional: Mount uploads directory if needed
|
|
||||||
- etsy_uploads:/app/uploads
|
- etsy_uploads:/app/uploads
|
||||||
# Share client build with nginx
|
|
||||||
- client_dist:/usr/share/nginx/html
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- etsy-network
|
- etsy-network
|
||||||
|
|
@ -46,24 +39,10 @@ services:
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 40s
|
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:
|
volumes:
|
||||||
etsy_uploads:
|
etsy_uploads:
|
||||||
driver: local
|
driver: local
|
||||||
client_dist:
|
|
||||||
driver: local
|
|
||||||
etsy_data:
|
etsy_data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue