optional: --server.port 8501 (in case you want to run it on a different port, like one opened in the container)
Env:
Running Jupyterhub with Docker, each user gets their own container with one of several pre-built environments they can choose from a drop-down list.
Issues I ran into:
Finding documentation about command-line arguments was difficult. I didnāt have access to edit ~/.streamlit/config.toml because of restricted access, hence the command-line.
Installing serverproxy in a container that didnāt already have it pre-installed doesnāt seem to work. No explanation for why. Using an image that came with serverproxy was fine. Intuition is that it shouldnāt matter, experiments have shown otherwise.
CORS must be disabled. Stuck āloadingā if not. I take care of all SSL at the nginx-level, and proxy-pass to the jupyterhub instance, so the safety wasnāt a concern for me (hub is running on http). Let me know if Iām wrong (Iām not a web-dev).
Had to visit user/michael/proxy/5000/ (and the trailing slash does matter)
Technically, the user-image that worked for me used the following install instructions, not pip install:
git clone --depth 1 https://github.com/jupyterhub/jupyter-server-proxy && \
cd jupyter-server-proxy/jupyterlab-server-proxy && \
npm install && npm run build && jupyter labextension link . && \
npm run build && jupyter lab build
I ran that in a container that didnāt have the proxy installed, didnāt fix lack of access.
At PyDataLA right now, so I donāt quite have the time to dig in and build a minimally-working Dockerfile, but thatās definitely a next step for debugging.
A bloated image (with R/Julia/Octave/Python) that does allow the proxy-pass can be found on docker hub at mathematicalmichael/math-user:latest
Got a minimal working example! Reproduction steps:
Dockerfile:
FROM jupyter/minimal-notebook:latest
RUN pip install streamlit jupyter-server-proxy jupyter-rsession-proxy
ENV JUPYTER_ENABLE_LAB=yes
So, apparently all that was missing was the jupyter-rsession-proxy, which I happened to be using to get RStudio working in JupyterHub.
Anyway, make that Dockerfile and then run:
docker built -t streamlit-image .
docker run --rm -p 8888:8888 streamlit-image jupyter lab --NotebookApp.token=''
Visit port 8888 on localhost (or the IP of your remote machine, as in my case).
Open Terminal and run streamlit hello --browser.serverAddress 0.0.0.0 --server.enableCORS False
In your address bar, swap /lab with /proxy/8501/ (trailing slash important!)
Enjoy the wonderful goodness that is the streamlit demo
This should make app-demos fairly easy. Swap jupyter lab ... for the streamlit command, map 8888:8501 instead and use nginx to proxy-pass to 127.0.0.1:8888/
In practiceā¦ That hasnāt worked for me. I suspect itās some problem in my nginx config (headers?). Iām able to hit the app but see āPlease waitā. Web console says something about an unspported state transition.
Would love help with thatā¦
With my above plan, if I visit the IP of my remote machine at port 8888 instead of the web address that I was attempting to proxy-pass, the app runs (on http)! Thatās promising. Basically says that we have a docker-run command now:
docker run --rm -p 8501:8501 streamlit-image streamlit hello --browser.serverAddress 0.0.0.0 (CORS seems to only be an issue for the proxy-via-jupyterlab approach).
also not really having a whole lot of success with this in an already-running JLab. It seems like if it exists upon startup, this solution works. But now Iām on someone elseās jupyter deployment so I donāt have the ability to do anything except pip install from JLabās terminal. Hitting 404 errors.
quick update on using with docker-machine (I didnāt install the desktop edition on my new mac, figuring out the kinks/differences as I go, finally got around to testing streamlit).
since docker wonāt bind localhost to the docker-machine IP, youāll have to disable CORS for local development.
Iāve been working on running Streamlit in JupyterHub but without using Docker. I also have experience doing this with Docker too, so if I get a chance Iāll go through your notes and see if I can write something up based on our ideas combined.
Thanks for this example @mathematicalmichael! I took this and wrapped it a bit further by adding streamlit to the jupyter config so that you just need to go to /streamlit to access the server.
The key piece is the jupyter_notebook_config.py file that defines streamlit as a server extension so if you want to run your own piece of code you would need to amend that file (or add a second spec).
so from within jupyter terminal this would be: streamlit run app.py --browser.serverAddress 0.0.0.0 --server.enableCORS False --server.enableXsrfProtection False
I have extended my work on JupyterHub + Streamlit and released a full JupyterHub extension that easily allows deployment of any dashboarding framework within JupyterHub (e.g. Streamlit, Voila, Plotly Dash etc).
This takes care of configuration for you - just specify the Streamlit file (or a Git repo URL) in a page under the new āDashboardā menu and it will automatically start a new server running only Streamlit. You can allow access to any authenticated JupyterHub user, or specify individual users who should have access.
It also means users can keep using their regular Jupyter servers just as before, and easily spin up a new ādashboardā for any new Streamlit apps. Really, itās just leveraging JupyterHubās security and deployment model.
Iād be really pleased if you get to try it out and let me know how it goes! The extension is ContainDS Dashboards.
@danlester loving the ContainsDS extension - hitting an issue where I get a Error: Request failed with status code 403 when trying to upload a file to a Streamlit app running in a dashboard - thinking it is XRSF related but not sure what to do from there. Any thoughts here? Thanks!
The problem is that Streamlit only sets the XRSF cookie once, and that is during the āwebsocket handshakeā - which is perhaps not enough really, and is missed through ContainDSā proxy. Maybe Streamlit would be better off with a fix to make this more robust, but hopefully I can work around it in ContainDS Dashboards anyway. Iāll take a look. For now, turning off XSRF is fine for a lot of JupyterHubs which are behind firewalls etc.
Iāll update here when a fix is available, but any other problems or feedback about the extension please just get in touch wherever makes the most sense!
@chrishumphries yes you would just add the snippet I included earlier at the end of the /opt/tljh/config/jupyterhub_config.d/cdsdashboards_config.py file that you would have created during ContainDS Dashboards setup for TLJH.
@chrishumphries Definitely - with ContainDS Dashboards you can just use your own conda environment for the usersā environment and install whatever you want.
If youāre using some kind of Docker system in your JupyterHub (Kubernetes or just DockerSpawner) then you might be using my pre-built Docker images. In that case, it will pick up the latest Streamlit when the image was builtā¦ the latest 0.3.5 tag was a month ago so I think it was version 0.67 of Streamlit. Iāve just added a commit to force a rebuilt, so that should pick up the latest Streamlit if you find the very latest tag in Docker hub in a short while.
In any case, of course you can build your own Docker images to contain whichever packages you need.
I hope this helps. Please let me know if you have any questions at all!
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking āAccept allā, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.