GithubHelp home page GithubHelp logo

Comments (28)

llionevans avatar llionevans commented on August 12, 2024 2

Yup, that was it. I was obviously trying to troubleshoot myself and forgot to change it back when it hadn't worked.

Amazing, thank you so much. I absolutely wouldn't have been able to do that by myself.

I think all the major parts are now in place. I need to do some tidying up and make some modifications (e.g. turn off saving screenshots to the server). Then I'll post a quick overview of the steps I took to get to this point in case it might be helpful to others (and as a reminder to my future self) then close this 'issue'.

If you're interested here's the result. You've already seen it a few years ago, but I wasn't able to update it thanks to having lost the ssh key (just after getting it up and running) and am only now getting the chance to rebuild. This is just three example datasets, two of which are prototype a fusion energy heat exchanger component. The samples have been manufactured, then CT scanned and the data converted into a micro-scale accurate FEA simulation. The idea is to simulate 'as manufactured' to pick up deviations that wouldn't be predicted in the 'as designed' model. One of the models has more than 20M tet elements, and it's impressive how responsive it still is remotely over a browser. I guess I'll then need to get some more recent data uploaded.

Truly, thank you sooo much. This has been on my 'to do' list for a very long time.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024 1

I think the docs had all the info I needed, but as someone relatively new to setting up a web server, ssl, containers and pvw (basically all of it) there was just a lot of terminology that I was unfamiliar with. So lots to learn during the process which I don't think I'd have been able to do without some hand holding, others might fare better.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

Hmmmm.... it may not be a timeout issue.

When I try to connect from a client (non-local browser) but on the same network, again I get the pvw demo landing page, again glance works, but this time when I click on visualizer it starts off with 'Loading ParaView...' then goes to 'Server Disconnected'.

So it appears that there's another issue somewhere that affects visualizer but not glance.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

Ok, I've gotten a bit further. I suspect that browser caching made me think some things above had worked, when indeed they hadn't.

So let's start again from the start.

I load the container with the following command:
sudo docker run --name pvw -p 0.0.0.0:80:80 --runtime=nvidia -d kitware/paraviewweb:pvw-egl-demo-v5.6.0 "ws://domain.co.uk:80/"

NOTE: I've now switched localhost with my domain name. I've also changed the port number to 80 (because I have no control over the firewall).

Locally: both domain.co.uk/visualizer and localhost/visualiser work.
Remotely (when on same network): I get the following for domain.co.uk

Index of /

Name	Last modified	Size	Description
cgi-bin/	2019-07-01 13:31	-	

If I remove the container and start again, but with my global IP
sudo docker run --name pvw -p GLOBAL_IP:80:80 --runtime=nvidia -d kitware/paraviewweb:pvw-egl-demo-v5.6.0 "ws://domain.co.uk:80/"

I now get the following:
Locally: domain.co.uk/visualizer works, localhost/visualiser gives 'can't establish a connection'.
Remotely (when on same network): visualizer now works
Remotely (different network): I get the following for domain.co.uk

Index of /

Name	Last modified	Size	Description
cgi-bin/	2019-07-01 13:31	-	

So I feel that I'm close, but am guessing that I'm doing something wrong with the ports and/or IP addresses/domain names.

Any suggestions gratefully appreciated.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

"ws://domain.co.uk:80/" was indeed the solution for one of your issue. But it seems now that you are hitting a network setup issue in your organization. You may want to check with your IT team. We should not have cgi-bin/. Maybe it is just the forward rule as you are missing the / after domain.co.uk/visualizer...

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

you're right. although i was getting some kind of response, and port 80 was the one I needed to use for http, the firewall wasn't actually letting me through. I think that's now been resolved.

It seems to work with -p 0.0.0.0:80:80 without needing to specify the server's global address. is this expected behaviour? If so, what's the point of specifying an IP with this flag?

