<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/django-and-r-on-heroku/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://pirategrunt.com/blog/r/2017/01/03/RonHeroku/"> PirateGrunt</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I’ve been playing with <a target="_blank" rel="nofollow" href="https://www.djangoproject.com/">Django</a> for a while now and I’m loving it. Don’t get me wrong, I still love Shiny, but Django is pretty tough to beat for data-heavy projects and managing user sessions. For deployment, I’ve been using Heroku and am very happy so far. Application updates are as simple as a Git push from the command line and it’s hard to get much easier than that.</p>
<p>Until today, the one thing I hadn’t tried to sort out is how to leverage R with the application. R isn’t one of Heroku’s officially support buildpacks (that’d be <a target="_blank" rel="nofollow" href="https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks">these</a>), but it is possible to get an instance up and running.</p>
<p>First, though, I’ll build a very basic Django application. This will do nothing more than act as a container for displaying the results of some R code. To start, I’ll create and populate a virtual environment for the project.</p>
<div>
<pre><code>mkvirtualenv r_on_heroku
pip install django
pip install gunicorn
pip install whitenoise
pip freeze > requirements.txt
</code></pre>
</div>
<p>Note that although requirements.txt isn’t necessary for local development, Heroku needs it to know which Python modules to install.</p>
<p>That done, I create a single python module which will serve a static web page at the site root. This is based on an example found in the book <a target="_blank" rel="nofollow" href="http://shop.oreilly.com/product/0636920032502.do">Lightweight Django</a>, which is excellent and well worth reading. For Heroku deployment, I’ll need two additional things. First, I need a Procfile. This is simply a one-line file which tells gunicorn to boot up and execute. What it’s executing is the second thing that I need, which is to create an application object. (I’ll also be using WhiteNoise to serve static content. More on that in a moment.)</p>
<p>So, my Procfile looks like this:</p>
<div>
<pre><code>web: gunicorn r_min.py
</code></pre>
</div>
<p>And I’ve added these lines at the bottom of my minimal Django example:</p>
<div>
<pre><code>from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)
</code></pre>
</div>
<p>My one and only view has this very basic code:</p>
<div>
<pre><code>def index(request):
    return HttpResponse('This is my minimal R example.')
</code></pre>
</div>
<p>We can confirm that everything is running as expected by issuing either of these two commands:</p>
<div>
<pre><code>python r_min.py runserver
heroku local web
</code></pre>
</div>
<p>Note that for the second command to work, I need to have Heroku’s command line interface installed.</p>
<p>Pushing the app up to Heroku is fairly easy. If you’ve never done this, the <a target="_blank" rel="nofollow" href="https://devcenter.heroku.com/articles/getting-started-with-python">Heroku docs</a> will help you get an app up and running in minutes. The sum total of pushing my fresh application to the interwebs is found in these seven lines of code:</p>
<div>
<pre><code>heroku login
heroku create r-on-heroku
git init
git remote add heroku https://git.heroku.com/r-on-heroku.git
git add .
git commit -m &quot;Initial commit&quot;
git push heroku master
</code></pre>
</div>
<p>A quick look at https://r-on-heroku.herokuapp.com/ shows me that everything is working fine. Not terribly interesting yet, but it’s working. To make R available, I need to add another buildpack to my Heroku app. As it happens, someone has built one for R, which you can read about <a target="_blank" rel="nofollow" href="https://github.com/virtualstaticvoid/heroku-buildpack-r/tree/cedar-14-chroot">here</a>.</p>
<div>
<pre><code>heroku buildpacks:add http://github.com/virtualstaticvoid/heroku-buildpack-r.git#cedar-14-chroot
</code></pre>
</div>
<p>The buildpack expects a file called “init.R”, which it will execute. This is a good place for installation of packages that the Django application will need. I don’t put anything in here as I’m just going to use base graphics. To make that happen, I create folders for static content and one HTML template. I tweak the settings so that Django knows where to find static content and templates and change my view function to this:</p>
<div>
<pre><code>import subprocess

def index(request):
    subprocess.call(&quot;Rscript ./myPlot.R&quot;, shell=True)
    return render(request, 'index.html')

