Package: dapp-runner
Golem dApp Runnerdapp-runneris a utility that allows you to run decentralized applications onGolem.
It uses simple application descriptors expressed inyaml, similar to those used by
tools likedocker-compose.dapp-runnerruns alongside theGolem daemonand usesyapapi, Golem's Python high-level API
to communicate with it. As opposed to using plainyapapithough, deployment of
applications on Golem usingdapp-runnerrequires no code and no experience in Python.GAP-16 / Multi-service application deployment frameworkIn its present form, thedapp-runnerconstitutes an initial reference implementation
of the multi-service application deployment framework described inGAP-16.Following features of the framework are currently supported:Descriptor "Apply" operationSingle-YAML package supportMerging descriptor filesGAOM explicit dependency syntaxGAOM object dependency graph[currently limited to the services' explicit dependency syntax]Relationship withdapp-managerWhile thedapp-runneris perfectly capable of running decentralized apps on its own, we are also
providing a separate tool to facilitate running and managing multiple applications on a single
machine, namely, thedapp-manager.dApp Manager keeps track of the launched apps and allows you to easily query their output streams.
It uses thedapp-runneras its back-end and both require the yagna daemon to communicate with the
rest of the Golem Network.Quick startYagna daemonTo run Golem apps,dapp-runnerrequires a properly configured yagna daemon.
In the future, you'll be able to provision apps using external supervisor machines
which will run a yagna daemon on your behalf.For now, please follow the"Requestor development: a quick primer"tutorial and ensure that youryagnais up and running. Only the first part of this
tutorial is required - you don't need to run the blender example.Most importantly, make sure you have set theYAGNA_APPKEYin your evironment, e.g. with:exportYAGNA_APPKEY=insert-your-32-char-app-key-hereor, on Windows:setYAGNA_APPKEY=insert-your-32-char-app-key-hereand if you don't know what your app-key is, you can always queryyagnawith:yagnaapp-keylistPython environmentFirst, ensure you have Python 3.8 or later:python3--version[ depending on the platform, it may be justpythoninstead ofpython3]If your Python version is older, consider usingpyenv.Once your python interpreter reports a version 3.8 or later, you can set-up your virtual
environment:python3-mvenv~/.envs/dapp-runnersource~/.envs/dapp-runner/bin/activateor, if you're on Windows:python-mvenv--clear%HOMEDRIVE%%HOMEPATH%\.envs\dapp-runner
%HOMEDRIVE%%HOMEPATH%\.envs\dapp-runner\Scripts\activate.batDApp runnerClone the repositorygitclone--recurse-submoduleshttps://github.com/golemfactory/dapp-runner.gitInstall the dependenciescddapp-runner
pipinstall-Upippoetry
poetryinstallRun an example applicationMake sure youryagnadaemon is running,
you have initialized the payment driver withyagna payment init --sender,
and that you have set theYAGNA_APPKEYenvironment variable.Then run:dapp-runnerstart--configconfigs/default.yamldapp-store/apps/webapp.yamlYou should see the application being deployed on the Golem Network and once it's up,
you'll be greeted with:{"http":{"local_proxy_address":"http://localhost:8080"}}You can connect tothis addressusing your local browser,
and you'll see our minimalistic web application example running.Press Ctrl-C in the terminal where you randapp-runnerto initiate its shutdown.Application descriptorAs mentioned above, the decentralized applications that are deployed on Golem by thedapp-runnerare described inyamlfiles, conforming to the schema
described inGAP-16.Example descriptorHere's an example application descriptor (http-proxy.yaml), that provisions a single
instance of a simple, static website served withnginx:payloads:nginx:runtime:"vm"params:image_hash:"16ad039c00f60a48c76d0644c96ccba63b13296d140477c736512127"nodes:http:payload:"nginx"init:-["/docker-entrypoint.sh"]-["/bin/chmod","a+x","/"]-["/bin/sh","-c",'echo"HellofrominsideGolem!">/usr/share/nginx/html/index.html']-["/bin/rm","/var/log/nginx/access.log","/var/log/nginx/error.log"]-["/usr/sbin/nginx"]http_proxy:ports:-"80"# specify just the remote port, allow the local port to be automatically chosenWeb applicationAnd here's an example of a slightly more complex application (webapp.yaml), that uses
two kinds of services and explicitly connects them within a specified network:payloads:db:runtime:"vm"params:image_hash:"85021afecf51687ecae8bdc21e10f3b11b82d2e3b169ba44e177340c"http:runtime:"vm"params:image_hash:"c37c1364f637c199fe710ca62241ff486db92c875b786814c6030aa1"nodes:db:payload:"db"init:-["/bin/run_rqlite.sh"]network:"default"ip:-"192.168.0.2"http:payload:"http"init:-["/bin/bash","-c","cd/webapp&&pythonapp.py--db-address192.168.0.2--db-port4001initdb"]-["/bin/bash","-c","cd/webapp&&pythonapp.py--db-address192.168.0.2--db-port4001run>/webapp/out2>/webapp/err&"]http_proxy:ports:-"5000"# specify just the remote port, allow the local port to be automatically chosennetwork:"default"ip:-"192.168.0.3"depends_on:-"db"networks:default:ip:"192.168.0.0/24"Implicit propertiesThenetworksdefinition and thevpncapabilityAs can be seen in thehttp_proxyexample above, thenetworksdefinition can be omitted.Adding ahttp_proxyelement to anodesentry, causes thedapp-runnerto implicitly
add thenetworksobject with a default of a single IPv4 network. Additionally, it adds
thevpncapability to the requested parameters of the deployedvmruntime.Note:Thenetworksandcapabilitiesobjects will only be implicitly added if
they are not already present in the descriptor. If the application specifies any of
those objects, it is assumed that the application authors know what they're doing.Themanifest-supportcapabilitySimilarly, specifying the payload asvm/manifestimplicitly addsmanifest-supportto
the requestedcapabilitiesfor the runtime.Note:Again, this is only done if thepayload.paramsdoesn't already contain thecapabilitiesobject.UsageCurrently, thedapp-runnerimplements a single CLI command,start:Usage:dapp-runnerstart[OPTIONS]DESCRIPTORS...which allows the following options:-d,--dataPATHPathtothedatafile.-l,--logPATHPathtothelogfile.-s,--statePATHPathtothestatefile.--stdoutPATHRedirectstdouttothespecifiedfile.--stderrPATHRedirectstderrtothespecifiedfile.-c,--configPATHPathtothefilecontainingyagna-specificconfig.[required]--silent--helpShowthismessageandexit.The--data,--log,--state,--stdout, and--stderrarguments specify the
locations of files to which the respective streams are written. If unspecified, all
streams are written to the console which thedapp-runneris invoked from.StreamsDataThedatastream consists of JSON-formatted output of specific components that are run
as part of the services. Currently it carries the command execution events from
exescript commands, e.g.:{"db":{"0":[{"command":{"run":{"entry_point":"/bin/run_rqlite.sh","args":[],"capture":{"stdout":{"stream":{}},"stderr":{"stream":{}}}}},"success":true,"stdout":null,"stderr":null}]}}and the parameters of any started instances of Local HTTP proxies:{"http":{"local_proxy_address":"http://localhost:8080"}}The keys in the outermost dictionaries refer to names of service cluster as specified in
theyamldescriptor file. For exescript commands, the secondary layer's keys refer to
indices of instances within the specific cluster.StateThestatestream consists of JSON-formatted descriptions of the state of the dapp
after each state change, e.g.:{"db":{"0":"running"},"http":{"0":"starting"}}Here, again, the keys in the topmost dictionary refer to the names of service clusters
defined in theyamldescriptor file and the secondary layer's keys refer to indices
of specific instances.LogThelogstream is a text stream of log messages emitted fromdapp-runner.Stdout / StderrFinally,stdoutandstderrrefer to the standard output streams of thedapp-runnerscript.ConfigThis is a mandatory argument, specifying a path to ayamlfile containing a
description of a configuration to connect to youryagnadaemon, e.g.:yagna:app_key:"$YAGNA_APPKEY"subnet_tag:"devnet-beta"payment:budget:1.0# GLMdriver:"erc20"network:"rinkeby"DescriptorsOne or more application descriptors, as specified in the"Application descriptor"section above.If more than oneyamldescriptor file is given, all of theyamlfiles are merged
into one descriptor before being processed further by thedapp-runner. The files
are merged using a deep-merge strategy with contents of each subsequentyamlfile
overriding the colliding keys of the former ones.