Next I need to build in the capability to auto load pre-prepared pvsn scenes with a url once again as I'd previously done with the AWS image. Unfortunately, I can no longer log into that image due to losing the ssh key because of a failed hard drive, so I'll have to start from scratch. I assume nothing major has changed and I'll need to follow similar steps?

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

0.0.0.0 allow to work on any eth connection that you may have instead of picking only 1 network card.

For the pre-loading, it will be the same as before. But you may want to migrate to a newer image which also slightly change how things/parameters are provided to the image. It will allow you to bundle your custom visualizer / launcher. There is no real reason to switch except to keep up with the "new way" for doing ParaViewWeb apps. But in general the concepts remain exactly the same. The goal is really to streamline pvw deployment with custom code.

You should be able to read more about it here and there. With those, you won't need to build any docker, but instead you will have to create a file structure of your app (visualizer-edited+launcher-config) and just mount that directory. Also, the latest images are underneath ParaView which can be found here.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

That's a really good approach, rather than having to rebuild an image myself to customise, from what I understand, I can just mount certain directories with customised scripts to override the default ones.

Thanks for those links, they're very helpful. There's a lot there for me to start thinking about. I'll start testing and I'm sure to have some follow up questions later on.

Can I please check, is 'kitware/paraview:pvw-master-egl-py3' the latest stable version I should be looking at? Does this include apache and all the setup required for running multiple concurrent sessions? Or, should I in fact be looking at 'kitware/paraviewweb:pvw-v5.6.0-egl' if I want to minimise the things I need to set up?

There's not a huge amount I want to change, mostly it's the ability to pre-load from a url, maybe also a few other very small things like turning off the option for users to save screenshots/data/state onto the host as this will be publicly facing.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

All the kitware/paraview:pvw-* include Apache+Launcher and expect you to mount a /pvw directory with the structure described in the doc.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

No need to pick pvw-master-.... All the images in kitware/paraview have the same structure. It will just be a matter of which PV/Python version you need/want.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

Maybe I'm not understanding correctly, what are the differences between 'kitware/paraview:pvw-' and 'kitware/paraviewweb:pvw-'?

For example:
'kitware/paraview:pvw-v5.7.0-egl' and 'kitware/paraviewweb:pvw-v5.7.0-rc2-egl'

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

Normally there should not be any, but I don't remember when we make the cut of the new layout. And I'm assuming that the kitware/paraview are only the new ones while the one in kitware/paraviewweb would be based on the old structure which require the ws://... as arg vs -e environment variable along with that /pvw directory structure I was talking about.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

Ok, I've had a chance to play a bit more and 'I think' I'm slowly getting my head around this.

On my local machine I've built this file structure:
<APP_ROOT>=../pvw

<APP_ROOT>/run.sh
<APP_ROOT>/endpoints.txt
<APP_ROOT>/data/<SOME_FILES>
<APP_ROOT>/launcher/config.json
<APP_ROOT>/www/index.html

index.html is just a placeholder file at the moment for me to check that apache is serving up the page correctly to the browser.

The contents of the other files are below. When I go to localhost I see my index file. At localhost/visualizer, the page starts loading with the rotating splash but then I get "Session did not start before timeout expired. Check session logs." (see log output below)

When I was using the older demo container it opened relatively quickly. So I don't think the issue is because the timeout limit is set too low (30s for visualizer). The workstation is sufficiently powerful.

I see it mention port 9000, but I need to use port 80. I've changed this in the environment setup (see run.sh) but not in config.json. When I change it there, then it's as if apache doesn't serve anything to my browser.

What might you suggest I try?

run.sh

export PORT=80
export DATA=/home/$USER/containers/pvw/data
export DEPLOY=/home/$USER/containers/pvw
export SERVER_NAME=localhost:80
export PROTOCOL=ws

sudo docker run --name pvw --runtime=nvidia \
    -p 0.0.0.0:${PORT}:80                   \
    -v ${DATA}:/data                        \
    -v ${DEPLOY}:/pvw                       \
    -e "SERVER_NAME=${SERVER_NAME}"         \
    -e "PROTOCOL=${PROTOCOL}"               \
    -d kitware/paraview:pvw-v5.8.0-egl-py3

