Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 92 additions & 7 deletions .docker/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,92 @@
# syntax=docker/dockerfile:1
#
# Reusable Nextcloud (FPM) runtime image.
#
# One Dockerfile covers both build channels:
#
# * release (default): the official Nextcloud image content, plus the
# LibreCode runtime tooling shared by every environment.
# * daily: the same runtime tooling on top of the current Nextcloud master
# daily tarball, for development environments that must follow the
# Nextcloud public APIs without waiting for an alpha/beta/RC.
#
# Build args (see docs/images.md for the full policy):
#
# NEXTCLOUD_VERSION upstream image tag (e.g. 34-fpm, stable-fpm)
# NEXTCLOUD_SOURCE "release" (default) or "daily"
# NEXTCLOUD_MAJOR optional assertion, e.g. "35" for the daily build
# NEXTCLOUD_DAILY_URL daily tarball URL
# PHP_EXTENSION_INSTALLER_VERSION pinned installer release
# VCS_REF / BUILD_DATE injected by CI for traceability
#
# Nothing LibreSign-specific belongs here. Environments that need extra tools
# must extend this image (FROM ...) or mount their own configuration.

ARG NEXTCLOUD_VERSION=stable-fpm

FROM nextcloud:${NEXTCLOUD_VERSION}

# --- Traceability metadata ----------------------------------------------------
# Filled in by CI; local builds keep the "unknown" defaults.
ARG VCS_REF=unknown
ARG BUILD_DATE=unknown
ARG NEXTCLOUD_MAJOR=

LABEL org.opencontainers.image.title="Nextcloud app runtime" \
org.opencontainers.image.description="Reusable Nextcloud FPM runtime foundation maintained by LibreCode" \
org.opencontainers.image.source="https://github.com/LibreCodeCoop/nextcloud-docker" \
org.opencontainers.image.licenses="AGPL-3.0-only" \
org.opencontainers.image.revision="${VCS_REF}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.version="${NEXTCLOUD_VERSION}" \
org.librecode.nextcloud.base-image="nextcloud:${NEXTCLOUD_VERSION}" \
org.librecode.nextcloud.major="${NEXTCLOUD_MAJOR}"

# --- Optional development overlay --------------------------------------------
# Replaces /usr/src/nextcloud (the seed the official entrypoint copies into
# /var/www/html) with the current Nextcloud master. Verified against the
# published .sha512 before being unpacked.
ARG NEXTCLOUD_SOURCE=release
ARG NEXTCLOUD_DAILY_URL=https://download.nextcloud.com/server/daily/latest-master.tar.bz2

RUN set -eux; \
case "${NEXTCLOUD_SOURCE}" in \
release) \
echo "Using the upstream Nextcloud sources shipped in the base image" \
;; \
daily) \
archive="${NEXTCLOUD_DAILY_URL##*/}"; \
curl -fsSL "${NEXTCLOUD_DAILY_URL}" -o "/tmp/${archive}"; \
curl -fsSL "${NEXTCLOUD_DAILY_URL}.sha512" -o "/tmp/${archive}.sha512"; \
cd /tmp; \
expected_sha512="$(awk -v name="${archive}" '$2 == name { print $1 }' "${archive}.sha512")"; \
test -n "${expected_sha512}"; \
echo "${expected_sha512} ${archive}" | sha512sum -c -; \
rm -rf /usr/src/nextcloud; \
tar -xjf "${archive}" -C /usr/src/; \
nextcloud_major="$(php -r 'require "/usr/src/nextcloud/version.php"; echo $OC_Version[0];')"; \
if [ -n "${NEXTCLOUD_MAJOR}" ]; then test "${nextcloud_major}" = "${NEXTCLOUD_MAJOR}"; fi; \
rm -f "/tmp/${archive}" "/tmp/${archive}.sha512"; \
rm -rf /usr/src/nextcloud/updater; \
mkdir -p /usr/src/nextcloud/data /usr/src/nextcloud/custom_apps; \
chmod +x /usr/src/nextcloud/occ \
;; \
*) \
echo "unsupported NEXTCLOUD_SOURCE=${NEXTCLOUD_SOURCE}" >&2; exit 1 \
;; \
esac

