libcurl4-openssl-dev apache2-threaded-dev \
libapr1-dev libaprutil1-dev
-# Install apache configuration...
+RUN cd /usr/src/arvados/services/api && \
+ /usr/local/rvm/bin/rvm-exec default bundle exec passenger-install-apache2-module --auto --languages ruby,python
+
+RUN cd /usr/src/arvados/services/api && \
+ /usr/local/rvm/bin/rvm-exec default bundle exec passenger-install-apache2-module --snippet > /etc/apache2/conf.d/passenger
+
+ADD apache2_foreground.sh /etc/apache2/foreground.sh
ADD apache2_vhost /etc/apache2/sites-available/arv-web
RUN \
+ mkdir /var/run/apache2 && \
a2dissite default && \
a2ensite arv-web && \
a2enmod rewrite
-ADD apache2_foreground.sh /etc/apache2/foreground.sh
+EXPOSE 80
CMD ["/etc/apache2/foreground.sh"]
\ No newline at end of file
--- /dev/null
+Sample Arvados web service.
+
+usage: arv-web-example.py [-h] --project PROJECT [--port PORT] --image IMAGE
+
+optional arguments:
+ -h, --help show this help message and exit
+ --project PROJECT Project to watch
+ --port PORT Local bind port
+ --image IMAGE Docker image to run
+
+
+This queries an Arvados project and FUSE mounts the most recently modified
+collection into a temporary directory. It then runs the supplied Docker image
+with the collection bind mounted to /mnt inside the container.
+
+When a new collection is added to the project, or an existing project is
+updated, it will detect the change, it will stop the running Docker container,
+unmount the old collection, mount the new most recently modified collection,
+and restart the Docker container with the new mount.
+
+The supplied Dockerfile builds a Docker image that runs Apache with /mnt as the
+DocumentRoot. This allows you to browse the mounted collection with Apache's
+default index page.
+
+
+Suggestions for extension:
+
+Configure the container to use mod_passenger (for an example,
+arvados/docker/passenger/Dockerfile) and include both your web app and your
+data in your collection.
\ No newline at end of file
# Index file and Document Root (where the public files are located)
DirectoryIndex index.html
- DocumentRoot /mnt
+ DocumentRoot /mnt/public
+ RackBaseURI /
LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
- <Directory /mnt>
- Options Indexes FollowSymLinks MultiViews IncludesNoExec
+ <Directory /mnt/public>
+ Options Indexes IncludesNoExec ExecCGI
+ AddHandler cgi-script .cgi
+ Options -MultiViews
AllowOverride None
Order allow,deny
- allow from all
+ Allow from all
</Directory>
</VirtualHost>
while running:
try:
eq = evqueue.get(True, 1)
- logging.info("%s %s, restarting web service" % (eq[1], eq[2]))
- if eq[1] == 'add' or eq[1] == 'update':
- collection = eq[2]
- running = False
- if eq[1] == 'remove':
- collection = api.collections().list(filters=[["owner_uuid", "=", project]],
+ logging.info("%s %s" % (eq[1], eq[2]))
+ newcollection = collection
+ if eq[1] in ('add', 'update', 'create'):
+ newcollection = eq[2]
+ elif eq[1] == 'remove':
+ newcollection = api.collections().list(filters=[["owner_uuid", "=", project]],
limit=1,
order='modified_at desc').execute()['items'][0]['uuid']
+ if newcollection != collection:
+ logging.info("restarting web service")
+ collection = newcollection
running = False
-
except Queue.Empty:
pass
- except KeyboardInterrupt:
+ except (KeyboardInterrupt):
logging.info("Got keyboard interrupt")
ws.close()
loop = False
+ except Exception as e:
+ logging.exception(str(e))
+ ws.close()
+ loop = False
finally:
if cid:
logging.info("Stopping docker container")
--- /dev/null
+#!/usr/bin/perl
+
+print "Content-type: text/html\n\n";
+print "Hello world from perl!";
--- /dev/null
+app = proc do |env|
+ [200, { "Content-Type" => "text/html" }, ["hello <b>world</b> from ruby"]]
+end
+run app
--- /dev/null
+<html>
+ <head><title>arv-web sample</title></head>
+ <body>
+ <p>Hello world static page</p>
+ </body>
+</html>
--- /dev/null
+def application(environ, start_response):
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return [b"hello world from python!\n"]