endpoints.txt

glance /opt/paraview/share/paraview-5.8/web/glance/www
lite /opt/paraview/share/paraview-5.8/web/lite/www
divvy /opt/paraview/share/paraview-5.8/web/divvy/www
visualizer /opt/paraview/share/paraview-5.8/web/visualizer/www
flow /opt/paraview/share/paraview-5.8/web/flow/www
DOCUMENT-ROOT-DIRECTORY /pvw/www/

launcher/config.json

{
  "resources": [ {"port_range": [9010, 9014], "host": "localhost"} ],
  "sessionData": {
    "updir": "/Home"
  },
  "configuration": {
    "log_dir": "/pvw/launcher/log",
    "host": "localhost",
    "endpoint": "paraview",
    "sessionURL": "SESSION_URL_ROOT/proxy?sessionId=${id}&path=ws",
    "timeout": 25,
    "upload_dir": "/data/upload",
    "fields": [],
    "port": 9000,
    "proxy_file": "/opt/launcher/proxy-mapping.txt",
    "sanitize": {
      "version": {
          "type": "regexp",
          "regexp": "^v[0-9]+.[0-9]+.[0-9]+$",
          "default": "v0.0.0"
      },
      "file": {
          "type": "regexp",
          "regexp": "^[-\\\\w./]+$",
          "default": "emptyFile"
      }
    }
  },
  "properties": {
    "dataDir": "/data",
    "webapps_dir": "/opt/paraview/share/paraview-5.7/web",
    "python_exec": "/opt/paraview/bin/pvpython"
  },
  "apps": {
    "visualizer": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "visualizer-with-file": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30",
        "--load-file", "${file}"
      ],
      "ready_line" : "Starting factory"
    },
    "paraview-lite": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/lite/server/pvw-lite.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "divvy": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/divvy/server/pvw-divvy.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "flow": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/flow/server/pvw-flow.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    }
  }
}

log

2020-12-09 18:00:31,630:INFO:twisted:Site starting on 9000
2020-12-09 18:00:31,631:INFO:twisted:Starting factory <twisted.web.server.Site object at 0x7feb499c97f0>
2020-12-09 18:01:01,495:INFO:twisted:"127.0.0.1" - - [09/Dec/2020:18:01:00 +0000] "POST /paraview/ HTTP/1.1" 503 78 "http://localhost/visualizer/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0"
2020-12-09 18:02:01,498:INFO:twisted:Timing out client: IPv4Address(type='TCP', host='127.0.0.1', port=52430)

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

"webapps_dir": "/opt/paraview/share/paraview-5.7/web",

Based on the version you are running on, it should be paraview-5.8.

You can look at the logs in "/pvw/launcher/log". I bet the process never start due to a command line error.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

hah, you're right. I changed those in endpoints.txt but missed that one. Thank you for your patience with me. On to the next step.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

