Headless GIMP in Docker for Server-Side Rendering

Running the GNU Image Manipulation Program (GIMP) in a headless Docker container enables scalable, automated image processing pipelines on servers without physical displays. This guide outlines the essential steps to containerize GIMP, configure a virtual framebuffer using Xvfb to satisfy display requirements, write batch processing scripts, and execute automated rendering jobs through Docker commands.

1. Create the Dockerfile

GIMP relies on an X display server even when executing commands in non-interactive batch mode. To run it headlessly, you must install GIMP alongside xvfb (X Virtual Framebuffer) on a lightweight Linux base image such as Debian or Ubuntu.

Create a file named Dockerfile:

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

# Install GIMP, Xvfb, and required dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    gimp \
    xvfb \
    python3 \
    dbus-x11 \
    && rm -rf /var/lib/apt/lists/*

# Set up working directory
WORKDIR /workspace

# Create an entrypoint script
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

2. Configure the Headless Entrypoint Script

The entrypoint script starts an in-memory virtual display, exports the DISPLAY environment variable, runs the GIMP batch command, and cleanly terminates the virtual server when rendering completes.

Create a file named entrypoint.sh:

#!/usr/bin/env bash
set -e

# Start Xvfb in the background on display :99
Xvfb :99 -screen 0 1024x768x24 -nolisten tcp &
XVFB_PID=$!

export DISPLAY=:99

# Execute passed arguments or default batch command
if [ "$#" -gt 0 ]; then
    "$@"
else
    echo "No command provided to GIMP container."
fi

# Terminate Xvfb
kill $XVFB_PID

3. Write a GIMP Batch Script

GIMP accepts automation scripts via Script-Fu (Scheme) or Python-Fu. For simple server-side rendering, Script-Fu allows direct interaction via the command line without extra plugin configurations.

Create a sample Script-Fu file named render.scm:

(define (server-side-render filename output)
  (let* ((image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
         (drawable (car (gimp-image-get-active-layer image))))
    ;; Apply an example filter: invert colors
    (gimp-drawable-invert drawable FALSE)
    ;; Save and clean up
    (gimp-file-save RUN-NONINTERACTIVE image drawable output output)
    (gimp-image-delete image)))

4. Build the Docker Image

Compile the container image using the Docker CLI:

docker build -t headless-gimp .

5. Execute Automated Server-Side Rendering

Run the container using volume mounts to pass input assets to the container and retrieve processed output files.

Use GIMP's command-line flags:

  • -i: Runs GIMP non-interactively without graphical user interface windows.
  • -b: Specifies the batch command to run or loads a custom Script-Fu expression.
  • -b '(gimp-quit 0)': Ensures the GIMP process exits upon completion.

Execute the following command to render an image:

docker run --rm \
  -v $(pwd)/workspace:/workspace \
  headless-gimp \
  gimp -i -b '(server-side-render "input.png" "output.png")' -b '(gimp-quit 0)'

When integrating this into an automated CI/CD or cloud workflow, mount cloud-storage buckets or network volumes into the /workspace directory, allowing GIMP to pull source media and output rendered artifacts programmatically.