Skip to content

Commit

Permalink
Output proxy url to stderr via logger instead of stdout via print whe…
Browse files Browse the repository at this point in the history
…n isRemote is True (streamlit#80)

* Output proxy url to stderr via logger instead of stdout via print when isRemote is True

If proxy.isRemote is true:
* output the external URL via python logging instead of via print.
  docker doesnt by default output print statements which is why this is
  needed.  I plan on running the remote proxy via docker.

* Dockerize proxy (streamlit#81)

* Dockerize streamlit proxy.

* Add more docker instructions.

* Add remote ip to docker conf and ignore some python files for docker image.

* Proxy fails to find script because of file system watcher, so disable it in docker.

* Add comment on how to start machines in AWS and GCE

* Add more documentation

* Change some proxy behavior when isRemote is true.

If proxy.isRemote is true:
* output the external URL via python logging instead of via print.
  docker doesnt by default output print statements which is why this is
  needed.  I plan on running the remote proxy via docker.
* dont stop the proxy.

* Add more comments.

* Add more details in README.md on whats being dockerized.

Also rollback keeping the proxy running forever as streamlit#87 will do that.
  • Loading branch information
aaj-st authored Nov 15, 2018
1 parent 779853c commit 506680e
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 2 deletions.
78 changes: 78 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Docker container for proxy.

This is for running the Proxy in Docker, not running scripts in docker.
ie client runs on your local machine but the proxy runs in docker. Your
browser connects to the proxy running in docker.

## Install Docker

### OSX
```
brew cask install docker
```

Then start docker and you should see the whale up in the top right.

OSX installs docker-machine and docker-compose

### Linux
[https://docs.docker.com/install/linux/docker-ce/ubuntu/](https://docs.docker.com/install/linux/docker-ce/ubuntu/)
[https://docs.docker.com/machine/install-machine/](https://docs.docker.com/machine/install-machine/)

Then `pip install docker-compose`

### Both
```
docker run hello-world
```

## Create a VM that has docker running on it.
This is basically needed so that proxy is running on 192.168.99.100
instead of localhost.

```
docker-machine create --driver=virtualbox vm0
```

*This is important cause you can easily spin up machines in AWS or GCE*
* [https://docs.docker.com/machine/drivers/aws/](https://docs.docker.com/machine/drivers/aws/)
* [https://docs.docker.com/machine/drivers/gce/](https://docs.docker.com/machine/drivers/gce/)

## Setup environment to point to docker running in vm
```
eval $(docker-machine env vm0)
```

## Build image
If you dont do the eval command above, this will build the image in the
docker-engine running on localhost instead of the vm.

```
cd docker/streamlit
docker-compose build
```


## Run image
```
cd docker/streamlit
docker-compose up proxy
```

Or run this to have it running in the background as a daemon.
```
docker-compose up -d proxy
```

Then this for logs.
```
docker-compose logs -f proxy
```

![images/docker.png](images/docker.png "images/docker.png")

## Misc
* Restart Virtualbox DHCP Server on OSX
```
sudo /Library/Application\ Support/VirtualBox/LaunchDaemons/VirtualBoxStartup.sh restart
```
Binary file added docker/images/docker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions docker/streamlit/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: '3.6'

services:
frontend:
image: st/frontend
build:
context: ../..
dockerfile: frontend/Dockerfile
ports:
- 3000:5000

proxy:
image: st/proxy
build:
context: ../..
dockerfile: lib/Dockerfile
environment:
- PORT=8501
- IP=192.168.99.100
ports:
- 8501:8501
3 changes: 3 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build
node_modules
.dockerignore
39 changes: 39 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#######################################################################
# Frontend Build
#######################################################################
# The frontend build image has a lot of stuff thats not required for
# serving static content but is required to build the static content.
# st/frontend latest 033f590e481a 2 minutes ago 217MB <-- frontend
# <none> <none> 1255147956f8 3 minutes ago 508MB <-- build

FROM node:carbon-slim as build

# frontend/.dockerignore is what ignores node_modules
COPY frontend/. /frontend/
COPY protobuf/. /protobuf/

WORKDIR /frontend

# Install packages
RUN npm install

# Create protobuf.js
RUN ./node_modules/protobufjs/bin/pbjs ../protobuf/*.proto -t static-module > ./src/protobuf.js

# Build static content which puts it into frontend/build
RUN npm run build

#######################################################################
# Frontend Container
#######################################################################
FROM node:carbon-slim

# Install npm package serve to start a web server to literally serve the
# built static contents
RUN npm install -g serve

# Copy the built static content from the temporary frontend build image
COPY --from=build /frontend/build/. /frontend

# By default it listens on port 5000
ENTRYPOINT serve -s /frontend
8 changes: 8 additions & 0 deletions lib/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
streamlit/protobuf/*_pb2.py
streamlit/static
Dockerfile
entrypoint.sh
tests
.dockerignore
**/*.pyc
**/.DS_Store
51 changes: 51 additions & 0 deletions lib/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#######################################################################
# Frontend image
#######################################################################
# We need to "mount" the frontend image so we can extract the built
# static contents and include in the proxy.
FROM st/frontend as frontend

#######################################################################
# Proxy build
#######################################################################
FROM python:2-slim-stretch as build

RUN apt-get update && apt-get install -y --no-install-recommends \
apt-utils apt-transport-https curl ca-certificates \
build-essential locales protobuf-compiler

# See lib/.dockerignore because only some of the directory is copied.
COPY lib/. /st/
COPY protobuf/. /protobuf/

# Create protobufs.
RUN protoc --proto_path=/protobuf /protobuf/*.proto --python_out=/st/streamlit/protobuf

# Copy the frontend static content from the frontend image.
COPY --from=frontend /frontend/. /st/streamlit/static/

WORKDIR /st

# Build the wheel file.
RUN python setup.py bdist_wheel --universal


#######################################################################
# Proxy container
#######################################################################
FROM python:2-slim-stretch

# build-essential shouldnt be needed but for some reason one of the pip
# dependencies compiles something so thats why its there. This image
# size is not ideal.
RUN apt-get update && apt-get install -y --no-install-recommends \
apt-utils apt-transport-https curl ca-certificates \
build-essential locales

COPY --from=build /st/dist/streamlit*.whl /st/
COPY lib/entrypoint.sh /

WORKDIR /st
RUN pip install *.whl

ENTRYPOINT /entrypoint.sh
30 changes: 30 additions & 0 deletions lib/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash -e

PORT=${PORT:-8501}
IP=${IP:-null}

mkdir -p ~/.streamlit

# Create a streamlit config
cat >~/.streamlit/config.yaml <<EOF
client:
# Whether Streamlit should remotely record usage stats
remotelyTrackUsage: false
# Enable development configuration. Without these two lines, docker
# logs won't output anything.
development: true
log_level: debug
proxy:
# IP address of the machine where the Streamlit Proxy is running.
externalIP: ${IP}
# Is the proxy running remotely.
isRemote: true
watchFileSystem: false
port: ${PORT}
useNode: false
EOF

python -m streamlit.proxy
7 changes: 5 additions & 2 deletions lib/streamlit/proxy/Proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,16 @@ def _print_remote_url(port, quoted_name):
external_url = _get_report_url(external_ip, port, quoted_name)
lan_url = _get_report_url(lan_ip, port, quoted_name)

print(textwrap.dedent(f'''
if config.get_option('proxy.isRemote'):
LOGGER.debug(f'External URL: {external_url}, Internal URL: {lan_url}')
else:
print(textwrap.dedent(f'''
=============================================================
Open one of the URLs below in your browser within {int(timeout_secs)} seconds
External URL: {external_url}
Internal URL: {lan_url}
=============================================================
'''))
'''))


def _launch_web_client(name):
Expand Down

0 comments on commit 506680e

Please sign in to comment.