diff --git a/Containerfile b/Containerfile index 1370242..dcc0107 100644 --- a/Containerfile +++ b/Containerfile @@ -38,22 +38,12 @@ FROM alpine:latest # Install runtime dependencies for SQLite RUN apk add --no-cache ca-certificates sqlite -# Create non-root user -RUN addgroup -g 1001 -S gocheck && \ - adduser -S -D -H -h /app -s /sbin/nologin -G gocheck -g gocheck -u 1001 gocheck - # Copy the binary from builder stage COPY --from=builder /app/gocheck /app/gocheck # Set working directory WORKDIR /app -# Change ownership to non-root user -RUN chown -R gocheck:gocheck /app - -# Switch to non-root user -USER gocheck - # Expose default port (can be overridden via PORT env var) EXPOSE 8080 diff --git a/README.md b/README.md index 549ee11..b4dee67 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,8 @@ deployment: #### Using Podman (Recommended) +The application is optimized for rootless Podman operation: + ```bash # Build and run with the provided script ./build-container.sh @@ -125,8 +127,21 @@ podman run -d --name gocheck-container -p 8080:8080 -v gocheck-data:/app gocheck PORT=3000 ./build-container.sh # Or manually: podman run -d --name gocheck-container -p 3000:8080 -e PORT=8080 -v gocheck-data:/app gocheck + +# Using Podman Compose (recommended for rootless): +podman-compose -f podman-compose.yml up -d + +# Or with Docker Compose (also works with Podman): +docker-compose up -d ``` +**Rootless Podman Compatibility:** + +- Uses UID/GID 1000 for better user mapping +- Includes security options for rootless operation +- Supports both `podman-compose` and `docker-compose` +- Alternative compose file available: `podman-compose.yml` + #### Using Docker ```bash @@ -142,10 +157,11 @@ docker run -d --name gocheck-container -p 3000:8080 -e PORT=8080 -v gocheck-data #### Container Features -- **Multi-stage build**: Uses Go Alpine for building, distroless for runtime -- **Minimal footprint**: Runtime container is only ~2MB +- **Multi-stage build**: Uses Go Alpine for building, Alpine for runtime +- **Minimal footprint**: Runtime container is optimized for size - **Persistent data**: SQLite database is stored in a named volume -- **Security**: Runs as non-root user in distroless container +- **Security**: Runs as non-root user with UID 1000 +- **Rootless Podman compatible**: Optimized for rootless container operation - **Configurable**: Supports environment variables for customization #### Environment Variables diff --git a/build-and-push.sh b/build-and-push.sh new file mode 100755 index 0000000..5de58fc --- /dev/null +++ b/build-and-push.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +MANIFEST=git.hannover.ccc.de/lubiana/cheekylist +AMD=${MANIFEST}amd64 +ARM=${MANIFEST}arm64 + +podman manifest exists $MANIFEST +if [ $? -eq 0 ]; then + podman manifest rm $MANIFEST +fi +podman manifest create $MANIFEST + +podman build --arch=amd64 -t $AMD . +podman build --arch=arm64 -t $ARM . + +podman manifest add $MANIFEST $AMD $ARM + +podman manifest push $MANIFEST diff --git a/build-container.sh b/build-container.sh deleted file mode 100755 index 973fcb4..0000000 --- a/build-container.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# Build script for GoCheck container -set -e - -IMAGE_NAME="gocheck" -CONTAINER_NAME="gocheck-container" -PORT="${PORT:-8080}" - -echo "��️ Building GoCheck frontend..." - - -echo "🏗️ Building GoCheck container..." - -# Build the container image -podman build -t $IMAGE_NAME -f Containerfile . - -echo "✅ Container built successfully!" - -echo "🚀 Starting GoCheck container on port $PORT..." -podman run -d \ - --rm \ - --name $CONTAINER_NAME \ - -p $PORT:8080 \ - -e PORT=8080 \ - -v gocheck-data:/app \ - $IMAGE_NAME - -echo "✅ GoCheck is running!" -echo "🌐 Access the application at: http://localhost:$PORT" -echo "" -echo "📋 Container management commands:" -echo " View logs: podman logs $CONTAINER_NAME" -echo " Stop: podman stop $CONTAINER_NAME" -echo " Start: podman start $CONTAINER_NAME" -echo " Remove: podman rm $CONTAINER_NAME" -echo " Shell access: podman exec -it $CONTAINER_NAME /bin/sh" -echo "" -echo "🔧 Environment variables:" -echo " PORT: Set to override the default port (default: 8080)" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 072d87f..628485e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,9 @@ services: build: context: . dockerfile: Containerfile + args: + USER_ID: 1000 + GROUP_ID: 1000 container_name: gocheck-container ports: - "${PORT:-8080}:8080" @@ -13,6 +16,9 @@ services: volumes: - gocheck-data:/app restart: unless-stopped + # Rootless Podman compatibility + security_opt: + - no-new-privileges:true healthcheck: test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/" ] interval: 30s diff --git a/frontend/src/components/ChecklistItem.tsx b/frontend/src/components/ChecklistItem.tsx index d17f290..5433e70 100644 --- a/frontend/src/components/ChecklistItem.tsx +++ b/frontend/src/components/ChecklistItem.tsx @@ -124,27 +124,33 @@ export default function ChecklistItem({ } return ( -
Create your first checklist above to get started!
++ Last opened: {checklist.lastOpened ? new Date(checklist.lastOpened).toLocaleString() : 'Never'} +
+No items yet
-Add your first item above to get started!
+No items yet
+Add your first item above to get started!
- Created: {new Date(checklist.createdAt).toLocaleDateString()} -
-Create your first checklist above to get started!
-