Skip to content

Commit

Permalink
chore(docker): Update scripts to use v2 www tools
Browse files Browse the repository at this point in the history
  • Loading branch information
jourdain committed May 17, 2022
1 parent 5f55d6a commit 361c976
Show file tree
Hide file tree
Showing 19 changed files with 489 additions and 0 deletions.
53 changes: 53 additions & 0 deletions docker/Dockerfile.common
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
ARG BASE_IMAGE=ubuntu:20.04
FROM ${BASE_IMAGE}

# Necessary to install tzdata. It will default to UTC.
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
apt-get install -y \
wget \
apache2 \
apache2-dev \
libapr1-dev \
apache2-utils \
gosu && \
rm -rf /var/lib/apt/lists/*

# Set up needed permissions and users
RUN groupadd trame-user -g 1000 && \
groupadd proxy-mapping -g 1001 && \
useradd -u 1000 -g trame-user -G proxy-mapping -s /sbin/nologin trame-user && \
usermod -a -G proxy-mapping www-data && \
mkdir -p /opt/trame && \
chown -R trame-user:trame-user /opt/trame && \
mkdir -p /home/trame-user && \
chown -R trame-user:trame-user /home/trame-user && \
touch /opt/trame/proxy-mapping.txt && \
chown trame-user:proxy-mapping /opt/trame/proxy-mapping.txt && \
chmod 660 /opt/trame/proxy-mapping.txt && \
mkdir -p /deploy && \
chown -R trame-user:trame-user /deploy

# Copy the apache configuration file into place
COPY config/apache/001-trame.conf /etc/apache2/sites-available/001-trame.conf
COPY config/default-launcher.json /opt/trame/default-launcher.json

# Configure the apache web server
RUN a2enmod vhost_alias && \
a2enmod proxy && \
a2enmod proxy_http && \
a2enmod proxy_wstunnel && \
a2enmod rewrite && \
a2enmod headers && \
a2dissite 000-default.conf && \
a2ensite 001-trame && \
a2dismod autoindex -f

# Copy the scripts into place
COPY scripts/* /opt/trame/

# Open port 80 to the world outside the container
EXPOSE 80

ENTRYPOINT ["/opt/trame/entrypoint.sh"]
26 changes: 26 additions & 0 deletions docker/Dockerfile.conda
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
ARG BASE_IMAGE=trame-common
FROM ${BASE_IMAGE}

# Install miniconda
ENV CONDA_DIR /opt/conda
RUN if [ $(uname -m) = "x86_64" ]; then arch="x86_64"; else arch="aarch64"; fi && \
wget -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-$arch.sh -O /miniconda.sh && \
/bin/bash /miniconda.sh -b -p $CONDA_DIR && \
rm /miniconda.sh && \
chown -R trame-user:trame-user $CONDA_DIR

# Put conda in the path
ENV PATH=$CONDA_DIR/bin:$PATH

# Install pyyaml
RUN gosu trame-user conda install -y --freeze-installed -c conda-forge \
pyyaml && \
conda clean -afy

# Copy the scripts into place
COPY scripts/conda/* /opt/trame/

# Set venv paths
ENV TRAME_VENV=/deploy/server/venv
ENV PV_VENV=$TRAME_VENV
ENV VTK_VENV=$TRAME_VENV
36 changes: 36 additions & 0 deletions docker/Dockerfile.pip
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ARG BASE_IMAGE=trame-common
FROM ${BASE_IMAGE}

RUN apt-get update && \
apt-get install -y \
python3.9 \
# python3.9-distutils is required to install pip
# it unfortunately has to install python3.8-minimal as well...
python3.9-distutils \
# python-is-python3 creates a symlink for python to python3
python-is-python3 \
# For creating virtual environments
python3.9-venv && \
rm -rf /var/lib/apt/lists/*

# Set python3 to python3.9 (otherwise, it will be python3.8)
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1

# Never use a cache directory for pip, both here in this Dockerfile
# and when we run the container.
ENV PIP_NO_CACHE_DIR=1

# Install and upgrade pip
RUN wget -q -O- https://bootstrap.pypa.io/get-pip.py | python3.9 && \
pip install -U pip

# Install setup dependencies
RUN pip install PyYAML

# Copy the pip scripts into place
COPY scripts/pip/* /opt/trame/

# Set venv paths
ENV TRAME_VENV=/deploy/server/venv
ENV PV_VENV=$TRAME_VENV
ENV VTK_VENV=$TRAME_VENV
25 changes: 25 additions & 0 deletions docker/config/apache/001-trame.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<VirtualHost *:80>
DocumentRoot /deploy/server/www
ErrorLog /deploy/server/logs/apache/error.log
CustomLog /deploy/server/logs/apache/access.log combined

<Directory /deploy/server/www>
Options Indexes FollowSymLinks
Order allow,deny
Allow from all
AllowOverride None
Require all granted
</Directory>

Header set Access-Control-Allow-Origin "*"

# Handle launcher forwarding
ProxyPass /launcher http://localhost:9000/paraview
ProxyPass /paraview http://localhost:9000/paraview

# Handle WebSocket forwarding
RewriteEngine On
RewriteMap session-to-port txt:/opt/trame/proxy-mapping.txt
RewriteCond %{QUERY_STRING} ^sessionId=(.*)&path=(.*)$ [NC]
RewriteRule ^/proxy.*$ ws://${session-to-port:%1}/%2 [P]
</VirtualHost>
24 changes: 24 additions & 0 deletions docker/config/default-launcher.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"configuration": {
"host": "0.0.0.0",
"port": 9000,
"endpoint": "paraview",
"log_dir": "/deploy/server/logs/launcher",
"proxy_file": "/opt/trame/proxy-mapping.txt",
"sessionURL": "ws://USE_HOST/proxy?sessionId=${id}&path=ws",
"timeout": 25,
"sanitize": {},
"fields": []
},
"resources": [
{
"host": "0.0.0.0",
"port_range": [
9001,
9500
]
}
],
"properties": {},
"apps": {}
}
3 changes: 3 additions & 0 deletions docker/scripts/conda/activate_venv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ensure we are in the base conda environment first, or it won't work.
. $CONDA_DIR/bin/activate
conda activate $TRAME_VENV
6 changes: 6 additions & 0 deletions docker/scripts/conda/create_venv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Ensure we are in the base conda environment first, or it won't work.
. $CONDA_DIR/bin/activate

conda create -y conda python=3.9 --prefix $TRAME_VENV
conda activate $TRAME_VENV
conda clean -afy
5 changes: 5 additions & 0 deletions docker/scripts/conda/install_requirements.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Install requirements (if it exists)
if [ -f /deploy/setup/requirements.txt ]
then
conda install -y --file /deploy/setup/requirements.txt
fi
19 changes: 19 additions & 0 deletions docker/scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

if [ ! -d /deploy/server ] && [ ! -d /deploy/setup ]
then
echo "ERROR: The deploy directory must be mounted into the container at /deploy"
exit 1
fi

# Fix any uid/gid mismatch
/opt/trame/fix_uid_gid.sh

# Ensure the needed directories exist
gosu trame-user /opt/trame/make_directories.sh

# Restart apache
service apache2 restart

# Start the server
gosu trame-user /opt/trame/server.sh
32 changes: 32 additions & 0 deletions docker/scripts/fix_uid_gid.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

check_dir=/deploy/server
if [ ! -d $check_dir ]
then
check_dir=/deploy/setup
fi

deploy_uid=$(stat -c '%u' $check_dir)
deploy_gid=$(stat -c '%g' $check_dir)

trame_user_uid=$(id -u trame-user)
trame_user_gid=$(id -g trame-user)

run_chown=false
if [[ "$deploy_uid" != "$trame_user_uid" ]]; then
usermod --uid $deploy_uid trame-user
run_chown=true
fi

if [[ "$deploy_gid" != "$trame_user_gid" ]]; then
groupmod --gid $deploy_gid trame-user
run_chown=true
fi

if [[ "$run_chown" == false ]]; then
exit 0
fi

# Run chown on all trame-user directories/files
chown -R trame-user:trame-user /opt/trame
chown trame-user:proxy-mapping /opt/trame/proxy-mapping.txt
78 changes: 78 additions & 0 deletions docker/scripts/generate_launcher_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env python3

import json
from pathlib import Path


def run(input_path, apps_path, out_path):
default_command_flags = [
'--host', '${host}',
'--port', '${port}',
'--authKey', '${secret}',
'--server',
]
default_ready_line = 'Starting factory'

with open(input_path, 'r') as rf:
input_dict = json.load(rf)

if not Path(apps_path).exists():
raise Exception(f'{apps_path} does not exist')

with open(apps_path, 'r') as rf:
apps_dict = json.load(rf)

if not apps_dict:
raise Exception(f'{apps_path} is empty')

for app_name, config in apps_dict.items():
if 'app' not in config:
msg = (
f'In {apps_path}, every app must contain an "app" key, but '
f'"{app_name}" does not'
)
raise Exception(msg)

if 'cmd' in config and 'args' in config:
msg = (
f'In {apps_path}, "args" and "cmd" cannot both be specified. '
'"args" is for appending extra args to the default "cmd", but '
'"cmd" is for overriding the command entirely. Error occurred '
f'in "{app_name}".'
)
raise Exception(msg)

app = config['app']
default_cmd = [app] + default_command_flags
cmd = config.get('cmd', default_cmd)
cmd += config.get('args', [])
ready_line = config.get('ready_line', default_ready_line)

input_dict.setdefault('apps', {})
input_dict['apps'][app_name] = {
'cmd': cmd,
'ready_line': ready_line,
}

if 'trame' not in input_dict['apps']:
# Make a copy of the first app and put it in PyWebVue, so that
# the default localhost:9000 web page will use that app.
first_key = next(iter(input_dict['apps']))
input_dict['apps']['trame'] = input_dict['apps'][first_key]

with open(out_path, 'w') as wf:
json.dump(input_dict, wf, indent=2)


if __name__ == '__main__':
default_input_path = '/opt/trame/default-launcher.json'
override_input_path = '/deploy/setup/launcher.json'
apps_path = '/opt/trame/apps.json'
out_path = '/deploy/server/launcher.json'

if Path(override_input_path).exists():
input_path = override_input_path
else:
input_path = default_input_path

run(input_path, apps_path, out_path)
26 changes: 26 additions & 0 deletions docker/scripts/generate_www.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python

import json
import subprocess


def run(apps_path, out_path, *modules):
# generate www content
cmd = ["python", "-m", "trame.tools.www", "--output", f'{out_path}', *modules]
subprocess.run(cmd)

with open(apps_path, 'r') as rf:
apps_dict = json.load(rf)

# FIXME need to generate index.html => {app_name}.html
# for app_name, config in apps_dict.items():
# name = config['app']
# => cp out_path/index.html out_path/{name}.html
# => replace data-app-name="trame" => data-app-name="{name}"


if __name__ == '__main__':
apps_path = '/opt/trame/apps.json'
out_path = '/deploy/server/www'
modules = ["client", "trame", "vtk", "vuetify", "plotly", "router", "vega", "markdown"]
run(apps_path, out_path, *modules)
7 changes: 7 additions & 0 deletions docker/scripts/make_directories.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

# Make directories we need before running the rest of the scripts
mkdir -p \
/deploy/server/www \
/deploy/server/logs/apache \
/deploy/server/logs/launcher
1 change: 1 addition & 0 deletions docker/scripts/pip/activate_venv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
. $TRAME_VENV/bin/activate
5 changes: 5 additions & 0 deletions docker/scripts/pip/create_venv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
python -m venv $TRAME_VENV
. $TRAME_VENV/bin/activate

# Update pip
pip install -U pip
5 changes: 5 additions & 0 deletions docker/scripts/pip/install_requirements.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Install requirements (if it exists)
if [ -f /deploy/setup/requirements.txt ]
then
pip install -r /deploy/setup/requirements.txt
fi
Loading

0 comments on commit 361c976

Please sign in to comment.