Files
lmnp-organizer/backend/Dockerfile
T

91 lines
6.8 KiB
Docker

# Build stage
FROM docker.io/library/maven:3.9-eclipse-temurin-25-alpine AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Runtime shared by acceptance and the final image
FROM docker.io/library/eclipse-temurin:25-jre-alpine AS runtime
WORKDIR /app
RUN apk add --no-cache imagemagick imagemagick-heic imagemagick-jpeg imagemagick-webp \
&& magick -version \
&& magick identify -list format | awk '$1 ~ /^JPEG/ && $3 ~ /r/ { jpeg=1 } $1 ~ /^PNG/ && $3 ~ /r/ { png=1 } $1 ~ /^WEBP/ && $3 ~ /rw/ { webp=1 } $1 ~ /^HEIC/ && $3 ~ /r/ { heic=1 } END { exit !(jpeg && png && webp && heic) }' \
&& addgroup -S lmnp \
&& adduser -S -G lmnp lmnp \
&& mkdir -p /data/attachments /tmp/lmnp-condition-photos \
&& chown -R lmnp:lmnp /data/attachments /tmp/lmnp-condition-photos
COPY src/main/resources/imagemagick-policy.xml /etc/ImageMagick-7/policy.xml
# Acceptance stage: fixtures never enter the final image's layer history
FROM runtime AS acceptance
COPY --from=build /app/target/backend-0.0.1-SNAPSHOT.jar app.jar
COPY --from=build /app/target/test-classes/fr/nessar/lmnporganizer/rental/adapter/out/image/ImageMagickPropertyConditionPhotoNormalizerDockerAcceptance.class /tmp/docker-acceptance/fr/nessar/lmnporganizer/rental/adapter/out/image/ImageMagickPropertyConditionPhotoNormalizerDockerAcceptance.class
RUN apk add --no-cache --virtual .fixture-tools exiftool unzip \
&& mv /etc/ImageMagick-7/policy.xml /tmp/imagemagick-policy.xml \
&& mkdir -p /tmp/lmnp-condition-photos/build-check \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/top-left.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/top-right.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/bottom-right.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/bottom-left.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/left-top.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/right-top.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/right-bottom.jpg \
&& magick -size 2400x1200 gradient: /tmp/lmnp-condition-photos/build-check/left-bottom.jpg \
&& exiftool -overwrite_original -Orientation#=1 /tmp/lmnp-condition-photos/build-check/top-left.jpg \
&& exiftool -overwrite_original -Orientation#=2 /tmp/lmnp-condition-photos/build-check/top-right.jpg \
&& exiftool -overwrite_original -Orientation#=3 /tmp/lmnp-condition-photos/build-check/bottom-right.jpg \
&& exiftool -overwrite_original -Orientation#=4 /tmp/lmnp-condition-photos/build-check/bottom-left.jpg \
&& exiftool -overwrite_original -Orientation#=5 /tmp/lmnp-condition-photos/build-check/left-top.jpg \
&& exiftool -overwrite_original -Orientation#=6 /tmp/lmnp-condition-photos/build-check/right-top.jpg \
&& exiftool -overwrite_original -Orientation#=7 /tmp/lmnp-condition-photos/build-check/right-bottom.jpg \
&& exiftool -overwrite_original -Orientation#=8 /tmp/lmnp-condition-photos/build-check/left-bottom.jpg \
&& magick -size 800x600 gradient: /tmp/lmnp-condition-photos/build-check/small.png \
&& magick -size 800x600 gradient: /tmp/lmnp-condition-photos/build-check/sample.webp \
&& magick -size 800x600 gradient: /tmp/lmnp-condition-photos/build-check/sample.heic \
&& magick -size 10x10 xc:red -size 10x10 xc:blue -delay 10 -loop 0 /tmp/lmnp-condition-photos/build-check/animated.webp \
&& magick -size 10x10 xc:red -size 10x10 xc:blue /tmp/lmnp-condition-photos/build-check/multipage.miff \
&& mv /tmp/imagemagick-policy.xml /etc/ImageMagick-7/policy.xml
RUN set -eu; \
for orientation in top-left top-right bottom-right bottom-left; do \
magick "/tmp/lmnp-condition-photos/build-check/$orientation.jpg[0]" -auto-orient -resize '1920x1080>' -strip -orient Undefined -quality 75 -define webp:lossless=false "webp:/tmp/lmnp-condition-photos/build-check/$orientation.webp"; \
actual="$(magick identify -quiet -format '%m|%wx%h|%[orientation]' "/tmp/lmnp-condition-photos/build-check/$orientation.webp")"; \
printf '%s\n' "$orientation=$actual"; \
test "$actual" = 'WEBP|1920x960|Undefined'; \
done; \
for orientation in left-top right-top right-bottom left-bottom; do \
magick "/tmp/lmnp-condition-photos/build-check/$orientation.jpg[0]" -auto-orient -resize '1080x1920>' -strip -orient Undefined -quality 75 -define webp:lossless=false "webp:/tmp/lmnp-condition-photos/build-check/$orientation.webp"; \
actual="$(magick identify -quiet -format '%m|%wx%h|%[orientation]' "/tmp/lmnp-condition-photos/build-check/$orientation.webp")"; \
printf '%s\n' "$orientation=$actual"; \
test "$actual" = 'WEBP|960x1920|Undefined'; \
done; \
for input in small.png sample.webp sample.heic; do \
cp "/tmp/lmnp-condition-photos/build-check/$input" "/tmp/lmnp-condition-photos/build-check/$input.upload"; \
magick identify -quiet "/tmp/lmnp-condition-photos/build-check/$input.upload"; \
done; \
magick '/tmp/lmnp-condition-photos/build-check/small.png[0]' -auto-orient -resize '1920x1080>' -strip -orient Undefined -quality 75 -define webp:lossless=false webp:/tmp/lmnp-condition-photos/build-check/small.webp; \
test "$(magick identify -quiet -format '%m|%wx%h|%[orientation]' /tmp/lmnp-condition-photos/build-check/small.webp)" = 'WEBP|800x600|Undefined'; \
! magick identify -verbose /tmp/lmnp-condition-photos/build-check/small.webp | grep -Eiq 'exif:|xmp:|profile-|comment:'; \
printf invalid > /tmp/lmnp-condition-photos/build-check/invalid.upload; \
! magick identify -quiet /etc/passwd; \
! magick identify -quiet -; \
magick identify -list policy | grep -q '/tmp/lmnp-condition-photos'; \
for limit in 'Memory: 256MiB' 'Map: 512MiB' 'Disk: 1GiB' 'Thread: 2' 'Time: 30 seconds'; do magick identify -list resource | grep -Fq "$limit"; done; \
mkdir /tmp/docker-acceptance/classes; \
unzip -q /app/app.jar -d /tmp/docker-acceptance/classes; \
java -cp '/tmp/docker-acceptance:/tmp/docker-acceptance/classes/BOOT-INF/classes:/tmp/docker-acceptance/classes/BOOT-INF/lib/*' fr.nessar.lmnporganizer.rental.adapter.out.image.ImageMagickPropertyConditionPhotoNormalizerDockerAcceptance; \
rm -rf /tmp/docker-acceptance /tmp/lmnp-condition-photos/build-check; \
apk del .fixture-tools; \
test ! -e /tmp/lmnp-condition-photos/build-check; \
touch /tmp/acceptance-passed
# Final image
FROM runtime
COPY --from=build /app/target/backend-0.0.1-SNAPSHOT.jar app.jar
COPY --from=acceptance /tmp/acceptance-passed /tmp/acceptance-passed
RUN test -f /tmp/acceptance-passed && rm /tmp/acceptance-passed
USER lmnp
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]