Webswing Standalone in Docker
Dockerfile
You can find an example Dockerfile in the standard Webswing distribution with examples. In case you need to create a Docker image with Webswing you can do so by using&extending it. Extract the distribution.zip file and execute:
docker build -t webswing .
docker run -d -p 8080:8080 webswing
This image is not meant for cluster deployment, please refer to Cluster Deployment section (below) if you need docker images for cluster deployment. This is the Dockerfile shipped with the current standard evaluation distribution. It uses UBI 9 and Java 17. Webswing's built-in XHeadless provides display support without a separate Xvfb service:
FROM redhat/ubi9
RUN dnf install -y \
libXext \
libXi \
libXtst \
libXrender \
pango \
gnupg2 \
socat \
java-17-openjdk
RUN dnf update glibc
# Copy all the application files into /opt/webswing
COPY . /opt/webswing/
ENV WEBSWING_HOME=/opt/webswing \
WEBSWING_OPTS="-h 0.0.0.0 -j /opt/webswing/jetty.properties -serveradmin -pfa /opt/webswing/admin/webswing-admin.properties -adminctx /admin -aw admin/webswing-admin-server.war" \
WEBSWING_JAVA_OPTS="-Xmx256M -Djava.net.preferIPv4Stack=true -Dwebswing.admin.url=http://localhost:8080/admin"
# Set the working directory for subsequent commands
WORKDIR /opt/webswing
RUN mkdir -p /opt/webswing/logs/
RUN mkdir -p /etc/service/webswing && \
echo "#!/bin/sh" > /etc/service/webswing/run && \
echo "cd $WEBSWING_HOME" >> /etc/service/webswing/run && \
echo "exec $JAVA_HOME/bin/java \$WEBSWING_JAVA_OPTS -jar $WEBSWING_HOME/server/webswing-jetty-launcher.jar \$WEBSWING_OPTS" >> /etc/service/webswing/run && \
chmod +x /etc/service/webswing/run
# Expose port 8080 so the Webswing server can be accessed externally
EXPOSE 8080
# Optional Xvfb: install Xvfb, xvfb-run and xauth in this image,
# then uncomment the Xvfb launch line below.
RUN echo "#!/bin/sh" > ./start.sh && \
# echo "exec xvfb-run -a /etc/service/webswing/run" >> ./start.sh && \
echo "exec /etc/service/webswing/run" >> ./start.sh && \
chmod +x ./start.sh
CMD ./start.sh
Quick startup
Running locally:
docker run -d --rm -p 8080:8080 webswing
Running on a server:
docker run -d --rm -e WEBSWING_JAVA_OPTS="-Xmx256M -Djava.net.preferIPv4Stack=true -Dwebswing.admin.url=/admin -Dwebswing.server.publicUrl=http://192.168.1.88:8080" -p 8080:8080 webswing
Docker Compose Example:
Create docker-compose.yml file:
services:
webswing:
image: webswing
restart: always
environment:
- WEBSWING_OPTS=-c /opt/webswing/host/webswing.config -h 0.0.0.0 -j /opt/webswing/jetty.properties -serveradmin -pfa /opt/webswing/host/webswing-admin.properties -adminctx /admin -aw admin/webswing-admin-server.war
- WEBSWING_JAVA_OPTS=-Xms1G -Xmx1G -Djava.net.preferIPv4Stack=true -Dwebswing.propertiesFile=/opt/webswing/webswing.properties -Dwebswing.server.publicUrl=http://192.168.1.2 -Dwebswing.admin.url=/admin
volumes:
- ./webswing:/opt/webswing/host
ports:
- "80:8080"
Environment variable WEBSWING_OPTS specifies startup arguments for the server.
You can reference your webswing.config here. Volume syncs container with host, so your config survives the restart of container.
Environment variable WEBSWING_JAVA_OPTS is for specifying all the system properties that needs to be changed. The most important one in docker context is webswing.admin.url that is mapped in webswing.config. This URL link is behind the Manage button in the application selector screen.
Please note that admin console can run in a different container/host/server, or not run if it is not needed.
In the docker-compose example file we expect that the server has IP address 192.168.1.2.
Docker ports are of "host:container" syntax. So with "80:8080" your app will be accessible without specifying port number.
On your host create folder /opt/app and place there application jar and dependencies in /opt/app/lib.
Copy webswing.config from your DEV machine to /opt/app/webswing.config.
To configure your app setup the classpath like following:
"classPathEntries" : [ "/opt/app/lib/*.jar", "/opt/app/MySwingApp.jar" ]
Run
docker-compose up -d
Here’s a polished documentation-style guide for configuring Webswing Cluster using Docker. It walks you through architecture, config files, Docker images, and best practices—all in one place.
Webswing Cluster in Docker: Architecture & Overview
Webswing Cluster modularizes deployment into three distinct components:
-
Cluster Server: A stateless gateway managing browser connections, load balancing across Session Pools, and web-level configuration (security, SSL, static resources).
-
Session Pool: Stateful handlers that launch and manage Java desktop application instances. They connect via WebSocket to all Cluster Servers and maintain session-level state.
-
Admin Console: A centralized interface offering monitoring, configuration, REST API access, log viewing, and Cluster management tools.
Why Run in Docker?
-
Modules are packaged independently using Docker images, simplifying deployment, scaling, and configuration management, especially in container orchestration environments like Kubernetes.
-
Docker supports isolating Cluster Servers, Session Pools, and Admin Console into lightweight, reproducible containers.
Docker Setup & Image Guidance
For Kubernetes or Docker-based deployments, Webswing provides example Dockerfiles:
-
Admin Console: The maintained Kubernetes example uses a Java 21 image and includes
webswing-admin-server.warwith a startup script exposing port 8080. -
Cluster Server: Packaging
webswing.warwithin the cluster distribution and launching the cluster module via the embedded Jetty launcher. -
Session Pool: Uses built-in XHeadless and the Java desktop libraries to support headless applications, runs within Docker, and starts the session-pool module. For applications that require a full X server, such as some JOGL or JxBrowser setups, enable the optional Xvfb installation in the Dockerfile. If the Dockerfile generates its startup script, also uncomment its Xvfb launch line. Existing
.shentrypoints preserve an explicitly configuredDISPLAYand otherwise usexvfb-runwhen it is available.
These can be used as reference or extended to suit your base OS, Java version, or architecture.
Configuration Files & Their Roles
Webswing Cluster relies on several important JSON config files:
- webswing-server.config (Cluster Server)
Defines web-level settings: paths, security, CORS, datastore, and upload limits.
Example snippet:
{
"/": {
"path": "/",
"security": { /* users, roles... */ },
"dataStore": {
"module": "FILESYSTEM",
"config": { "transferFolder": "/data/transfer" }
},
"allowedCorsOrigins": ["*"]
},
"/app": { "enabled": true, "maxClients": 100, ... }
}
- webswing-app.config (Session Pool)
Contains application specific definitions: launcher config, timeouts, UI features, file upload/download flags, etc.
Example snippet:
{
"/app": {
"jreExecutable": "/usr/bin/java",
"launcherConfig": { "mainClass": "com.example.Main" },
"allowUpload": true,
"directdraw": true,
"jsLinkWhitelist": ["*"]
}
}
- webswing-sessionpool.properties
Handles cluster connectivity and pool behavior: secret key (shared among all modules), WebSocket URLs, session pool ID, reconnection settings.
Key settings:
webswing.connection.secret=ALPHANUMERICKEY
webswing.server.websocketUrl=ws://cluster-server:8080
sessionpool.instances.max=10
- webswing.properties
Defines shared security, WebSocket secrets, and load-balancing strategies. For instance, to change load balancing from round-robin to active-sessions-based:
org.webswing.server.api.service.sessionpool.loadbalance.LoadBalanceResolver=org.webswing.server.core.services.sessionpool.loadbalance.ActiveSessionsCountLoadBalanceResolver
Docker Configuration Workflow
Step 1: Build Images
Build images using provided Dockerfile templates:
webswing-admin→ Admin Console
FROM eclipse-temurin:21-jdk
RUN apt-get update && apt-get install --no-install-recommends -y \
wget \
unzip \
less \
nano \
procps \
dos2unix
COPY *.zip /opt/webswing-admin/dist.zip
RUN unzip /opt/webswing-admin/dist.zip -d /opt/webswing-admin && \
mv /opt/webswing-admin/webswing-admin-*/* /opt/webswing-admin && \
rm -d /opt/webswing-admin/dist.zip /opt/webswing-admin/webswing-admin-*/
COPY *.war /opt/webswing-admin/webswing-admin-server.war
ENV WEBSWING_HOME=/opt/webswing-admin
COPY docker/docker.tgz .
RUN tar xzvf docker.tgz --strip 1 -C /usr/local/bin docker/docker && rm docker.tgz
WORKDIR $WEBSWING_HOME
RUN mkdir -p /etc/service/webswing-admin && \
echo "#!/bin/sh\ncd $WEBSWING_HOME\nexec $JAVA_HOME/bin/java \$1 -jar $WEBSWING_HOME/server/webswing-jetty-launcher.jar -admin \$2" > /etc/service/webswing-admin/run && \
chmod +x /etc/service/webswing-admin/run
COPY ./webswing-admin.properties /opt/webswing-admin/webswing-admin.properties
COPY ./webswing-autoscaling.config /opt/webswing-admin/webswing-autoscaling.config
COPY ./start_sp.sh /opt/webswing-admin/start_sp.sh
COPY ./stop_sp.sh /opt/webswing-admin/stop_sp.sh
COPY ./secret.key /opt/webswing-admin/secret.key
RUN dos2unix /opt/webswing-admin/start_sp.sh
RUN dos2unix /opt/webswing-admin/stop_sp.sh
EXPOSE 8080
CMD /etc/service/webswing-admin/run "$ADMIN_JAVA_OPTS" "$ADMIN_OPTS"
webswing-server→ Cluster Server
FROM eclipse-temurin:21-jre
RUN apt-get update && apt-get install --no-install-recommends -y \
wget \
unzip \
less \
nano \
procps
COPY *.zip /opt/webswing-cluster/dist.zip
RUN unzip /opt/webswing-cluster/dist.zip -d /opt/webswing-cluster && \
mv /opt/webswing-cluster/webswing-cluster-*/* /opt/webswing-cluster && \
rm -d /opt/webswing-cluster/dist.zip /opt/webswing-cluster/webswing-cluster-*/
COPY *.war /opt/webswing-cluster/webswing.war
ENV WEBSWING_HOME=/opt/webswing-cluster
WORKDIR $WEBSWING_HOME
RUN mkdir -p /etc/service/webswing-cluster && \
echo "#!/bin/sh\ncd $WEBSWING_HOME\nexec $JAVA_HOME/bin/java \$1 -jar $WEBSWING_HOME/server/webswing-jetty-launcher.jar \$2" > /etc/service/webswing-cluster/run && \
chmod +x /etc/service/webswing-cluster/run
EXPOSE 8080
COPY ./webswing.properties /opt/webswing-cluster/webswing.properties
COPY ./webswing-server.config /opt/webswing-cluster/webswing-server.config
COPY ./secret.key /opt/webswing-cluster/secret.key
COPY ./apps /opt/webswing-cluster/apps
CMD /etc/service/webswing-cluster/run "$WEBSWING_JAVA_OPTS" "$WEBSWING_OPTS"
webswing-session→ Session Pool
FROM eclipse-temurin:21-jdk
RUN apt-get update && apt-get install --no-install-recommends -y \
wget \
unzip \
libxext6 \
libxi6 \
libxtst6 \
libxrender1 \
libpangoft2-1.0-0 \
dos2unix \
less \
nano \
procps
COPY *.zip /opt/webswing-sessionpool/dist.zip
RUN unzip /opt/webswing-sessionpool/dist.zip -d /opt/webswing-sessionpool && \
mv /opt/webswing-sessionpool/webswing-cluster-*/* /opt/webswing-sessionpool && \
rm -d /opt/webswing-sessionpool/dist.zip /opt/webswing-sessionpool/webswing-cluster-*/
COPY *.war /opt/webswing-sessionpool/webswing.war
ENV WEBSWING_HOME=/opt/webswing-sessionpool
WORKDIR $WEBSWING_HOME
# Built-in XHeadless is used by default; leave DISPLAY unset.
# For applications requiring a full X server (e.g. JOGL or JxBrowser),
# uncomment the installation and the Xvfb launch line below.
# RUN apt-get update && apt-get install --no-install-recommends -y xvfb xauth
RUN mkdir -p /etc/service/webswing-sessionpool && \
echo "#!/bin/sh\ncd $WEBSWING_HOME\nexec $JAVA_HOME/bin/java \$1 -jar $WEBSWING_HOME/webswing.war \$2" > /etc/service/webswing-sessionpool/run && \
chmod +x /etc/service/webswing-sessionpool/run
COPY ./webswing-app.config /opt/webswing-sessionpool/webswing-app.config
COPY ./webswing-sessionpool.properties /opt/webswing-sessionpool/webswing-sessionpool.properties
COPY ./secret.key /opt/webswing-sessionpool/secret.key
COPY ./apps /opt/webswing-sessionpool/apps/
COPY ./fonts /opt/webswing-sessionpool/fonts/
ENV WEBSWING_OPTS="-sessionpool"
RUN echo "#!/bin/sh" > ./start.sh && \
# echo "exec xvfb-run -a /etc/service/webswing-sessionpool/run \"\$WEBSWING_JAVA_OPTS\" \"\$WEBSWING_OPTS\"" >> ./start.sh && \
echo "exec /etc/service/webswing-sessionpool/run \"\$WEBSWING_JAVA_OPTS\" \"\$WEBSWING_OPTS\"" >> ./start.sh && \
chmod +x ./start.sh
CMD ./start.sh
Step 2: Provide Config Files
Mount all required config files into each container:
- Cluster Server:
webswing-server.config,webswing.properties,jetty.properties, TLS certs, etc. - Session Pool:
webswing-app.config,webswing-sessionpool.properties, plus app binaries and fonts. - Admin Console:
webswing-admin.properties, REST config, etc.
These files can be also part of the images created in Step 1
Step 3: Environment Variables & Secrets
Set WEBSWING_OPTS, WEBSWING_JAVA_OPTS, and ensure webswing.connection.secret is consistent across modules. Map volumes for persistent storage or shared transfer folders.
Step 4: Networking & Service Exposure
- Expose ports, e.g., 8080 for Cluster Server and Admin Console.
- Connect Session Pools via WebSocket to Cluster Server using defined URLs.
- In orchestration (e.g., Docker Compose or Kubernetes), manage service names and ports accordingly.
Step 5: Scaling & High Availability
- Cluster Server: Stateless—spin up multiple replicas for load balancing.
- Session Pool: Scale based on load; each pool manages its own app instances.
- Admin Console remains singleton or backed with shared state.
Step 6: Monitor & Tune
- Use hardware guidance: ~$300 MB RAM & 1 CPU per 50 users; plan with metrics
- Enable verbose logging (
-v) or via Admin UI for debugging cluster behavior
Sample Docker Compose Snippet (Simplified)
version: "3.8"
services:
cluster:
image: your/webswing-cluster:latest
volumes:
- ./config/webswing-server.config:/opt/webswing-cluster/webswing-server.config
- ./config/webswing.properties:/opt/webswing-cluster/webswing.properties
ports:
- "8080:8080"
sessionpool:
image: your/webswing-session:latest
volumes:
- ./config/webswing-app.config:/opt/webswing-sessionpool/webswing-app.config
- ./config/webswing-sessionpool.properties:/opt/webswing-sessionpool/webswing-sessionpool.properties
- ./app:/opt/webswing-sessionpool/apps
depends_on:
- cluster
admin:
image: your/webswing-admin:latest
volumes:
- ./config/webswing-admin.properties:/opt/webswing-admin/webswing-admin.properties
ports:
- "8081:8080"
Summary Table
| Component | Config Files | Key Responsibilities |
|---|---|---|
| Cluster Server | webswing-server.config, webswing.properties |
Routing, load balancing, session tracking, web exposure |
| Session Pool | webswing-app.config, webswing-sessionpool.properties |
Launching Java apps, managing app sessions |
| Admin Console | webswing-admin.properties |
Monitoring, configuration, UI dashboard, REST API |
Final Tips
- Secret key consistency is critical across cluster, session-pool, and admin modules to secure WebSocket communication and session tokens (JWT)
- Use shared filesystem (e.g., Docker volumes or host paths) for data store (uploads, thread dumps), or rely on
directTransfermode which uses websocket streams instead of HTTP - Monitor resource consumption—Webswing recommends empirical testing rather than fixed AML values
- The packaged Cluster deployment example is maintained under
webswing-cluster/webswing-cluster-assembly/src/main/containerized-example; canonical image recipes live underwebswing-cluster/webswing-cluster-assembly/src/main/container-imagesandwebswing-admin/webswing-admin-assembly/src/main/container-images