I think I'm making good progress. I've now been able to get datasets/scenes to auto-load with a particular url (as I'm previously set up with the AWS ami).

The next thing I'm trying to to is set up for the server to work with https. Are there any guides for this?

I've tried the following without success:

  • create a certificate using certbot (on the host machine)
  • mount the following
    -v /etc/letsencrypt:/etc/letsencrypt \
    -v /var/lib/letsencrypt:/var/lib/letsencrypt \ 
  • update the script to launch docker PROTOCOL=wss

As I'm mounting my amended config.json file, should I also change the following line there from ws to wss?
"sessionURL": "SESSION_URL_ROOT/proxy?sessionId=${id}&path=ws",

I've tried both, but I still don't manage to connect when I try https instead of http.

An alternative approach I've not tried is to build on top of the docker image, so that certbot runs inside it rather than on the host. But I'd rather use the official pvw container rather than making my own (will make updating easier in future).

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

This is a bit old, but it is still valid. You want to use your host machine to do the encryption part via apache and run docker inside that host on regular http/ws.

That guide explain how to setup that host and use our docker image. Just make sure to use the docker image you've been playing with. No need to use an older version for it.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

Thanks, that guide is very helpful. I'm following it in parallel with this one which is helping with setting up the certificate.

I've set up the following (see below for contents, apologies for long paste dump, I can use pastebin if preferable?):
/etc/apache2/sites-available/001-pvw.conf
/etc/apache2/sites-available/002-pvw-https.conf
<APP_ROOT>/run.sh
<APP_ROOT>/launcher/config.json

After creating the apache conf files I added them and disables the default ones such that those listed above show up in ../sites-enabled/. I also restarted apache.

When I try booting the docker container I get the following:

docker: Error response from daemon: driver failed programming external connectivity on endpoint pvw (6319a7e957a2642cd1e0c90d11044c8006c3c4ebea54348ec43b0467ee6fce54): Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use.

If I stop the host apache server, then the container starts without error but I cannot connect over https to the site. I'm assuming apache should be running on the host while I start the container, so that wasn't the right thing to do. But I'm not sure how to avoid that error.

BTW - I think I need to use port 80 due to my organisation's firewall rules. I'm trying to find out if 443 is open for https traffic. I'm a bit confused in the scripts below which port numbers I should be changing and which ones I should leave alone.


/etc/apache2/sites-available/001-pvw.conf

<VirtualHost *:80>
  ServerName   avishai.ibsim.co.uk
  Redirect permanent / https://avishai.ibsim.co.uk/
</VirtualHost>

/etc/apache2/sites-available/002-pvw-https.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ProxyPreserveHost On
  ServerName   avishai.ibsim.co.uk
  ErrorLog /var/log/apache2/001-pvw_error.log
  CustomLog /var/log/apache2/001-pvw_access.log combined

  SSLEngine on
  SSLProxyEngine on

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/avishai.ibsim.co.uk/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/avishai.ibsim.co.uk/privkey.pem

  # Handle websocket forwarding
  ProxyPass /proxy ws://localhost:9000/proxy

  # Main server
  ProxyPass        / http://localhost:9000/
  ProxyPassReverse / http://localhost:9000/
</VirtualHost>
</IfModule>

<APP_ROOT>/run.sh

export PORT=80
export DATA=/home/llion/containers/pvw/data
export DEPLOY=/home/llion/containers/pvw
export index_new=/home/llion/containers/pvw/www/index_pvw.html
export SERVER_NAME=avishai.ibsim.co.uk:80
export PROTOCOL=wss

sudo docker run --name pvw -h avishai.ibsim.co.uk --runtime=nvidia \
    -p 0.0.0.0:${PORT}:80                   \
    -v ${DATA}:/data                        \
    -v ${DEPLOY}:/pvw                       \
    -v ${index_new}:/opt/paraview/share/paraview-5.8/web/visualizer/www/index.html                                  \
    -e "SERVER_NAME=${SERVER_NAME}"         \
    -e "PROTOCOL=${PROTOCOL}"               \
    -d kitware/paraview:pvw-v5.8.0-egl-py3

<APP_ROOT>/launcher/config.json

{
  "resources": [ {"port_range": [9010, 9014], "host": "localhost"} ],
  "sessionData": {
    "updir": "/Home"
  },
  "configuration": {
    "log_dir": "/pvw/launcher/log",
    "host": "localhost",
    "endpoint": "paraview",
    "sessionURL": "SESSION_URL_ROOT/proxy?sessionId=${id}&path=ws",
    "timeout": 25,
    "upload_dir": "/data/upload",
    "fields": [],
    "port": 9000,
    "proxy_file": "/opt/launcher/proxy-mapping.txt",
    "sanitize": {
      "version": {
          "type": "regexp",
          "regexp": "^v[0-9]+.[0-9]+.[0-9]+$",
          "default": "v0.0.0"
      },
      "file": {
          "type": "regexp",
          "regexp": "^[-\\\\w./]+$",
          "default": "emptyFile"
      }
    }
  },
  "properties": {
    "dataDir": "/data",
    "webapps_dir": "/opt/paraview/share/paraview-5.8/web",
    "python_exec": "/opt/paraview/bin/pvpython"
  },
  "apps": {
    "visualizer": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--load-file", "${dataFile}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "visualizer-with-file": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30",
        "--load-file", "${file}"
      ],
      "ready_line" : "Starting factory"
    },
    "paraview-lite": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/lite/server/pvw-lite.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "divvy": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/divvy/server/pvw-divvy.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "flow": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/flow/server/pvw-flow.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    }
  }
}

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