</code></pre>
</div>
<p>My R script will do nothing more than create a basic histogram for a normal distribution. The code to create the view will be rerun every time I make a request, so refreshing the page will produce a new, randomized image.</p>
<p>Testing this locally, everything works as expected. However, when I test the page as served by Heroku, things are not as nice. Refreshing the page continues to serve the same .PNG that I pushed up with git. What’s going on?</p>
<p>The proximate issue is that the Rscript command isn’t found on the deployment site. It turns out that installation of R on Heroku isn’t straightforward, as documented <a target="_blank" rel="nofollow" href="https://github.com/virtualstaticvoid/heroku-buildpack-r/blob/cedar-14-chroot/bin/compile">here</a>. This is quite a rabbit hole and it chewed up a healthy amount of a Friday afternoon. I did a bit of spelunking on the bash shell with <code>heroku run bash</code>. This tells me that R is installed in a hidden folder: <code>/app/.root/usr/bin/</code>. OK, so I can add that to the PATH and smooth sailing, right? Not so fast. The <code>R</code> command is actually a shell script and one of the first things it does is check for the location of <code>R_HOME</code>. And when I say “check for”, I mean “expect to find” in a specific place, namely <code>usr/lib/R</code>. OK, so I’ll just change that (despite <a target="_blank" rel="nofollow" href="https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=15070#c1">this comment</a>).</p>
<div>
<pre><code>R_HOME_DIR=/app/.root/usr/lib/R
if test &quot;${R_HOME_DIR}&quot; = &quot;/app/.root/usr/lib/R&quot;; then
</code></pre>
</div>
<p>This doesn’t work either. There’s a library that can’t be found, leading me to spend a bit of time playing with LD_LIBRARY_PATHS. At this point, I’m an appreciable distance from a canonical R installation. The buildpack documentation for R isn’t super detailed, but there’s a brief discussion of using the <code>chroot</code> command to run R as installed. Now, no one would mistake me for a Linux command line expert, so I’ll confess that this was a new one for me. Basically, it has the process run in such a way that it presumes the directory where it resides is root. This will make all the path references in the R script and environment variables work. So far, so cool. But there is one new problem. R can’t find my script. Playing with things in bash for a bit, I quickly fixed this. All I need is to prefix references to anything in my app with <code>~/</code> to get back to the “real” root directory.</p>
<p>Whew. That was a bit of a long walk, but things now work on Herkou. Just one more hassle: now things are gummed up locally. We can fix this by taking advantage of Heroku’s configuration variables. This allows me to store different environment variables locally and on production. I create two new strings to identify the R command used to run the script and where to find root. These have different values on my local device and Heroku. I test in both places and hurrah! Everything looks good!</p>
<p>Two additional environment variables isn’t terribly clean, but for now I’ll take it. Actually, storing this setting in the environment, rather than a Django configuration variable has at least one benefit: the value is easily accessible in R. I’ll need to ensure that all file access is decorated with the folder prefix, but this doesn’t feel like such a bad thing.</p>
<div>
<pre><code>myFile &lt;- file.path(Sys.getenv('R_SCRIPT_FOLDER_PREFIX'), 'static', 'myPlot.png')
png(filename=myFile)
</code></pre>
</div>
<p>Feel free to have a look at the basic project on <a target="_blank" rel="nofollow" href="https://github.com/PirateGrunt/r_on_heroku">https://github.com/PirateGrunt/r_on_heroku</a>.</p>
<h2>References</h2>
<p>This isn’t an exhaustive list. Suffice to say that I combed through <em>loads</em> of stackoverflow.</p>
<ul>
<li><a target="_blank" rel="nofollow" href="https://github.com/virtualstaticvoid/heroku-buildpack-r/tree/cedar-14-chroot">https://github.com/virtualstaticvoid/heroku-buildpack-r/tree/cedar-14-chroot</a></li>
<li><a target="_blank" rel="nofollow" href="http://stackoverflow.com/questions/16435615/heroku-rpy-rhome-discovery">http://stackoverflow.com/questions/16435615/heroku-rpy-rhome-discovery</a></li>
<li><a target="_blank" rel="nofollow" href="https://devcenter.heroku.com/articles/buildpacks">https://devcenter.heroku.com/articles/buildpacks</a></li>
</ul>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://pirategrunt.com/blog/r/2017/01/03/RonHeroku/"> PirateGrunt</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/5SaJc9fGOYw"></a></div>