# --- Shared runtime tooling ---------------------------------------------------
# Kept identical for every channel so stable and development images follow the
# same maintenance and security rules.
#
# The upgrade step matters: the upstream Nextcloud tag is not rebuilt the moment
# a security fix lands in Debian, so building straight from it can ship CVEs
# that are already fixed. Refreshing the packages here keeps the runtime patched
# without waiting for an upstream rebuild. trivy.yaml is what verifies it.
RUN apt-get update \
&& apt-get install -y \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends \
gzip \
locales \
postgresql-client \
Expand All @@ -12,14 +95,16 @@ RUN apt-get update \
&& locale-gen \
&& rm -rf /var/lib/apt/lists/*

ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8

ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
# Pinned so image builds are reproducible and traceable to a released installer.
ARG PHP_EXTENSION_INSTALLER_VERSION=2.12.0
ADD https://github.com/mlocati/docker-php-extension-installer/releases/download/${PHP_EXTENSION_INSTALLER_VERSION}/install-php-extensions /usr/local/bin/
RUN chmod uga+x /usr/local/bin/install-php-extensions && sync \
&& install-php-extensions \
bz2 \
imagick
bz2 \
imagick

COPY config/php.ini /usr/local/etc/php/conf.d/
40 changes: 0 additions & 40 deletions .docker/app/Dockerfile.35

This file was deleted.

8 changes: 8 additions & 0 deletions .docker/web/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
FROM nginx:alpine

# Refresh the Alpine packages at build time.
#
# The upstream tag is not rebuilt the moment a security fix lands in the Alpine
# repository, so an image built straight from it can ship CVEs that are already
# fixed. Upgrading here keeps the runtime patched without waiting for the
# upstream rebuild. The scan policy in trivy.yaml is what verifies this.
RUN apk upgrade --no-cache

COPY nginx.conf /etc/nginx/nginx.conf
COPY nextcloud.conf /etc/nginx/nextcloud.conf
80 changes: 36 additions & 44 deletions .github/actions/build-and-scan/action.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
name: Build and scan runtime images
description: Build both runtime images for amd64 and arm64, then scan each image
name: Build and scan a runtime image
description: >-
Build one runtime image for linux/amd64 and linux/arm64 and scan both
architectures with Trivy. Works for any image defined in this repository,
so every build channel follows the same build, test and security rules.
inputs:
nextcloud_version:
description: Nextcloud version passed to the app image build
label:
description: Short label used for the scan reports (e.g. app, web, app-dev).
required: true
context:
description: Docker build context. The Dockerfile must be <context>/Dockerfile.
required: true
build-args:
description: Newline separated Docker build arguments.
required: false
default: ''
runs:
using: composite
steps:
Expand All @@ -15,61 +25,43 @@ runs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build app image (linux/amd64)
uses: docker/build-push-action@v6
with:
context: .docker/app
platforms: linux/amd64
load: true
build-args: |
NEXTCLOUD_VERSION=${{ inputs.nextcloud_version }}
tags: scan/app:amd64
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build app image (linux/arm64)
uses: docker/build-push-action@v6
with:
context: .docker/app
platforms: linux/arm64
load: true
build-args: |
NEXTCLOUD_VERSION=${{ inputs.nextcloud_version }}
tags: scan/app:arm64
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build web image (linux/amd64)
- name: Build image for linux/amd64
uses: docker/build-push-action@v6
with:
context: .docker/web
context: ${{ inputs.context }}
file: ${{ inputs.context }}/Dockerfile
platforms: linux/amd64
load: true
tags: scan/web:amd64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: ${{ inputs.build-args }}
tags: scan/${{ inputs.label }}:amd64
cache-from: type=gha,scope=${{ inputs.label }}
cache-to: type=gha,mode=max,scope=${{ inputs.label }}

- name: Build web image (linux/arm64)
- name: Build image for linux/arm64
uses: docker/build-push-action@v6
with:
context: .docker/web
context: ${{ inputs.context }}
file: ${{ inputs.context }}/Dockerfile
platforms: linux/arm64
load: true
tags: scan/web:arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: ${{ inputs.build-args }}
tags: scan/${{ inputs.label }}:arm64
cache-from: type=gha,scope=${{ inputs.label }}
cache-to: type=gha,mode=max,scope=${{ inputs.label }}

- name: Install Trivy
uses: aquasecurity/setup-trivy@81e514348e19b6112ce2a7e3ecbafe19c1e1f567 # v0.3.1
with:
version: v0.74.0
# Keep in sync with the version documented in README.md and
# docs/images.md. Trivy releases a new minor roughly monthly and its
# vulnerability DB evolves with it; an outdated scanner is a common
# cause of opaque scan failures.
version: v0.75.0
cache: true

- name: Scan runtime images
- name: Scan image
shell: bash
run: |
bash scripts/scan-images.sh \
'app@linux/amd64=scan/app:amd64' \
'app@linux/arm64=scan/app:arm64' \
'web@linux/amd64=scan/web:amd64' \
'web@linux/arm64=scan/web:arm64'
'${{ inputs.label }}@linux/amd64=scan/${{ inputs.label }}:amd64' \
'${{ inputs.label }}@linux/arm64=scan/${{ inputs.label }}:arm64'
Loading
Loading