How to run SavaPage in Docker
Introduction
This is a guide by example on how to deploy SavaPage in a Docker container.
References
- Jérôme Boillot created a
docker-compose.yml
file to deploy SavaPage in a Docker container. See https://hub.docker.com/r/jboillot/savapage - Markus Neuberger created a SavaPage Podman module for NethServer 8. See https://github.com/mrmarkuz/ns8-savapage
Install Docker
#install Docker + Compose sudo apt install docker.io docker-compose-v2 # add yourself to docker group sudo usermod -aG docker $(whoami)
Create Container
mkdir -p ~/Docker-containers/savapage cd ~/Docker-containers/savapage
Copy files below to ~/Docker-containers/savapage
docker-compose.yml
Docker containers are ephemeral by default. Changes made to a container's filesystem won't persist after the container stops.
There are a few different approaches to managing persistent data. The most common is to use a Docker Volume. Volumes are storage units that are mounted into container filesystems. Any data in a volume will remain intact after its linked container stops, letting you connect another container in the future.
- docker-compose.yml
services: savapage: hostname: sp-server image: savapage container_name: savapage environment: TZ: Europe/Amsterdam env_file: docker.env ports: # CUPS - "127.0.0.1:6631:631" - "[::1]:6631:631" # http #- "127.0.0.1:8641:8631" #- "[::1]:8641:8631" # https - "127.0.0.1:8642:8632" - "[::1]:8642:8632" networks: # IP address assigned by Docker ... #- savapage_network # IP address self assigned example savapage_network: ipv4_address: 172.20.0.10 aliases: - sp-server volumes: - savapage_custom:/opt/savapage/server/custom - savapage_data:/opt/savapage/server/data - savapage_ext:/opt/savapage/server/ext - savapage_logs:/opt/savapage/server/logs - savapage_cups:/etc/cups restart: always postgres: hostname: sp-postgres image: postgres container_name: postgres ports: - "5442:5432" networks: # IP address self assigned example savapage_network: ipv4_address: 172.20.0.20 aliases: - savapage-postgres volumes: - savapage_database:/var/lib/postgresql/data restart: always networks: savapage_network: driver: bridge # IP address self assigned example ipam: config: - subnet: 172.20.0.0/16 volumes: savapage_custom: driver: local savapage_data: driver: local savapage_ext: driver: local savapage_database: driver: local savapage_logs: driver: local savapage_cups: driver: local
docker.env
Important | SP_CONTAINER=DOCKER is required for Docker container. |
---|
- docker.env
# Namespace as prefix for SavaPage envvar names (mandatory) SAVAPAGE_NS=SP_ # Required for Docker container ** SP_CONTAINER=DOCKER # Unique SP_SRV_* variables with server.properties key/value # separated by ':' like SP_SRV_n=key:value # For example: SP_SRV_01=visitor.organization:Acme Corporation SP_SRV_02=server.port:8080 SP_SRV_03=server.ssl.port:8443 SP_SRV_11=database.type:PostgreSQL SP_SRV_12=database.driver:org.postgresql.Driver SP_SRV_13=database.url:jdbc:postgresql://savapage-postgres:5432/savapage SP_SRV_14=database.user:sp-user SP_SRV_15=database.password:my-password # Do NOT redirect: disable http by not exposing # port 8631 as 8641 in docker-compose.yml # SP_SRV_20=server.html.redirect.ssl:true
Dockerfile
A Dockerfile describes how to run your service by installing required software and copying in files.
- Dockerfile
FROM debian:bookworm RUN apt update && apt install --no-install-recommends --no-install-suggests -y binutils cpio \ cups cups-bsd debianutils default-jdk-headless gzip imagemagick librsvg2-bin perl poppler-utils \ qpdf supervisor wkhtmltopdf libheif-examples vim-tiny findutils apt-utils iputils-ping \ gnupg curl hplip COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY docker.env /etc/environment RUN useradd -rmd /opt/savapage -s /bin/bash -G lpadmin savapage && chown savapage:savapage /opt/savapage # Create persistent password for admin tasks in CUPS web interface. RUN echo 'savapage:mysecret' | chpasswd ENV SAVAPAGE_VERSION=1.6.0-rc ENV SAVAPAGE_NS=SP_ ENV SP_CONTAINER=DOCKER USER savapage COPY ./savapage-setup-${SAVAPAGE_VERSION}-linux-x64.bin /opt/savapage/savapage-setup.bin RUN ["bash", "/opt/savapage/savapage-setup.bin", "-n"] USER root RUN ["/opt/savapage/server/bin/linux-x64/roottasks", "pam"] EXPOSE 631 8631 8632 CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
supervisord.conf
- supervisord.conf
[supervisord] nodaemon=true [program:cupsd] command=/usr/sbin/cupsd -f autostart=true autorestart=true [program:cupsctl] command=/usr/sbin/cupsctl --remote-any autostart=true autorestart=true [program:savapage-cups-notifier] command=/opt/savapage/providers/cups/linux-x64/roottasks autostart=true autorestart=true user=root [program:savapage] command=/opt/savapage/server/bin/linux-x64/app-server start autostart=true autorestart=true user=savapage
Build Image
Before you start:
- Download the right
${SAVAPAGE_VERSION}
to./savapage-setup-${SAVAPAGE_VERSION}-linux-x64.bin
- Make sure the build date is March 22, 2025 or later.
- Execute in
~/Docker-containers/savapage
- build.sh
#!/bin/bash # Use Dockerfile to construct the image and tag as "savapage". # Execute if any of the Docker files changed. docker build -t savapage . 2>&1 | tee ./build.log
Run Container
- start.sh
#!/bin/bash #-------------------------- # Start SavaPage container #-------------------------- cd ~/Docker-containers/savapage docker compose up -d
- stop.sh
#!/bin/bash #-------------------------- # Stop SavaPage container #-------------------------- cd ~/Docker-containers/savapage docker compose down
- exec-it-savapage.sh
#!/bin/bash #--------------------------------------- # Execute command in SavaPage container #--------------------------------------- docker exec -it savapage bash
- exec-it-postgres.sh
#!/bin/bash #--------------------------------------- # Execute command in Postgres container #--------------------------------------- docker exec -it postgres bash
# Check running containers docker ps # What's in the SavaPage-container? docker exec -it savapage bash # List docker volumes docker volume ls # List processes docker ps -a # List images docker images # List dangling images docker images -f dangling=true # Remove all the dangling images docker system prune
CUPS
Note | Password for CUPS admin savapage is set in Dockerfile |
---|
CUPS Web interface: http://127.0.0.1:6631/printers/
Admin Web App
Remove Container
https://docs.docker.com/reference/cli/docker/image/rm/
# List images docker images # ... and remove savapage docker image rm savapage
https://docs.docker.com/reference/cli/docker/volume/rm/
# List volumes docker volume ls # ... and remove them docker volume rm savapage_savapage_custom docker volume rm savapage_savapage_data docker volume rm savapage_savapage_database docker volume rm savapage_savapage_ext docker volume rm savapage_savapage_logs