diff --git a/.docker/frankenphp/conf.d/app.ini b/.docker/frankenphp/conf.d/app.ini index 08c71700..10a062f2 100644 --- a/.docker/frankenphp/conf.d/app.ini +++ b/.docker/frankenphp/conf.d/app.ini @@ -12,7 +12,7 @@ opcache.max_accelerated_files = 20000 opcache.memory_consumption = 256 opcache.enable_file_override = 1 -memory_limit = 512M +memory_limit = 256M upload_max_filesize=256M -post_max_size=300M +post_max_size=300M \ No newline at end of file diff --git a/.docker/frankenphp/worker.Caddyfile b/.docker/frankenphp/worker.Caddyfile index eaea1892..d384ae4c 100644 --- a/.docker/frankenphp/worker.Caddyfile +++ b/.docker/frankenphp/worker.Caddyfile @@ -1,3 +1,4 @@ worker { file ./public/index.php + env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime } diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 2e0d533c..ce3243ca 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -15,20 +15,8 @@ on: - 'v*.*.*-**' jobs: - build: - strategy: - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - platform-slug: amd64 - - platform: linux/arm64 - runner: ubuntu-24.04-arm - platform-slug: arm64 - - platform: linux/arm/v7 - runner: ubuntu-24.04-arm - platform-slug: armv7 - runs-on: ${{ matrix.runner }} + docker: + runs-on: ubuntu-latest steps: - name: Checkout @@ -44,12 +32,13 @@ jobs: # Mark the image build from master as latest (as we dont have really releases yet) tags: | type=edge,branch=master - type=ref,event=branch - type=ref,event=tag + type=ref,event=branch, + type=ref,event=tag, type=schedule type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} + type=ref,event=branch type=ref,event=pr labels: | org.opencontainers.image.source=${{ github.event.repository.clone_url }} @@ -60,10 +49,12 @@ jobs: org.opencontainers.image.source=https://github.com/Part-DB/Part-DB-symfony org.opencontainers.image.authors=Jan Böhmer org.opencontainers.licenses=AGPL-3.0-or-later - # Disable automatic 'latest' tag in build jobs - it will be created in merge job - flavor: | - latest=false + - + name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: 'arm64,arm' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -76,85 +67,13 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push by digest - id: build + name: Build and push uses: docker/build-push-action@v6 with: context: . - platforms: ${{ matrix.platform }} + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} - outputs: type=image,name=jbtronics/part-db1,push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }} - cache-from: type=gha,scope=build-${{ matrix.platform }} - cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }} - - - - name: Export digest - if: github.event_name != 'pull_request' - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - - name: Upload digest - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: digests-${{ matrix.platform-slug }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - build - if: github.event_name != 'pull_request' - steps: - - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: /tmp/digests - pattern: digests-* - merge-multiple: true - - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - - name: Docker meta - id: docker_meta - uses: docker/metadata-action@v5 - with: - images: | - jbtronics/part-db1 - tags: | - type=edge,branch=master - type=ref,event=branch - type=ref,event=tag - type=schedule - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=ref,event=pr - - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf 'jbtronics/part-db1@sha256:%s ' *) - - - - name: Inspect image - run: | - docker buildx imagetools inspect jbtronics/part-db1:${{ steps.docker_meta.outputs.version }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker_frankenphp.yml b/.github/workflows/docker_frankenphp.yml index 10e62dfc..1180f0c5 100644 --- a/.github/workflows/docker_frankenphp.yml +++ b/.github/workflows/docker_frankenphp.yml @@ -15,20 +15,8 @@ on: - 'v*.*.*-**' jobs: - build: - strategy: - matrix: - include: - - platform: linux/amd64 - runner: ubuntu-latest - platform-slug: amd64 - - platform: linux/arm64 - runner: ubuntu-24.04-arm - platform-slug: arm64 - - platform: linux/arm/v7 - runner: ubuntu-24.04-arm - platform-slug: armv7 - runs-on: ${{ matrix.runner }} + docker: + runs-on: ubuntu-latest steps: - name: Checkout @@ -44,12 +32,13 @@ jobs: # Mark the image build from master as latest (as we dont have really releases yet) tags: | type=edge,branch=master - type=ref,event=branch - type=ref,event=tag + type=ref,event=branch, + type=ref,event=tag, type=schedule type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} + type=ref,event=branch type=ref,event=pr labels: | org.opencontainers.image.source=${{ github.event.repository.clone_url }} @@ -60,10 +49,12 @@ jobs: org.opencontainers.image.source=https://github.com/Part-DB/Part-DB-server org.opencontainers.image.authors=Jan Böhmer org.opencontainers.licenses=AGPL-3.0-or-later - # Disable automatic 'latest' tag in build jobs - it will be created in merge job - flavor: | - latest=false + - + name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: 'arm64,arm' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -76,86 +67,14 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push by digest - id: build + name: Build and push uses: docker/build-push-action@v6 with: context: . file: Dockerfile-frankenphp - platforms: ${{ matrix.platform }} + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} - outputs: type=image,name=partdborg/part-db,push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }} - cache-from: type=gha,scope=build-${{ matrix.platform }} - cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }} - - - - name: Export digest - if: github.event_name != 'pull_request' - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - - name: Upload digest - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: digests-${{ matrix.platform-slug }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - build - if: github.event_name != 'pull_request' - steps: - - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: /tmp/digests - pattern: digests-* - merge-multiple: true - - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - - name: Docker meta - id: docker_meta - uses: docker/metadata-action@v5 - with: - images: | - partdborg/part-db - tags: | - type=edge,branch=master - type=ref,event=branch - type=ref,event=tag - type=schedule - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=ref,event=pr - - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf 'partdborg/part-db@sha256:%s ' *) - - - - name: Inspect image - run: | - docker buildx imagetools inspect partdborg/part-db:${{ steps.docker_meta.outputs.version }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index e848acc1..8ebd320c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,75 +1,15 @@ -# syntax=docker/dockerfile:1 ARG BASE_IMAGE=debian:bookworm-slim ARG PHP_VERSION=8.4 -ARG NODE_VERSION=22 -# Node.js build stage for building frontend assets -# Use native platform for build stage as it's platform-independent -FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-bookworm-slim AS node-builder -ARG TARGETARCH -WORKDIR /app -# Install composer and minimal PHP for running Symfony commands -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer - -# Use BuildKit cache mounts for apt in builder stage -RUN --mount=type=cache,id=apt-cache-node-$TARGETARCH,target=/var/cache/apt \ - --mount=type=cache,id=apt-lists-node-$TARGETARCH,target=/var/lib/apt/lists \ - apt-get update && apt-get install -y --no-install-recommends \ - php-cli \ - php-xml \ - php-mbstring \ - unzip \ - git \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -# Copy composer files and install dependencies (needed for Symfony UX assets) -COPY composer.json composer.lock symfony.lock ./ - -# Use BuildKit cache for Composer downloads -RUN --mount=type=cache,id=composer-cache,target=/root/.cache/composer \ - composer install --no-scripts --no-autoloader --no-dev --prefer-dist --ignore-platform-reqs - -# Copy all application files needed for cache warmup and webpack build -COPY .env* ./ -COPY bin ./bin -COPY config ./config -COPY src ./src -COPY translations ./translations -COPY public ./public -COPY assets ./assets -COPY webpack.config.js ./ - -# Generate autoloader -RUN composer dump-autoload - -# Create required directories for cache warmup -RUN mkdir -p var/cache var/log uploads public/media - -# Dump translations, which we need for cache warmup -RUN php bin/console cache:warmup -n --env=prod 2>&1 - -# Copy package files and install node dependencies -COPY package.json yarn.lock ./ -# Use BuildKit cache for yarn/npm -RUN --mount=type=cache,id=yarn-cache,target=/root/.cache/yarn \ - --mount=type=cache,id=npm-cache,target=/root/.npm \ - yarn install --network-timeout 600000 - -# Build the assets -RUN yarn build - -# Clean up -RUN yarn cache clean && rm -rf node_modules/ - -# Base stage for PHP FROM ${BASE_IMAGE} AS base ARG PHP_VERSION -ARG TARGETARCH -# Use BuildKit cache mounts for apt in base stage -RUN --mount=type=cache,id=apt-cache-$TARGETARCH,target=/var/cache/apt \ - --mount=type=cache,id=apt-lists-$TARGETARCH,target=/var/lib/apt/lists \ - apt-get update && apt-get -y install \ +# Install needed dependencies for PHP build +#RUN apt-get update && apt-get install -y pkg-config curl libcurl4-openssl-dev libicu-dev \ +# libpng-dev libjpeg-dev libfreetype6-dev gnupg zip libzip-dev libjpeg62-turbo-dev libonig-dev libxslt-dev libwebp-dev vim \ +# && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/* + +RUN apt-get update && apt-get -y install \ apt-transport-https \ lsb-release \ ca-certificates \ @@ -99,10 +39,19 @@ RUN --mount=type=cache,id=apt-cache-$TARGETARCH,target=/var/cache/apt \ gpg \ sudo \ && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/* \ +# Create workdir and set permissions if directory does not exists && mkdir -p /var/www/html \ && chown -R www-data:www-data /var/www/html \ +# delete the "index.html" that installing Apache drops in here && rm -rvf /var/www/html/* +# Install node and yarn +RUN curl -sL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get update && apt-get install -y \ + nodejs \ + && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/* && \ + npm install -g yarn + # Install composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer @@ -116,12 +65,14 @@ ENV APACHE_ENVVARS=$APACHE_CONFDIR/envvars # : ${APACHE_RUN_USER:=www-data} # export APACHE_RUN_USER # so that they can be overridden at runtime ("-e APACHE_RUN_USER=...") -RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS" && \ - set -eux; . "$APACHE_ENVVARS" && \ - ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log" && \ - ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log" && \ - ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log" && \ - chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR" +RUN sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \ + set -eux; . "$APACHE_ENVVARS"; \ + \ + # logs should go to stdout / stderr + ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \ + ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \ + ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \ + chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"; # --- @@ -190,6 +141,7 @@ COPY --chown=www-data:www-data . . # Setup apache2 RUN a2dissite 000-default.conf && \ a2ensite symfony.conf && \ +# Enable php-fpm a2enmod proxy_fcgi setenvif && \ a2enconf php${PHP_VERSION}-fpm && \ a2enconf docker-php && \ @@ -197,13 +149,12 @@ RUN a2dissite 000-default.conf && \ # Install composer and yarn dependencies for Part-DB USER www-data -# Use BuildKit cache for Composer when running as www-data by setting COMPOSER_CACHE_DIR -RUN --mount=type=cache,id=composer-cache,target=/tmp/.composer-cache \ - COMPOSER_CACHE_DIR=/tmp/.composer-cache composer install -a --no-dev && \ +RUN composer install -a --no-dev && \ composer clear-cache - -# Copy built frontend assets from node-builder stage -COPY --from=node-builder --chown=www-data:www-data /app/public/build ./public/build +RUN yarn install --network-timeout 600000 && \ + yarn build && \ + yarn cache clean && \ + rm -rf node_modules/ # Use docker env to output logs to stdout ENV APP_ENV=docker @@ -215,12 +166,10 @@ USER root RUN sed -i "s/PHP_VERSION/${PHP_VERSION}/g" ./.docker/partdb-entrypoint.sh # Copy entrypoint and apache2-foreground to /usr/local/bin and make it executable -# Convert CRLF -> LF and install entrypoint scripts with executable mode -RUN sed -i 's/\r$//' ./.docker/partdb-entrypoint.sh ./.docker/apache2-foreground && \ - install -m 0755 ./.docker/partdb-entrypoint.sh /usr/local/bin/ && \ - install -m 0755 ./.docker/apache2-foreground /usr/local/bin/ +RUN install ./.docker/partdb-entrypoint.sh /usr/local/bin && \ + install ./.docker/apache2-foreground /usr/local/bin ENTRYPOINT ["partdb-entrypoint.sh"] -CMD ["/usr/local/bin/apache2-foreground"] +CMD ["apache2-foreground"] # https://httpd.apache.org/docs/2.4/stopping.html#gracefulstop STOPSIGNAL SIGWINCH diff --git a/Dockerfile-frankenphp b/Dockerfile-frankenphp index 4bf9eeeb..69b9bacd 100644 --- a/Dockerfile-frankenphp +++ b/Dockerfile-frankenphp @@ -1,72 +1,6 @@ -ARG NODE_VERSION=22 - -# Node.js build stage for building frontend assets -# Use native platform for build stage as it's platform-independent -FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-bookworm-slim AS node-builder -ARG TARGETARCH -WORKDIR /app - -# Install composer and minimal PHP for running Symfony commands -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer - -# Use BuildKit cache mounts for apt in builder stage -RUN --mount=type=cache,id=apt-cache-node-$TARGETARCH,target=/var/cache/apt \ - --mount=type=cache,id=apt-lists-node-$TARGETARCH,target=/var/lib/apt/lists \ - apt-get update && apt-get install -y --no-install-recommends \ - php-cli \ - php-xml \ - php-mbstring \ - unzip \ - git \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -# Copy composer files and install dependencies (needed for Symfony UX assets) -COPY composer.json composer.lock symfony.lock ./ - -# Use BuildKit cache for Composer downloads -RUN --mount=type=cache,id=composer-cache,target=/root/.cache/composer \ - composer install --no-scripts --no-autoloader --no-dev --prefer-dist --ignore-platform-reqs - -# Copy all application files needed for cache warmup and webpack build -COPY .env* ./ -COPY bin ./bin -COPY config ./config -COPY src ./src -COPY translations ./translations -COPY public ./public -COPY assets ./assets -COPY webpack.config.js ./ - -# Generate autoloader -RUN composer dump-autoload - -# Create required directories for cache warmup -RUN mkdir -p var/cache var/log uploads public/media - -# Dump translations, which we need for cache warmup -RUN php bin/console cache:warmup -n --env=prod 2>&1 - -# Copy package files and install node dependencies -COPY package.json yarn.lock ./ - -# Use BuildKit cache for yarn/npm -RUN --mount=type=cache,id=yarn-cache,target=/root/.cache/yarn \ - --mount=type=cache,id=npm-cache,target=/root/.npm \ - yarn install --network-timeout 600000 - - -# Build the assets -RUN yarn build - -# Clean up -RUN yarn cache clean && rm -rf node_modules/ - -# FrankenPHP base stage FROM dunglas/frankenphp:1-php8.4 AS frankenphp_upstream -ARG TARGETARCH -RUN --mount=type=cache,id=apt-cache-$TARGETARCH,target=/var/cache/apt \ - --mount=type=cache,id=apt-lists-$TARGETARCH,target=/var/lib/apt/lists \ - apt-get update && apt-get -y install \ + +RUN apt-get update && apt-get -y install \ curl \ ca-certificates \ mariadb-client \ @@ -79,6 +13,24 @@ RUN --mount=type=cache,id=apt-cache-$TARGETARCH,target=/var/cache/apt \ zip \ && apt-get -y autoremove && apt-get clean autoclean && rm -rf /var/lib/apt/lists/*; +RUN set -eux; \ + # Run NodeSource setup script + curl -sL https://deb.nodesource.com/setup_22.x | bash -; \ + \ + # Install Node.js + apt-get update; \ + apt-get install -y --no-install-recommends \ + nodejs; \ + \ + # Cleanup + apt-get -y autoremove; \ + apt-get clean autoclean; \ + rm -rf /var/lib/apt/lists/*; \ + \ + # Install Yarn via npm + npm install -g yarn + + # Install PHP RUN set -eux; \ install-php-extensions \ @@ -124,11 +76,14 @@ COPY --link . ./ RUN set -eux; \ mkdir -p var/cache var/log; \ composer dump-autoload --classmap-authoritative --no-dev; \ + composer dump-env prod; \ composer run-script --no-dev post-install-cmd; \ chmod +x bin/console; sync; -# Copy built frontend assets from node-builder stage -COPY --from=node-builder /app/public/build ./public/build +RUN yarn install --network-timeout 600000 && \ + yarn build && \ + yarn cache clean && \ + rm -rf node_modules/ # Use docker env to output logs to stdout ENV APP_ENV=docker @@ -147,8 +102,8 @@ VOLUME ["/var/www/html/uploads", "/var/www/html/public/media"] HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1 # See https://caddyserver.com/docs/conventions#file-locations for details -ENV XDG_CONFIG_HOME=/config -ENV XDG_DATA_HOME=/data +ENV XDG_CONFIG_HOME /config +ENV XDG_DATA_HOME /data EXPOSE 80 EXPOSE 443 diff --git a/VERSION b/VERSION index 24ba9a38..e70b4523 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.7.0 +2.6.0