Public Access
1
0

fix: improve image build

This commit is contained in:
2025-08-27 21:13:46 -04:00
parent 650694665d
commit 4e0abc72e5
4 changed files with 69 additions and 95 deletions

View File

@@ -5,6 +5,10 @@
ARG TARGETPLATFORM
ARG BUILDPLATFORM
# Arguments for user and group IDs. Default to a common non-root user ID.
ARG UID=1000
ARG GID=1000
# STAGE 1: Dependencies
# This stage installs all dependencies (dev and prod) from package-lock.json
# It's used as a base for both development and builder stages to leverage caching.
@@ -38,21 +42,20 @@ RUN npm prune --production
FROM node:18-alpine AS production
WORKDIR /app
# Create a non-root user for better security
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# The node:18-alpine image comes with a non-root 'node' user (UID/GID 1000)
# which we will use. We only need su-exec to drop privileges in the entrypoint.
# Install su-exec for dropping privileges from root
RUN apk add --no-cache su-exec
# Copy only the necessary artifacts from the builder stage
# Using --chown ensures the non-root user owns the files.
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./package.json
COPY --from=builder --chown=appuser:appgroup /app/src/server.js .
COPY --from=builder --chown=appuser:appgroup /app/_site ./_site
COPY --from=builder --chown=node:node /app/node_modules ./node_modules
COPY --from=builder --chown=node:node /app/package.json ./package.json
COPY --from=builder --chown=node:node /app/src/server.js .
COPY --from=builder --chown=node:node /app/_site ./_site
# The _data directory is handled by the volume, but we copy it so the volume can be pre-populated on first run.
COPY --from=builder --chown=appuser:appgroup /app/src/_data/ ./_data/
COPY --chown=appuser:appgroup healthcheck.js .
COPY --from=builder --chown=node:node /app/src/_data/ ./_data/
COPY --chown=node:node healthcheck.js .
# Copy and set up the entrypoint script
COPY --chown=root:root entrypoint.sh /usr/local/bin/
@@ -60,7 +63,7 @@ RUN chmod +x /usr/local/bin/entrypoint.sh
# Add a healthcheck to ensure the container is running correctly.
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD ["su-exec", "appuser", "node", "healthcheck.js"]
CMD ["su-exec", "node", "node", "healthcheck.js"]
ENTRYPOINT ["entrypoint.sh"]
CMD ["node", "server.js"]

View File

@@ -1,60 +0,0 @@
# docker-compose.dev.yml for development
# This setup runs two services:
# 1. The Eleventy dev server for live-reloading site changes.
# 2. The Express API server for the view counter.
#
# To start both, run: docker compose -f docker-compose.dev.yml up
#
# Your site will be available at http://localhost:8080.
# API requests are proxied from /api to the API service, so you don't need to access port 3000 directly.
services:
# This service runs the Eleventy development server.
eleventy:
build:
context: .
target: development # Use the 'development' stage from the Dockerfile
# Adding `init: true` ensures that the container's main process receives
# signals correctly (like SIGINT/SIGTERM) when you stop the container.
# This helps the dev server to shut down gracefully.
init: true
container_name: eleventy_dev
ports:
- "9229:9229" # Node.js debugger port
- "8080:8080" # Eleventy dev server port
volumes:
# Mount the project directory for live-reloading.
# The anonymous volume for node_modules prevents the local one from overwriting the container's.
- .:/app
- /app/node_modules
networks:
# Both services need to be on the same network for the Eleventy dev server
# to proxy requests to the API container using its service name ('api').
- dev_network
# This command runs Eleventy's dev server with file watching.
command: npm run debug
# This service runs your Express API server.
api:
build:
context: .
target: development # Use the same 'development' stage
# Adding `init: true` is especially important for debugging. It ensures
# the Node.js process receives shutdown signals, allowing the debugger
# to detach cleanly.
init: true
container_name: api_dev
# The API port does not need to be exposed to the host. The 'eleventy'
# service proxies requests to it over the internal Docker network.
volumes:
- .:/app
- /app/node_modules
networks:
- dev_network
# Use Node's built-in --watch mode instead of nodemon. It can be more
# stable inside Docker and avoids some of nodemon's complexities. The
# --inspect flag has been moved to the eleventy service.
command: node --watch src/server.js
networks:
dev_network:
driver: bridge

View File

@@ -1,29 +1,60 @@
# docker-compose.yml for production
# This setup builds and runs the optimized production image.
# docker-compose.dev.yml for development
# This setup runs two services:
# 1. The Eleventy dev server for live-reloading site changes.
# 2. The Express API server for the view counter.
#
# To update, run: docker compose build
# To start both, run: docker compose -f docker-compose.dev.yml up
#
# Your site will be available at http://localhost:8080.
# API requests are proxied from /api to the API service, so you don't need to access port 3000 directly.
services:
app:
# This service runs the Eleventy development server.
eleventy:
build:
context: .
target: production # Use the 'production' stage from the Dockerfile
platform: linux/arm64
container_name: eleventy_prod
target: development # Use the 'development' stage from the Dockerfile
# Adding `init: true` ensures that the container's main process receives
# signals correctly (like SIGINT/SIGTERM) when you stop the container.
# This helps the dev server to shut down gracefully.
init: true
container_name: eleventy_dev
ports:
- "9229:9229" # Node.js debugger port
- "8080:8080" # Eleventy dev server port
volumes:
# Persist the view count data in a named volume.
- data:/app/_data
restart: unless-stopped
labels:
diun.enable: true
homepage.group: Tools
homepage.name: 11ty Website
homepage.icon: https://jesus.twk95.com/android-chrome-192x192.png
homepage.href: ${APP_URL}
# Mount the project directory for live-reloading.
# The anonymous volume for node_modules prevents the local one from overwriting the container's.
- .:/app
- /app/node_modules
networks:
- proxy
volumes:
data: null
# Both services need to be on the same network for the Eleventy dev server
# to proxy requests to the API container using its service name ('api').
- dev_network
# This command runs Eleventy's dev server with file watching.
command: npm run debug
# This service runs your Express API server.
api:
build:
context: .
target: development # Use the same 'development' stage
# Adding `init: true` is especially important for debugging. It ensures
# the Node.js process receives shutdown signals, allowing the debugger
# to detach cleanly.
init: true
container_name: api_dev
# The API port does not need to be exposed to the host. The 'eleventy'
# service proxies requests to it over the internal Docker network.
volumes:
- .:/app
- /app/node_modules
networks:
- dev_network
# Use Node's built-in --watch mode instead of nodemon. It can be more
# stable inside Docker and avoids some of nodemon's complexities. The
# --inspect flag has been moved to the eleventy service.
command: node --watch src/server.js
networks:
proxy:
external: true
dev_network:
driver: bridge

View File

@@ -1,10 +1,10 @@
#!/bin/sh
# This script is used as the container's entrypoint.
# It ensures that the /app/_data directory (mounted as a volume)
# is owned by the non-root 'appuser', so the application can write to it.
# is owned by the non-root 'node' user, so the application can write to it.
set -e
# Fix ownership of the data volume and execute the main command
chown -R appuser:appgroup /app/_data
exec su-exec appuser "$@"
# Fix ownership of the data volume and execute the main command as the 'node' user
chown -R node:node /app/_data
exec su-exec node "$@"