Convert JPG/PNG to WebP and AVIF. Minimal, non-root, CI-friendly.
Base image: SUSE BCI Base 16.0-10.3
- Scans your working directory (recursively) for
*.jpg*.jpeg*.png*.gif. - Produces matching
*.webpand*.avifbeside the originals. - Runs as non-root out of the box (default UID/GID
65532:65532). - Bundles mozjpeg/pngquant/oxipng/gifsicle/webpinfo so you can pre/post-process assets in the same container.
- Docker (or a compatible container runtime).
- A directory containing images to convert (mounted at
/work).
Build the image locally (choose your own tag/name):
docker build -t asset-convert:1.0.0-bci-base-16.0-10.3 .Convert everything under the current directory:
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0-10.3Convert only specific files/paths:
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0-10.3 path/to/a.png path/to/b.jpgMap your host UID/GID so outputs are owned by you:
docker run --rm \
-u "$(id -u)":"$(id -g)" \
-v "$PWD:/work" \
asset-convert:1.0.0-bci-base-16.0-10.3- Default command:
convert-webp-avif - No args: scans
/workrecursively for JPG/JPEG/PNG/GIF. - With args: processes only the provided files or directories (relative to
/work). - Timestamp-aware: re-runs conversions whenever the source image is newer than the existing
.webp/.avif, otherwise skips. - Animated GIF sources automatically route through
gif2webpso their frames remain intact in the generated.webp. - Regex-aware
--profileflags let you override WebP/AVIF quality for matching files.
WEBP_QUALITY(default:85) — WebP quality (0–100).AVIF_QUALITY(default:37) — AVIF quality (0–100, higher = better).AVIF_ALPHA_QUALITY(default: matchesAVIF_QUALITY) — AVIF alpha-channel quality (0–100).AVIF_MIN/AVIF_MAX— deprecated quantizer knobs. When present they are translated to an approximateAVIF_QUALITYso existing pipelines keep working, but you should migrate toAVIF_QUALITYdirectly.
Examples:
# Slightly lighter WebP and AVIF
docker run --rm -v "$PWD:/work" \
-e WEBP_QUALITY=80 -e AVIF_QUALITY=40 \
asset-convert:1.0.0-bci-base-16.0-10.3
# Convert only a folder
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0-10.3 public/images/Match files by regex and adjust encoder settings with one or more --profile flags. The first matching profile applies and any omitted qualities fall back to the defaults or environment overrides. avif-alpha and avifAlpha are interchangeable keys for controlling the AVIF alpha-channel quality per profile.
# Higher quality for UI icons, lighter touch for thumbnails
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0-10.3 \
--profile 'regex=^public/icons/.*\\.png$;webp=92;avif=42' \
--profile 'regex=^public/thumbnails/.*;webp=80;avif=38'Run this container once at build/deploy time to generate WebP/AVIF assets. Serve originals and modern formats from your webserver (e.g., NGINX/Caddy rules to prefer .avif/.webp when present).
Typical pipeline steps:
- Check out code.
- Run
asset-converton your asset directory. - Publish the directory (including generated
.webp/.avif) to your CDN/webserver.
- Keep originals in source control; generated files can be cached or stored as build artifacts.
- For photographic assets, try
WEBP_QUALITY=82andAVIF_QUALITY≈40for a balanced trade-off. - For UI/graphics with flat colors, pre-check PNG conversions to avoid visible banding.
- Animated GIFs are preserved when producing WebP (we switch to
gif2webpunder the hood). Keep originals around if you still need GIF outputs or want to re-rungifsiclemanually.
The container now includes a small toolkit so you don't have to build your own extensions:
- mozjpeg (
cjpeg,jpegtran,djpeg) — re-encode/optimize source JPGs before or after WebP/AVIF conversion. - pngquant (lossy) and oxipng (lossless) — shrink PNG sources to reduce the bytes we feed to the encoders.
- gifsicle + gif2webp/img2webp — inspect/optimize GIFs and reliably convert animated GIFs to animated WebP assets.
- webpinfo — inspect WebP metadata (useful in CI).
Example manual optimizations inside the container:
# Re-encode an original JPG in-place using mozjpeg
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0 \
bash -lc 'jpegtran -optimize -progressive -outfile assets/hero.opt.jpg assets/hero.jpg'
# Lossless shrink on PNGs before running asset-convert
docker run --rm -v "$PWD:/work" asset-convert:1.0.0-bci-base-16.0 \
bash -lc 'oxipng -o 4 -strip safe -r public/icons'Need even more tooling (ImageMagick, ffmpeg, fonts, etc.)? Create a thin wrapper image:
FROM docker.io/ggualerz/asset-convert:1.0.0-bci-base-16.0-10.3
RUN zypper --non-interactive ref && \
zypper --non-interactive install --no-recommends ImageMagick && \
zypper clean -aRebuild and push your derivative image; the convert-webp-avif entrypoint stays the same while your extra CLI utilities are layered on top.
Use publish-asset-convert.sh to build and push tags that follow the x.y.z-bci-base-16.0-10.3 pattern.
- Run the script once to generate
release.env, then edit it with your Docker Hub repository, username, optional extra tags (e.g.,latest). The script auto-detectsBCI_VARIANT/BCI_VERSIONfrom theDockerfileFROMline; override them inrelease.envonly if you need a custom value. - Execute
./publish-asset-convert.shand follow the prompts to bump or set the semantic version (the script appends-bci-base-16.0-10.3automatically). - When prompted, paste a Docker Hub access token/password so the script can
docker login,docker build, tag, and push the resulting image.
Additional tags defined in OCI_IMAGE_ADDITIONAL_TAGS (comma-separated) are applied to the same build, which is helpful for maintaining a latest tag alongside versioned releases.
- “No images found”: confirm paths or pass explicit files/dirs.
- Permission issues: add
-u $(id -u):$(id -g)when running. - Slow conversion: start with looser AVIF settings (e.g.,
AVIF_QUALITY=45).
When publishing (e.g., via GitHub Actions to Docker Hub), tag images with the pattern x.x.x-bci-base-16.0-10.3 to reflect both your release and the SUSE base version.