You are suppose to run docker on 9000 so https apache (on the host not in docker) can proxy to it.

https:443 apache (host) => http://localhost:9000 (docker)

9000 was just picked here, but you can choose another number. Just don't expose it to the outside. That is just internal to that machine...

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

That is your config in Apache

 # Handle websocket forwarding
  ProxyPass /proxy ws://localhost:9000/proxy

  # Main server
  ProxyPass        / http://localhost:9000/
  ProxyPassReverse / http://localhost:9000/

Which mean, you need to have docker running on 9000.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

I've had confirmation that port 443 is unblocked for my ip for https traffic. So that's one obstacle out of the way. I should also have mentioned that I tested this on a simple index.html page over https (not in the container) and it worked.

Thanks for your pointers. I've edited run.sh as below (the only file I've edited). I started apache again on the host. Rebooted the container, and this time it started without any error about "address already in use". So far, so good.

But when I go to the webpage I get a 502 status. Should I have edited something else as well e.g. should the ProxyPass you mention above be wss and https?

Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request

Reason: Error reading from remote server

run.sh

export PORT=9000
export DATA=/home/llion/containers/pvw/data
export DEPLOY=/home/llion/containers/pvw
export index_new=/home/llion/containers/pvw/www/index_pvw.html
export SERVER_NAME=avishai.ibsim.co.uk:9000
export PROTOCOL=wss

sudo docker run --name pvw -h avishai.ibsim.co.uk --runtime=nvidia \
    -p 0.0.0.0:${PORT}:443                   \
    -v ${DATA}:/data                        \
    -v ${DEPLOY}:/pvw                       \
    -v ${index_new}:/opt/paraview/share/paraview-5.8/web/visualizer/www/index.html                                  \
    -e "SERVER_NAME=${SERVER_NAME}"         \
    -e "PROTOCOL=${PROTOCOL}"               \
    -d kitware/paraview:pvw-v5.8.0-egl-py3

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

export SERVER_NAME=avishai.ibsim.co.uk:9000 should be the name on how you can reach it.

So maybe SERVER_NAME=avishai.ibsim.co.uk:443 and maybe just SERVER_NAME=avishai.ibsim.co.uk

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

I seem to get the exact same error for both of those options.

Additionally, if I try http://localhost:9000 I get the message below on firefox

The connection was reset

The connection to the server was reset while the page was loading.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

I didn't notice that you changed that line...
-p 0.0.0.0:${PORT}:443

The second arg is where things are running inside docker. That never change it is on port 80 via http... So you are forwarding toward something that does not exist.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

The documentation is correct, you just need to follow it and not change random stuff here and there. ;-)

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

Your config was correct initially

export PORT=9000
export DATA=/home/llion/containers/pvw/data
export DEPLOY=/home/llion/containers/pvw
export index_new=/home/llion/containers/pvw/www/index_pvw.html
export SERVER_NAME=avishai.ibsim.co.uk
export PROTOCOL=wss

sudo docker run --name pvw -h avishai.ibsim.co.uk --runtime=nvidia \
    -p 0.0.0.0:${PORT}:80                   \
    -v ${DATA}:/data                        \
    -v ${DEPLOY}:/pvw                       \
    -v ${index_new}:/opt/paraview/share/paraview-5.8/web/visualizer/www/index.html                                  \
    -e "SERVER_NAME=${SERVER_NAME}"         \
    -e "PROTOCOL=${PROTOCOL}"               \
    -d kitware/paraview:pvw-v5.8.0-egl-py3

