Skip to content

Conversation

vmstan
Copy link
Owner

@vmstan vmstan commented May 7, 2024

This PR enhances the production Dockerfile by converting from installing the versions of libvips and ffmpeg that are available in the Debian repos, to using with custom built versions of those applications. This has the following advantages:

  • Image size reduction: the current Dockerfile was optimized in Dockerfile rewrite based on Ruby image with performance optimizations and size reduction, dedicated Streaming image mastodon/mastodon#26850 through a number of methods including separating the Core Image and Streaming image, removing Node from the resulting image. The 4.2 image is approximately 1.5GB in size while the current 4.3 image is just under 1GB. When ffmpeg and libvips are installed from the Debian repo, they include a number of dependencies to support file formats that are not used or explicitly not desired in Mastodon, including the unused X11 server. Additionally, libvips will install ImageMagick as a fallback for some image formats, when the ultimate goal of Add support for libvips in addition to ImageMagick mastodon/mastodon#30090 is to ultimately remove IM from the codebase entirely for all the reasons why Vips is superior. The size of the resulting Docker image built under this PR is 691MB!
  • Controlled version adoption: Vips and ffmpeg version control should be considered as essential as Ruby, Node, Postgres, or any other Mastodon dependency given the importance of media processing. The Debian repos are notoriously slow in adoption of upgrades, for example ffmpeg is currently at 5.1.4 when 7.0.1 is available, and libvips is at 8.14.1 when 8.15.2 is available.
  • Optimized library selection: Compiling these packages from source allows us to use only the libraries that are necessary for Mastodon. For example there is no support included for things like PDF, JXL, JPEG2000, NIfTI, FITS, Matlab, or SVG. Not only is this more size efficient as noted above, it could be considered more secure by lowering the attack surface of the container through removal of unnecessary components but ultimately it is to allow more granular control where there are multiple choices, especially for Vips as further noted below.

Vips compile/library settings

  • Versions can be controlled in a similar method as Ruby/Node through Docker build arguments, to enable easier local testing and customized version deployments. [--build-arg VIPS_VERSION="8.15.2"]
  • Source code is downloaded directly from GitHub and includes a sha256 hash check as part of the process to insure package integrity.
  • Building deprecated components is disabled, building example programs is disabled, building GObject introspection is disabled, building dynamic modules is disabled. (Full list of libvips build options https://github.com/libvips/libvips/blob/master/meson_options.txt)
  • libjpeg-turbo is used for JPEG processing which is 2-6x faster than standard libjpeg. Another option would be to use mozjpeg but this library is not available in Debian and would required another direct compilation.
  • cgif is used for GIF processing, which if not present would require Vips to fallback to ImageMagick.
  • libspng is used for PNG processing, which is similarly more performant than the standard libpng package.
  • libwebp is used for WebP processing.
  • libheif is used for processing HEIC/HEIF images.
  • orc-0.4 is used for some SIMD operations instead of highway due to the Debian repos not containing a version that is suitable for libvips but this could either be compiled directly or evaluated later if Debian packages are updated.
  • libimagequant is used for libvips to write 8-bit PNG and GIF files, with an alternative being quantizr that is not available in Debian repos but could be built directly.
$ vips --vips-config
enable debug: false
enable deprecated: false
enable modules: false
enable cplusplus: true
enable RAD load/save: true
enable Analyze7 load/save: true
enable PPM load/save: true
enable GIF load: true
use fftw for FFTs: false
SIMD support with highway: false
accelerate loops with ORC: true
ICC profile support with lcms: true
zlib: true
text rendering with pangocairo: false
font file support with fontconfig: false
EXIF metadata support with libexif: true
JPEG load/save with libjpeg: true
JXL load/save with libjxl: false (dynamic module: false)
JPEG2000 load/save with OpenJPEG: false
PNG load/save with libspng: true
PNG load/save with libpng: false
selected quantisation package: imagequant
TIFF load/save with libtiff: true
image pyramid save with libarchive: false
HEIC/AVIF load/save with libheif: true (dynamic module: false)
WebP load/save with libwebp: true
PDF load with PDFium: false
PDF load with poppler-glib: false (dynamic module: false)
SVG load with librsvg: false
EXR load with OpenEXR: false
OpenSlide load: false (dynamic module: false)
Matlab load with libmatio: false
NIfTI load/save with niftiio: false
FITS load/save with cfitsio: false
GIF save with cgif: true
selected Magick package: none (dynamic module: false)
Magick API version: none
Magick load: false
Magick save: false

ffmpeg compile/library settings

  • Versions can be controlled in a similar method as Ruby/Node through Docker build arguments, to enable easier local testing and customized version deployments. [--build-arg FFMPEG_VERSION="7.0.1"]
  • Source code is downloaded directly from ffmpeg.org and includes a sha256 hash check as part of the process to insure package integrity.
  • Building documentation and direct network support are disabled. (Full list of compile options available at https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu)
  • libx264 is used for H.264 video encoding
  • libx265 is used for HEVC video encoding (unclear on if this is necessary)
  • libvpx is used for VP8/VP9 video encoding/decoding
  • libopus is used for Opus audio encoding/decoding
  • libdav1d is used for AV1 decoding
  • libmp3lame is used for MP3 audio processing
  • libvorbis is used for Vorbis audio processing

Ultimately I would like to become more restrictive about what formats are compiled as supported in ffmpeg as most are not needed by Mastodon.

$ ffmpeg -version
ffmpeg version 7.0.1 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 12 (Debian 12.2.0-14)
configuration: --prefix=/opt/ffmpeg --enable-rpath --enable-gpl --enable-version3 --enable-nonfree --enable-shared --enable-ffmpeg --enable-ffprobe --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --disable-doc --disable-network --disable-static
libavutil      59.  8.100 / 59.  8.100
libavcodec     61.  3.100 / 61.  3.100
libavformat    61.  1.100 / 61.  1.100
libavdevice    61.  1.100 / 61.  1.100
libavfilter    10.  1.100 / 10.  1.100
libswscale      8.  1.100 /  8.  1.100
libswresample   5.  1.100 /  5.  1.100
libpostproc    58.  1.100 / 58.  1.100 

@vmstan vmstan closed this Jun 7, 2024
@vmstan vmstan deleted the libvips-dockerfile branch July 26, 2024 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant