diff --git a/Dockerfile.rootless b/Dockerfile.rootless index 53452dba..caeabd47 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,87 +1,93 @@ -# Node dependencies +# Node dependencies stage FROM public.ecr.aws/docker/library/node:18-alpine AS frontend-dependencies WORKDIR /app -# Install bash and pnpm dependencies -RUN apk update && apk add --no-cache bash - -# Install pnpm globally +# Install pnpm globally (caching layer) RUN npm install -g pnpm -COPY frontend/package.json frontend/pnpm-lock.yaml ./ +# Copy package.json and lockfile to leverage caching +COPY frontend/package.json frontend/pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --shamefully-hoist -# Build Nuxt +# Build Nuxt (frontend) stage FROM public.ecr.aws/docker/library/node:18-alpine AS frontend-builder WORKDIR /app -# Install pnpm globally +# Install pnpm globally again (it can reuse the cache if not changed) RUN npm install -g pnpm -# Copy frontend and install node_modules from previous stage -COPY frontend ./ +# Copy over source files and node_modules from dependencies stage +COPY frontend . COPY --from=frontend-dependencies /app/node_modules ./node_modules RUN pnpm build -# Build Go dependencies +# Go dependencies stage FROM public.ecr.aws/docker/library/golang:alpine AS builder-dependencies WORKDIR /go/src/app -COPY ./backend/go.mod ./backend/go.sum ./ -RUN apk update && apk add --no-cache git \ - && go mod download -# Build API +# Copy go.mod and go.sum for better caching +COPY ./backend/go.mod ./backend/go.sum ./ +RUN go mod download + +# Build API stage FROM public.ecr.aws/docker/library/golang:alpine AS builder ARG BUILD_TIME ARG COMMIT ARG VERSION -RUN apk update && apk upgrade && apk add --no-cache git build-base gcc g++ \ - && addgroup -S nonroot && adduser -S nonroot -G nonroot +# Install necessary build tools +RUN apk update && \ + apk upgrade && \ + apk add --no-cache git build-base gcc g++ WORKDIR /go/src/app -COPY ./backend ./ + +# Copy Go modules (from dependencies stage) and source code +COPY --from=builder-dependencies /go/pkg/mod /go/pkg/mod +COPY ./backend . + +# Clear old public files and copy new ones from frontend build RUN rm -rf ./app/api/public COPY --from=frontend-builder /app/.output/public ./app/api/static/public -COPY --from=builder-dependencies /go/pkg/mod /go/pkg/mod -# Use cache for Go build +# Use cache for Go build artifacts RUN --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=0 GOOS=linux go build \ -ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \ - -o /go/bin/api ./app/api/*.go + -o /go/bin/api \ + -v ./app/api/*.go -# Change ownership of files to nonroot -RUN chown -R nonroot:nonroot /go/bin/api /go/src/app - -# Production stage with Alpine +# Production stage FROM public.ecr.aws/docker/library/alpine:latest - ENV HBOX_MODE=production ENV HBOX_STORAGE_DATA=/data/ -ENV HBOX_STORAGE_SQLITE_URL=/data/homebox.db?_fk=1&_time_format=sqlite +ENV HBOX_STORAGE_SQLITE_URL=/data/homebox.db?_pragma=busy_timeout=2000&_pragma=journal_mode=WAL&_fk=1&_time_format=sqlite # Install necessary runtime dependencies -RUN apk --no-cache add ca-certificates wget curl bash +RUN apk --no-cache add ca-certificates wget +RUN addgroup -S nonroot && adduser -S nonroot -G nonroot -# Copy the binary and data directory +# Create application directory and copy over built Go binary +RUN mkdir /app COPY --from=builder /go/bin/api /app -COPY --from=builder /data /data +RUN chmod +x /app/api +# Labels and configuration for the final image LABEL Name=homebox Version=0.0.1 LABEL org.opencontainers.image.source="https://github.com/sysadminsmedia/homebox" + +# Expose necessary ports for Homebox EXPOSE 7745 +WORKDIR /app -# Update HEALTHCHECK to use curl -HEALTHCHECK --interval=30s \ - --timeout=5s \ - --start-period=5s \ - --retries=3 \ - CMD ["/usr/bin/curl", "--silent", "--fail", "http://localhost:7745/api/v1/status"] +# Healthcheck configuration +HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ + CMD [ "wget", "--no-verbose", "--tries=1", "-O", "-", "http://localhost:7745/api/v1/status" ] -VOLUME ["/data"] +# Persist volume +VOLUME [ "/data" ] -# Use nonroot user +# Entrypoint and CMD USER nonroot -ENTRYPOINT ["/app"] -CMD ["/data/config.yml"] +ENTRYPOINT [ "/app/api" ] +CMD [ "/data/config.yml" ]