The export part is where you should change things (user defined), not the docker command line.

from paraviewweb.

jourdain avatar jourdain commented on August 12, 2024

I'm glad you got everything working and feel free to submit a PR for updating the doc or even create a new one if you feel it would be better.

from paraviewweb.

llionevans avatar llionevans commented on August 12, 2024

As promised, here's an overview of the steps I took to put together a demo site using pvw with docker.

There are much more detailed tutorials available if you follow the links jourdain posted above in this thread, and they give advice for a range of different setups. I'm only describing the specific setup for my application which was to have a webpage with ssl (i.e. over https://) that would auto-load a scene (.pvsm) in pvw depending on the url.

I'm starting from a pretty much fresh copy of ubuntu 18.04 and a modestly powered visualisation PC:

  • i7 CPU
  • 32 GB RAM
  • Nvidia Quadro P5000

At the time of buying, the graphics card was more expensive than the rest of the machine.

A note on naming, we'll be dealing here with both webservers and containers. We'll call the PC that has the webserver the 'server' and the external browser which connects the 'client'. But then we'll also call the PC when outside the container the 'host', and inside the container we'll call 'container'. But there'll also be a webserver running inside the container.

You'll likely be behind a firewall whether you're setting this up at home or work, so you'll need ports opened to let traffic through to your server. These are normally 80 for http and 443 for https. You'll need to find a tutorial online for your specific setup.

Firstly get a webserver set up and working on your PC. I found the tutorial below extremely helpful.
https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-18-04

Next you'll want to setup ssl. Browsers are increasingly restricting access to non ssl sites, so it makes sense to sort this out now. Again, the tutorial below was extremely helpful.
https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04

Next you'll want to install your container platform, docker is the one I'm using here.
https://docs.docker.com/engine/install/ubuntu/

I'd suggest you do this with a GPU if possible. The process for installing the latest nvidia drivers and support for use with docker changes frequently, so any advice you find on forums (and even nvidia's website) is likely to be out of date. But keep looking and you'll find something that works. I tried many different approaches before finally finding something that worked on the link below.
https://marmelab.com/blog/2018/03/21/using-nvidia-gpu-within-docker-container.html

Before continuing it's worth reading these pages to get a better understanding of what's going on.
http://kitware.github.io/paraviewweb/docs/container_overview.html
http://kitware.github.io/paraviewweb/docs/docker_cheatsheet.html

Next you'll need to create the directory structure and some files for your pvw web app.
<APP_ROOT>=../path/to/pvw
<APP_ROOT>/run.sh
<APP_ROOT>/endpoints.txt
<APP_ROOT>/data/<SOME_FILES>
<APP_ROOT>/launcher/log/
<APP_ROOT>/launcher/config.json
<APP_ROOT>/www/index.html

<APP_ROOT>/run.sh is a shell script that you'll use to launch the pvw container.

Other pvw examples use '--gpus all' to give the container access to the GPU, '--runtime=nvidia' is the only way I found worked for me for some reason.

Choose your particular image, replacing 'kitware/paraview:pvw-v5.8.0-egl-py3' using the guidance below.
https://hub.docker.com/r/kitware/paraview

I swapped the -it flag with -d for 'detatched' mode because I don't need to run it interactively. That means if my terminal shuts, the container will keep running. I also added the --name flag, this makes it easier to shutdown the container at a later stage e.g. with 'sudo docker stop pvw && sudo docker rm pvw'. There are other ways to do this, for example use --rm so that the container is removed as soon as it's closed.

export PORT=9000
export DATA=/home/user/containers/pvw/data #Path on host where you'll save your datasets
export DEPLOY=/home/user/containers/pvw #Path on host where you'll save your stuff related to pvw
export index_new=/home/user/containers/pvw/www/index_pvw.html #Path on host to html file that will be used in place of the default visualiser version to auto-load a file using the url.
export SERVER_NAME=mydomain.com
export PROTOCOL=wss

