Docker
Introduction
Starting with version 2.2.0 of the operator, the operator can run on pure Docker hosts. Such a setup provides many of the benefits of running ShinyProxy on Kubernetes, without the complexity of running Kubernetes. Deploying ShinyProxy with the operator is the recommended approach. See the Features page for an overview of all benefits.
Tutorial
Installing the operator
-
Prepare a server with your favorite Linux distribution. If you don’t know which distribution to pick, we advice to start with Ubuntu Server LTS.
-
Install Docker on Debian, Ubuntu, CentOS or RHEL. It’s recommended to use the Docker binaries provided by the Docker website and not by your Linux distribution. When using Ubuntu, make sure to not use the Docker snap as this can cause problems as well.
-
The operator creates some directories and files, it’s important that these files are owned by a non-root user. Therefore, make sure to have a non-root user ready. Create a user. if you don’t have a user yet (i.e. you are logged root):
sudo useradd -m shinyproxy
The remainder of this tutorial assumes that you are using a user called
shinyproxy
, with the home directory/home/shinyproxy/shinyproxy
. If you continue with a different user or home directory, make sure to change this in the upcoming commands. -
Create a (global) storage directory for ShinyProxy:
sudo mkdir -p /opt/shinyproxy-docker-operator/data sudo chown -R shinyproxy:shinyproxy /opt/shinyproxy-docker-operator
-
Get the id of the
shinyproxy
user:sudo id -u shinyproxy
-
Get the id of the
docker
group:sudo getent group docker | cut -d: -f3
-
As the
shinyproxy
user, create a directory for the configuration files of ShinyProxy:sudo -u shinyproxy mkdir -p /home/shinyproxy/shinyproxy/input
-
Inside the home directory of the non-root user (i.e.
/home/shinyproxy/shinyproxy
), create thedocker-compose.yml
file. Make sure to fill in the ids of step 5 and 6 in the highlighted lines:sudo -u shinyproxy nano /home/shinyproxy/shinyproxy/docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
services: shinyproxy-operator: image: openanalytics/shinyproxy-operator:2.2.0 environment: SPO_ORCHESTRATOR: docker SPO_DOCKER_GID: 1234 # replace by the id of step 6 volumes: - ./input:/opt/shinyproxy-docker-operator/input - /var/run/docker.sock:/var/run/docker.sock:ro - /opt/shinyproxy-docker-operator/data:/opt/shinyproxy-docker-operator/data group_add: - 1234 # replace by the id of step 6 networks: - sp-shared-network restart: always labels: app: shinyproxy-operator user: "1234" # replace by the id of step 5 (must be a sting) networks: sp-shared-network: name: sp-shared-network
-
Start the ShinyProxy Operator
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
The operator is now running. It’s a good idea to have a look at the logs to ensure no warnings or errors are logged:
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml logs -f
On startup, the operator logs all its configuration parameters. The last few log lines should look similar to:
07:54:42.291 [main ] INFO eu.op.sh.Main - Starting background processes of ShinyProxy Operator
07:54:42.304 [main ] INFO eu.op.sh.im.so.FileSource - No input files found
07:54:42.305 [main ] INFO eu.op.sh.im.so.FileSource - FileSource ready
07:54:42.306 [main ] INFO eu.op.sh.im.do.DockerOrchestrator - Initializing DockerOrchestrator
07:54:42.762 [main ] INFO eu.op.sh.im.do.RedisConfig - Re-using password from Redis state
07:54:43.483 [atcher-worker-1] INFO eu.op.sh.Main - Starting ShinyProxy Operator
07:54:43.485 [atcher-worker-1] INFO eu.op.sh.co.ShinyProxyController - Starting ShinyProxyController
See the troubleshooting section if you see an error in the logs.
As the operator is now running, you are ready to deploy a ShinyProxy server, this is explained in the next section.
Deploying a ShinyProxy server
To deploy a ShinyProxy server using the operator, you must create a
configuration file in the input (/home/shinyproxy/shinyproxy/input
) directory.
This file is similar to the application.yml
file used by ShinyProxy itself,
although a few additional properties are supported.
Before starting the deployment, you should decide on a domain name to use for
the server. If you are running this tutorial on your laptop, you can simply use
localhost
. Otherwise, you can use the IP address of the server (use ip addr
to find it). If you want to expose this server to the network (internet or LAN),
you must use a domain name (e.g. shinyproxy.example.com
) and setup the DNS
records. The remainder of this tutorial assumes the domain name is localhost
.
Next, create the input file /home/shinyproxy/shinyproxy/input/localhost.shinyproxy.yaml
,
with the following demo configuration:
|
|
The important parts of this configuration file are:
- lines 1-8: these properties are required when using the operator. Don’t remove or change these lines.
- line 9: specifies the
realm-id
of the server. This is used to identify the server in logs, the monitoring stack and Redis. Choose a short and simple string. - line 29: specifies the Docker image to use for the ShinyProxy server
- line 30: specifies the domain name (
fqdn)
to use
The other parts of the file are the normal ShinyProxy configuration properties.
In this case, we configure two users and two apps. Every minute, ShinyProxy
checks the input directory for new files. Look at the logs of the operator (
using
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml logs -f
)
and wait for the operator to create the new server. Once the operator has
discovered the configuration file, you should logs output similar to:
09:33:24.797 [atcher-worker-1] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 0/4: Ok] ReconcileSingleShinyProxy
09:33:24.827 [atcher-worker-1] INFO eu.op.sh.im.do.RedisConfig - [Redis] Pulling image
09:33:25.857 [atcher-worker-1] INFO eu.op.sh.im.do.RedisConfig - [Redis] Creating new container
09:33:26.212 [atcher-worker-1] INFO eu.op.sh.im.do.DockerOrchestrator - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Docker] Pulling image
09:33:26.752 [atcher-worker-3] INFO eu.op.sh.im.do.DockerOrchestrator - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Docker] Creating new container
09:33:27.080 [atcher-worker-3] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 1/4: Reconciling] [Container]
09:33:27.372 [atcher-worker-1] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Container: 601d0fa70223a] not ready yet (0/24)
09:33:32.407 [atcher-worker-1] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Container: 601d0fa70223a] not ready yet (1/24)
09:33:37.436 [atcher-worker-1] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Container: 601d0fa70223a] not ready yet (2/24)
09:33:42.845 [atcher-worker-1] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Container: 601d0fa70223a] ready
09:33:42.852 [atcher-worker-3] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 0/4: Ok] ReconcileSingleShinyProxy
09:33:42.910 [atcher-worker-3] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 1/4: Ok] [Container]
09:33:42.920 [atcher-worker-3] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 2/4: Ok] [LatestMarker] Instance became latest
09:33:42.921 [atcher-worker-3] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/3500196eb4d8294a5bccf475e7b4884f8a653b6e/0] [Step 3/4: Reconciling] [Ingress]
09:33:42.947 [atcher-worker-1] INFO eu.op.sh.im.do.CaddyConfig - [Caddy] Pulling image
09:33:43.875 [atcher-worker-1] INFO eu.op.sh.im.do.CaddyConfig - [Caddy] Creating new container
09:33:44.162 [atcher-worker-1] INFO eu.op.sh.im.do.CaddyConfig - [Caddy] Not ready yet (0/24)
09:33:44.689 [atcher-worker-1] INFO eu.op.sh.im.do.CaddyConfig - [Caddy] Ready (1/24)
The ShinyProxy server is now ready to use and is accessible by going to the
configured domain name (e.g. http://localhost/
). You can
login by using the username
jack
and the password password
. Click on Hello Application
to start the
first demo app.
Note
Don’t specify:8080
(or any other
port) when accessing the server through the domain name. The operator
automatically deploys Caddy as reverse proxy, therefore all ShinyProxy servers
deployed by the operator are accessible on the default HTTP port (80
).
See the troubleshooting section if your servers fails to start.
Updating a ShinyProxy server
Updating the configuration of a ShinyProxy server (e.g. to add a new app) is as simple as modifying the configuration file and waiting for the operator to create a new instance. There is no need to restart the ShinyProxy Operator (or its container). The operator checks the input file every minute for changes. So after changing the config file, the operator automatically detects the changed and re-tries deploying the ShinyProxy server.
Note
You can update the image of an app without modifying the configuration of ShinyProxy, see this section on how to enable this.Enabling TLS
Using Let’s Encrypt
The ShinyProxy Operator makes use of Caddy as a reverse proxy. A unique feature of Caddy is that it’s able to fully automatically configure TLS for your domain, typically using the free certificates provided by Let’s Encrypt.
-
Before enabling TLS, make sure to meet the following requirements:
- ShinyProxy is configured to use a public domain name (e.g.
shinyproxy.example.com
) - DNS is configured, such that this domain name points to your server
- the ShinyProxy server is accessible over the internet
Note: Caddy automatically renews the certificate when needed, therefore, the server must be accessible from the internet at all times.
- ShinyProxy is configured to use a public domain name (e.g.
-
Add the
SPO_CADDY_ENABLE_TLS: "true"
environment variable to thedocker-compose.yml
file:services: shinyproxy-operator: image: openanalytics/shinyproxy-operator:2.2.0 # ... environment: SPO_ORCHESTRATOR: docker SPO_DOCKER_GID: 1234 # replace by the id of step 6 SPO_CADDY_ENABLE_TLS: "true" # ...
-
Restart the ShinyProxy Operator (this is only needed once, because we added the
SPO_CADDY_ENABLE_TLS
environment variable):sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
If you aren’t sure whether all requirements are met, you can simply try enabling TLS and observe whether it works. If not, the Caddy logs contain more information:
sudo docker logs -f sp-caddy
Using custom certificates
The operator allows to use a certificate you already own. This is useful for deployments in organisations with a custom PKI.
-
Add the
SPO_CADDY_ENABLE_TLS: "true"
environment variable to thedocker-compose.yml
file:services: shinyproxy-operator: image: openanalytics/shinyproxy-operator:2.2.0 # ... environment: SPO_ORCHESTRATOR: docker SPO_DOCKER_GID: 1234 # replace by the id of step 6 SPO_CADDY_ENABLE_TLS: "true" # ...
-
Put your certificates somewhere in the input directory. In this example we put the cert and key at:
/home/shinyproxy/shinyproxy/input/mycert.crt
/home/shinyproxy/shinyproxy/input/mycert.key
-
Change the ShinyProxy configuration to reference the cert and key. Use the absolute path inside the operator container. In our example, we’re using the input directory to store the certs, therefore we can use the following config:
proxy: # .... caddyTlsCertFile: /opt/shinyproxy-docker-operator/input/mycert.crt caddyTlsKeyFile: /opt/shinyproxy-docker-operator/input/mycert.key
-
Restart the ShinyProxy Operator (this is only needed once, because we added the
SPO_CADDY_ENABLE_TLS
environment variable):sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
Enabling monitoring
The operator includes a complete monitoring stack for ShinyProxy. This collects logs, metrics, and usage statistics. The following open source components are used:
Grafana acts as the UI for all these components. It’s automatically embedded in Grafana, meaning you can re-use the authentication of ShinyProxy to access it. Only admin users can access it.
To enable monitoring:
-
Install the Loki Docker driver. The operator includes a script to do this:
sudo docker run --group-add $(getent group docker | cut -d: -f3) -v /var/run/docker.sock:/var/run/docker.sock:ro openanalytics/shinyproxy-operator:2.2.0 /install_plugins.sh
-
Add the
SPO_ENABLE_MONITORING: "true"
environment variable to thedocker-compose.yml
file:services: shinyproxy-operator: image: openanalytics/shinyproxy-operator:2.2.0 # ... environment: SPO_ORCHESTRATOR: docker SPO_DOCKER_GID: 1234 # replace by the id of step 6 SPO_ENABLE_MONITORING: "true" # ...
-
Add the log configuration to the
docker-compose.yml
file. This is required to collect the logs of the operator itself:services: shinyproxy-operator: image: openanalytics/shinyproxy-operator:2.2.0 # ... logging: driver: loki options: loki-url: "http://localhost:3100/loki/api/v1/push" mode: non-blocking loki-external-labels: app=shinyproxy-operator,namespace=default
-
Restart the ShinyProxy Operator (this is only needed once, because we modified the
docker-compose.yml
file):sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
-
Add a user (e.g.
jack
) as an admin (in the ShinyProxy configuration):proxy: # ... admin-users: - jack
After a few minutes all components should be running. Grafana is now accessible
at the /grafana
sub-path on your ShinyProxy server. For example, if your
fqdn
is localhost
, Grafana is accessible at
http://localhost/grafana
.
Adding templates
The look and feel of ShinyProxy can be customized by editing
the templates.
When using the operator you can put custom templates in the
input/templates/<realm-id>/
directory. Where input/
is the directory where
the ShinyProxy configuration files are located and <realm-id>
is the value of
the proxy.realm-id
property.
Warning
The templates are copied on every deployment of a new server. Make sure to change some (dummy) property in the configuration when making changes to the templates.If the operator has discovered the templates it logs a line similar too:
13:36:39.723 [atcher-worker-1] INFO eu.op.sh.im.do.DockerOrchestrator - [default-localhost/global] [Docker] Templates copied
If this line doesn’t appear in the logs, the templates are probably placed in the wrong directory.
Configuration reference
Operator configuration
In most situations, the operator itself needs very little configuration.
Nevertheless, for some specific cases some configuration options are available.
These options are specified using environment variables. All variables start
with the SPO
prefix, meaning ShinyProxyOperator.
SPO_ORCHESTRATOR
: (required) can either bekubernetes
(default) ordocker
.SPO_DOCKER_GID
: (required)SPO_LOG_LEVEL
: configures the log level of the operator, may be one of the following:OFF
: disables loggingERROR
WARN
INFO
DEBUG
: default (may change)TRACE
ALL
: enables all logging
SPO_CADDY_ENABLE_TLS
: (optional) boolean flag enabling TLS, disabled by default.SPO_ENABLE_MONITORING
: (optional) boolean flag enabling monitoring, disabled by default.SPO_GRAFANA_ROLE
: (optional) the role used by Grafana for new users. Valid options areAdmin
,Editor
andViewer
(default).SPO_IMAGE_PULL_POLICY
: (optional) pull policy for images used by the operator (e.g. Redis and Caddy). Doesn’t apply to the image of ShinyProxy itself and doesn’t change the behavior of ShinyProxy. Valid options areNever
,IfNotPresent
andAlways
(default).
The following options are more advanced and may cause problems if not used correctly:
SPO_DISABLE_ICC
: (optional) boolean flag enabling inter-container connectivity, enabled by default. Disabling this requires additional setup and configuration.SPO_FILE_POLL_INTERVAL
: (optional) time in seconds that ShinyProxy waits before checking for changes in configurationSPO_DOCKER_SOCKET
: (optional) the location of the Docker socket on the host, default is/var/run/docker.sock
.SPO_DOCKER_DATA_DIR
: the directory where ShinyProxy stores its data, default is/opt/shinyproxy-docker-operator/data/
SPO_INPUT_DIR
: the directory containing the input (configuration) files, default is/opt/shinyproxy-docker-operator/input
SPO_CADDY_IMAGE
: the Caddy image to use, default isdocker.io/library/caddy:2.8
SPO_CADVISOR_IMAGE
: the cAdvisor image to use, default isgcr.io/cadvisor/cadvisor:v0.49.1
SPO_GRAFANA_IMAGE
: the Grafana image to use, default isdocker.io/grafana/grafana-oss:11.6.1
SPO_GRAFANA_LOKI_IMAGE
: the Grafana Loki image to use, default isdocker.io/grafana/loki:3.2.2
SPO_PROMETHEUS_IMAGE
: the Prometheus image to use, default isdocker.io/prom/prometheus:v3.0.1
SPO_REDIS_IMAGE
: the Redis image to use, default isdocker.io/library/redis:7.2.4
ShinyProxy configuration
Configuration (of the operator) that’s specific to a single ShinyProxy server, must be configured in the configuration file of that ShinyProxy Server. In other words, both the operator and ShinyProxy itself read this configuration file. The following configuration options can be used:
image
: (required) the Docker image to use for ShinyProxy (e.g.openanalytics/shinyproxy:3.2.0
)image-pull-policy
: (optional) pull policy for the ShinyProxy image (doesn’t change the behavior of ShinyProxy). Valid options areNever
,IfNotPresent
andAlways
(default).fqdn
: (required) the fully qualified domain name, used to access ShinyProxy-
proxy.realm-id
: (required) identifier of the ShinyProxy server. Used in logs, the monitoring stack and Redis. Maximum length is 63 characters, only alphanumeric characters and-
allowed, but may not start or end with-
. additionalFqdns
: (optional) a list of additional FQDNs that can be used to access ShinyProxy.replicas
: (optional) the number of ShinyProxy replicas to run.labels
: (optional) map of labels to add to the ShinyProxy container.memory-request
: (optional) the minimum amount of memory available to a single ShinyProxy instance. Uses the same format as for apps. For example1G
.memory-limit
: (optional) the maximum amount of memory available to a single ShinyProxy instance. Uses the same format as for apps. For example1G
.cpu-limit
: (optional) the maximum amount of CPU time available to a single ShinyProxy instance. Uses the same format as for apps. For example1
(= 1 CPU core).dns
: (optional) list of DNS servers to be used by the ShinyProxy container.caddyTlsCertFile
: (optional) path to a TLS certificate file (see Enabling TLS).caddyTlsKeyFile
: (optional) path to a TLS key file(see Enabling TLS).
Mandatory configuration
In order for the operator to work correctly, the following configuration must always be included in every input file. In addition, don’t change the values.
spring:
session:
store-type: redis
proxy:
store-mode: Redis
docker:
internal-networking: true
stop-proxies-on-shutdown: false
authentication: simple
Forbidden configuration
To make things easy, the operator automatically adds a few configuration properties to the ShinyProxy configuration. These configuration properties shouldn’t be used in the input files. The full list of forbidden properties is:
logging.file.name
management.prometheus.metrics.export.enabled
management.server.port
proxy.docker.loki-url
proxy.log-as-json
proxy.monitoring.grafana-url
proxy.port
proxy.template-path
proxy.usage-stats-url
spring.config.import
spring.data.redis.host
spring.data.redis.password
Troubleshooting
Issue with the data directory
The operator requires a data directory, in order to share files between the
multiple containers it creates. This data directory exists on the Docker host
and is mounted in the container. The directory must exist before the operator is
started, and must be owned by a non-root user. Finally, the id of the owner of
this directory must be set inside the docker-compose.yml
file.
If one of these pre-requisites isn’t met, the operator may fail with one these errors:
Exception: The data directory doesn't exist: '/opt/shinyproxy-docker-operator/data'!
Exception: Missing read permission for the data directory: '/opt/shinyproxy-docker-operator/data'!
Exception: Missing write permission for the data directory: '/opt/shinyproxy-docker-operator/data'!
To fix this, follow these steps:
-
Re-create the directory:
sudo mkdir -p /opt/shinyproxy-docker-operator/data
-
Change the owner of the directory to the non-root user, e.g.
shinyproxy
:sudo chown shinyproxy:shinyproxy /opt/shinyproxy-docker-operator sudo chown shinyproxy:shinyproxy /opt/shinyproxy-docker-operator/data
-
Change the permissions of the directory:
sudo chmod 755 /opt/shinyproxy-docker-operator sudo chmod 755 /opt/shinyproxy-docker-operator/data
-
Check that the
docker-compose.yml
file contains a volume mapping for the data directory:1 2 3 4 5 6 7 8
services: shinyproxy-operator: # ... volumes: - ./input:/opt/shinyproxy-docker-operator/input - /var/run/docker.sock:/var/run/docker.sock:ro - /opt/shinyproxy-docker-operator/data:/opt/shinyproxy-docker-operator/data # ...
-
Check that the container runs as the non-root user:
-
Get the id of the user:
sudo id -u shinyproxy
-
Then make sure it’s configured in the
docker-compose.yml
file:1 2 3 4
services: shinyproxy-operator: # ... user: "1234" # replace by the id of the previous step (must be a sting)
-
-
Re-create the container:
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
Issue with the input directory
The operator reads the configuration files (for ShinyProxy) from an input directory. Similarly, to the data directory, this directory must be mounted in the container and also accessible the container.
If this isn’t the case, the operator may fail with the error:
Exception: Missing read permission for the input '/opt/shinyproxy-docker-operator/input' directory!
To fix this, follow these steps:
-
Re-create the directory (the
input
directory must be created in the same directory as thedocker-compose.yml
file):sudo mkdir -p /home/shinyproxy/shinyproxy/input
-
Change the owner of the directory to the non-root user, e.g.
shinyproxy
:sudo chown shinyproxy:shinyproxy /home/shinyproxy/shinyproxy/input
-
Change the permissions of the directory:
sudo chmod 755 /home/shinyproxy/shinyproxy/input
-
Check that the
docker-compose.yml
file contains a volume mapping for the data directory:1 2 3 4 5 6 7 8
services: shinyproxy-operator: # ... volumes: - ./input:/opt/shinyproxy-docker-operator/input - /var/run/docker.sock:/var/run/docker.sock:ro - /opt/shinyproxy-docker-operator/data:/opt/shinyproxy-docker-operator/data # ...
-
Re-create the container:
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
Issue with the Docker socket
The ShinyProxy Operator (just like ShinyProxy itself) needs access to the Docker
daemon. This is archived by mounting the Docker socket into the container. The
socket is owned by the docker
group. To ensure that the operator can use the
socket, it must be part of the docker
group. Therefore, the id of the group
must be configured in the docker-compose.yml
file.
If one of these pre-requisites isn’t met, the operator may fail with the error:
Exception: No permission to access Docker daemon, check the mount of the socket and the 'SPO_DOCKER_GID' environment variable.
To fix this, follow these steps:
-
Fix the permissions of the Docker socket:
sudo chown -R root:docker /var/run/docker.sock
-
Get the id of the
docker
group:sudo getent group docker | cut -d: -f3
-
Check that the
docker-compose.yml
file contains this id at two places: in theSPO_DOCKER_GID
environment variable and in thegroup_add
parameter:1 2 3 4 5 6 7 8 9
services: shinyproxy-operator: # ... environment: SPO_ORCHESTRATOR: docker SPO_DOCKER_GID: 1234 # replace by the id of step 2 group_add: - 1234 # replace by the id of step 2 # ...
-
Check that the
docker-compose.yml
file contains a volume mapping for the Docker socket:1 2 3 4 5 6 7 8
services: shinyproxy-operator: # ... volumes: - ./input:/opt/shinyproxy-docker-operator/input - /var/run/docker.sock:/var/run/docker.sock:ro - /opt/shinyproxy-docker-operator/data:/opt/shinyproxy-docker-operator/data # ...
-
Check that the
docker-compose.yml
file doesn’t contain a value for theSPO_DOCKER_SOCKET
environment variable -
Re-create the container:
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml down sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml up -d
ShinyProxy fails to start
There can be many reasons why your ShinyProxy servers fails to start, therefore start by looking at the logs of the operator using:
sudo docker compose -f /home/shinyproxy/shinyproxy/docker-compose.yml logs -f
In many cases the logs of the operator already explains the issue and a potential solution. For example, if you specify an incorrect image, you’ll receive an error similar to:
org.mandas.docker.client.exceptions.ImageNotFoundException: Image not found: my-example-image
The solution is then to modify the input file (e.g.
/home/shinyproxy/shinyproxy/input/localhost.shinyproxy.yaml
) and change the image
property.
Note
There is no need to restart the ShinyProxy Operator (or its container). The operator checks the input file every minute for changes. So after changing the config file, the operator automatically detects the changed and re-tries deploying the ShinyProxy server.Another common issue is that the operator is able to create the ShinyProxy container, but the container fails to startup. This is usually caused by some invalid properties in the configuration file. In most cases, the operator already logs the error reported by ShinyProxy:
09:55:35.175 [atcher-worker-2] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/24a8189e821d0edaa7997848cfea33b6917fec17/0] [Container: b328fb7bd6875] not ready yet (2/24)
09:55:40.183 [atcher-worker-2] INFO u.op.sh.im.do.ShinyProxyReadyChecker - [default-localhost/24a8189e821d0edaa7997848cfea33b6917fec17/0] [Container: b328fb7bd6875] failed (container has been restarted) (3/24)
09:55:40.205 [atcher-worker-2] INFO eu.op.sh.co.ShinyProxyController - [default-localhost/24a8189e821d0edaa7997848cfea33b6917fec17/0] Instance failed to start up, output: Full log file available at '/opt/shinyproxy-docker-operator/data/logs/sp-default-localhost-24a8189e821d0edaa7997848cfea33b6917fec17-0-LPIOHqcFin/shinyproxy.log', last output: ShinyProxy crashed! Exception: 'java.lang.RuntimeException', message: 'Unknown authentication type:simpl'
In this example, we used the following invalid config:
proxy:
authentication: simpl
And as expected, the error indicates the incorrect property:
Unknown authentication type:simpl
. Changing this to the correct value, will
fix the issue and allow ShinyProxy to start:
proxy:
authentication: simple
If the issues doesn’t become clear from the operator logs, the next step is to
look at the full logs of ShinyProxy itself. The operator automatically stores
these logs on disk in the /opt/shinyproxy-docker-operator/data/logs/
directory. As can be seen in the example logs, the operator also reports the
exact location of the logs. You can easily view these logs on the Docker host
using:
less /opt/shinyproxy-docker-operator/data/logs/sp-default-localhost-24a8189e821d0edaa7997848cfea33b6917fec17-0-LPIOHqcFin/shinyproxy.log
In some cases these logs can be empty, especially when an error occurs before ShinyProxy can write it logs. In this case you can find the error using the Docker CLI:
-
List all containers:
sudo docker ps -a
-
Find the ShinyProxy container in the list, and copy its name
-
View the logs of the container:
sudo docker logs -f sp-default-localhost-24a8189e821d0edaa7997848cfea33b6917fec17-0-LPIOHqcFin
-
If you suspect an issue with the configuration of the container, you can inspect the container to view all its configuration:
sudo docker inspect sp-default-localhost-24a8189e821d0edaa7997848cfea33b6917fec17-0-LPIOHqcFin
Finally, make sure to check that you have set all mandatory config and aren’t using any forbidden config.