sudo docker run --name pvw --runtime=nvidia \
    -p 0.0.0.0:${PORT}:80                   \
    -v ${DATA}:/data                        \
    -v ${DEPLOY}:/pvw                       \
    -v ${index_new}:/opt/paraview/share/paraview-5.8/web/visualizer/www/index.html                                  \
    -e "SERVER_NAME=${SERVER_NAME}"         \
    -e "PROTOCOL=${PROTOCOL}"               \
    -d kitware/paraview:pvw-v5.8.0-egl-py3

<APP_ROOT>/endpoints.txt

glance /opt/paraview/share/paraview-5.8/web/glance/www
lite /opt/paraview/share/paraview-5.8/web/lite/www
divvy /opt/paraview/share/paraview-5.8/web/divvy/www
visualizer /opt/paraview/share/paraview-5.8/web/visualizer/www
flow /opt/paraview/share/paraview-5.8/web/flow/www
DOCUMENT-ROOT-DIRECTORY /pvw/www/

<APP_ROOT>/launcher/config.json
I think that the main change here is the addition of ' "--load-file", "${dataFile}",' to the visualizer section.

{
  "resources": [ {"port_range": [9010, 9014], "host": "localhost"} ],
  "sessionData": {
    "updir": "/Home"
  },
  "configuration": {
    "log_dir": "/pvw/launcher/log",
    "host": "localhost",
    "endpoint": "paraview",
    "sessionURL": "SESSION_URL_ROOT/proxy?sessionId=${id}&path=ws",
    "timeout": 60,
    "upload_dir": "/data/upload",
    "fields": [],
    "port": 9000,
    "proxy_file": "/opt/launcher/proxy-mapping.txt",
    "sanitize": {
      "version": {
          "type": "regexp",
          "regexp": "^v[0-9]+.[0-9]+.[0-9]+$",
          "default": "v0.0.0"
      },
      "file": {
          "type": "regexp",
          "regexp": "^[-\\\\w./]+$",
          "default": "emptyFile"
      }
    }
  },
  "properties": {
    "dataDir": "/data",
    "webapps_dir": "/opt/paraview/share/paraview-5.8/web",
    "python_exec": "/opt/paraview/bin/pvpython"
  },
  "apps": {
    "visualizer": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--load-file", "${dataFile}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "60"
      ],
      "ready_line" : "Starting factory"
    },
    "visualizer-with-file": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/visualizer/server/pvw-visualizer.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30",
        "--load-file", "${file}"
      ],
      "ready_line" : "Starting factory"
    },
    "paraview-lite": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/lite/server/pvw-lite.py",
        "--port", "${port}",
        "--data", "${dataDir}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "divvy": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/divvy/server/pvw-divvy.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    },
    "flow": {
      "cmd": [
        "${python_exec}",
        EXTRA_PVPYTHON_ARGS
        "${webapps_dir}/flow/server/pvw-flow.py",
        "--port", "${port}",
        "--data", "${dataDir}/${file}",
        "--authKey", "${secret}",
        "--viewport-max-width", "1920",
        "--viewport-max-height", "1080",
        "--timeout", "30"
      ],
      "ready_line" : "Starting factory"
    }
  }
}

<APP_ROOT>/www/index.html
What goes here is anything you want as a home page that will show up under ${SERVER_NAME}. For my purposes this isn't used but I put a simple html file there just in case some script check it exists.

<APP_ROOT>/www/index_pvw.html
Some extra bits to grab the data file name from the url

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
    <link rel="icon" type="image/png" href="favicon-32x32.png">
    <title>ParaViewWeb Visualizer</title>
  </head>
  <body>
    <div class='content'></div>
    <script src="Visualizer.js"></script>
    <script>
      // grab the parameter from the URL
      function getUrlParameter(name) {
        name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
        var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
        var results = regex.exec(location.search);
        return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
      };
      
      Visualizer.connectWithArgsAsConfig({
        application: 'visualizer',
        dataFile: getUrlParameter('data')
      });
      </script>
  </body>
</html>

Then we need to finish setting up the webserver on the host to point at the one in the container and use the ssl certificates we created right at the start. Follow the guide on the link, below are the versions of the files I used along with certbot for the ssl certificate.
http://kitware.github.io/paraviewweb/docs/docker.html

/etc/apache2/sites-available/001-pvw.conf

<VirtualHost *:80>
  ServerName   mydomain.com
  Redirect permanent / https://mydomain.com/
</VirtualHost>

/etc/apache2/sites-available/002-pvw-https.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ProxyPreserveHost On
  ServerName   mydomain.com
  ErrorLog /var/log/apache2/001-pvw_error.log
  CustomLog /var/log/apache2/001-pvw_access.log combined

  SSLEngine on
  #SSLCertificateFile      "/etc/apache2/ssl/${DOMAIN_CERT}.crt"
  #SSLCertificateKeyFile   "/etc/apache2/ssl/${DOMAIN_CERT}.key"
  #SSLCertificateChainFile "/etc/apache2/ssl/DigiCertCA.crt"
  SSLProxyEngine on

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem

  # Handle websocket forwarding
  ProxyPass /proxy ws://localhost:9000/proxy

  # Main server
  ProxyPass        / http://localhost:9000/
  ProxyPassReverse / http://localhost:9000/
</VirtualHost>
</IfModule>

At this stage, the link below should work (if your container is running).
https://mydomain.com/visualizer/?data=filename.pvsm

The last piece of the puzzle for me was to have a page on my main website (running on a completely different webserver) that could read the filename from the url to launch pvw-visualizer and auto-load that data. To do that I used a php page similar to what I've hacked together below in an iframe of another html page.

This is the format of the url it uses:
https://mydomain.com/demo/load_confirm.php/?data=filename.pvsm

load_confirm.php

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta name="robots" content="noindex, nofollow">
    <meta name="googlebot" content="noindex, nofollow">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>www.mydomain.com | ParaViewWeb</title>
  </head>

  <body bgcolor="#333333" text="#808080" link="#CCCCCC" vlink="#CCCCCC">

    <script>
      function getUrlParameter(name) {
        name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
        var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
        var results = regex.exec(location.search);
        return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
      };
    </script>

    <table width="100%" height="100%">
      <tr align="center" valign="top"><td align="center" valign="middle">
      <table width="80%">
        <tr><td>
        <p align="center"><br>
          <font face="Trebuchet MS" size="3" color="#B8B8B9">
<?php
            if (isset($_GET['data'])) {
              $file = substr($_GET['data'], 0, strpos($_GET['data'], "."));
            } else {
              // Fallback behaviour goes here
            }

            $url = "http://mydomain.com/";
            $curl = curl_init($url);
            curl_setopt($curl, CURLOPT_NOBODY, true);
            $result = curl_exec($curl);
            if ($result !== false) {
              $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
              if ($statusCode == 404) {
                echo "Some error message";
              }
              else {
                echo "            <a id='customurl' href='' >\n";
                echo "              <img src='https://mydomain.com/images/" . $file . ".png' style='width:60vw;max-width:60%;border:0;'>";
                echo "<br><br>\n";
                echo "            <font face=\"Trebuchet MS\" size=\"5\" color=\"#B8B8B9\">Click to load, then please be patient as this may take a while.<br></font>\n";
                echo "          </a>\n";

              }
            }
            else {
                echo "Some error message";
            }
?>
          </font>
        </p>
        </td></tr>
      </table>
      </td></tr>
    </table>

    <script>
      document.getElementById('customurl').href ='https://mydomain.com/visualizer/?data='+getUrlParameter('data')
    </script>
  </body>
</html>

With all of that in place, you should only need to launch the container with <APP_ROOT>/./run.sh (assuming you've already made it executable).

from paraviewweb.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.