<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/building-a-repository-of-alpine-based-docker-images-for-r-part-ii/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://velaco.github.io/my-dockerfile-for-r-shiny-based-on-alpine-linux-II/"> Curiosity Killed the Cat</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img alt="Shiny Alpine Docker Run" src="https://i2.wp.com/velaco.github.io/images/shiny-alpine-docker/alpine-shiny-run-success.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>In the <a rel="nofollow" href="https://velaco.github.io/my-dockerfile-for-r-shiny-based-on-alpine-linux/" target="_blank">first article of this series</a>, I built an Alpine-based Docker image with R base packages from Alpine’s native repositories, as well as one image with R compiled from source code. The images are hosted on Docker Hub, <a rel="nofollow" href="https://hub.docker.com/r/velaco/alpine-r/" target="_blank">velaco/alpine-r</a> repository.</p>
<p>The next step was either to address the fatal errors I found while testing the installation of R or to proceed building an image with Shiny Server. The logical choice would have been to pass all tests with R’s base packages before proceeding, but I was a bit impatient and wanted to go through the process of building a Shiny Server as soon as possible. After two weeks of trial and error, I finally have a container that can start the server and run Shiny apps.</p>
<p><span></span></p>
<p><em><strong>Notes:</strong> The Dockerfile I used is available in the <a rel="nofollow" href="https://github.com/velaco/alpine-r/" target="_blank">velaco/alpine-r repository</a> on GitHub. The latest image with Shiny Server is not available on Docker Hub because it exceeded the time limit for automated builds, so I’ll have to upload it manually.</em></p>
<h2>Building the R Shiny Server Image</h2>
<p>Shiny Server doesn’t have precompiled installers for Alpine Linux, so I had to build it from source. I used <a rel="nofollow" href="https://github.com/rstudio/shiny-server/wiki/Building-Shiny-Server-from-Source" target="_blank">Building Shiny Server from Source</a> as a reference to determine which dependencies I’ll install and to write the first version of the installation and post-installation instructions.</p>
<h3>Dependencies</h3>
<p>I wasn’t sure which dependencies to put under BUILD and which to put under PERSISTENT, so I added them all to a single variable for now. The packages <em>python2</em>, <em>gcc</em>, <em>g++</em>, <em>git</em>, <em>cmake</em>, and <em>R</em> (base and devel) are the main system requirements for installing Shiny Server from source. Based on my review of other Dockerfiles for Shiny, including the one maintained by Rocker, I also added <em>curl-dev</em>, <em>libffi</em>, <em>psmisc</em>, <em>rrdtool</em>, <em>cairo-dev</em>, <em>libxt-dev</em>, and <em>libxml2-dev</em> to the list of dependencies.</p>
<p>A system-wide installation of the <em>shiny</em> package and its dependencies is also necessary, and the first problem I encountered was the installation of the <em>httpuv</em> package. In order to install the <em>httpuv</em> package, I had to install <em>automake</em>, <em>autoconf</em>, <em>m4</em>, and <em>file</em> as well. The package asked for <em>automake</em> version 1.15 specifically, so I had to include the command <code>echo 'http://dl-cdn.alpinelinux.org/alpine/v3.6/main' >> /etc/apk/repositories</code> before adding the system requirements because that branch contains <em>automake</em> v1.15.1.</p>
<p>The package <em>wget</em> retrieves Node.js and <em>linux-headers</em> are needed to compile it from source. (The precompiled binaries didn’t work.)</p>
<p>Here is the final list of dependencies I included in the Dockerfile:</p>
<div>
<div>
<pre><code><span>FROM</span><span> velaco/alpine-r:base-3.5.0-r1</span>

<span>MAINTAINER</span><span> Aleksandar Ratesic &quot;aratesic@gmail.com&quot;</span>

<span># TODO: Separate to build and persistent!</span>
<span>ENV</span><span> ALL_DEPS \</span>
    automake==1.15.1-r0 \
    autoconf \
    bash \
    m4 \
    file \
    curl-dev \
    python2 \ 
    g++ \ 
    gcc \
    cmake \
    # Forgot to remove libc6-compat, no longer needed
    libc6-compat \
    git \
    libffi \
    psmisc \
    rrdtool \
    cairo-dev \
    libxt-dev \
    libxml2-dev \
    linux-headers \
    wget
</code></pre>
</div>
</div>
<h3>Installation</h3>
<p>I forked the Shiny Server git repository to make sure I have control over the changes made to it while working on this image. Apart from the installation of system dependencies and the <em>shiny</em> package, the installation instructions in the first version of the Dockerfile were pretty much an exact copy of the instructions provided by RStudio on GitHub:</p>
<div>
<div>
<pre><code><span>RUN </span><span>echo</span> <span>'http://dl-cdn.alpinelinux.org/alpine/v3.6/main'</span> <span>>></span> /etc/apk/repositories <span>&amp;&amp;</span> <span>\
</span>    apk upgrade <span>--update</span> <span>&amp;&amp;</span> <span>\
</span>    apk add <span>--no-cache</span> <span>$ALL_DEPS</span> <span>&amp;&amp;</span> <span>\
</span>    R <span>-e</span> <span>&quot;install.packages(c('shiny'), repos='http://cran.rstudio.com/')&quot;</span> <span>&amp;&amp;</span> <span>\
</span>    git clone https://github.com/velaco/shiny-server.git <span>&amp;&amp;</span> <span>\
</span>    <span>cd </span>shiny-server <span>&amp;&amp;</span> mkdir tmp <span>&amp;&amp;</span> <span>cd </span>tmp <span>&amp;&amp;</span> <span>\
</span>    <span>DIR</span><span>=</span><span>`</span><span>pwd</span><span>`</span> <span>&amp;&amp;</span> <span>PATH</span><span>=</span><span>$DIR</span>/../bin:<span>$PATH</span> <span>&amp;&amp;</span> <span>\
</span>    cmake <span>-DCMAKE_INSTALL_PREFIX</span><span>=</span>/usr/local ../ <span>&amp;&amp;</span> <span>\
</span>    make <span>&amp;&amp;</span> mkdir ../build <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> ./bin/npm <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> install<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> ./bin/node /usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> rebuild<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    make install
</code></pre>
</div>
</div>
<p>The first problem during the installation occurred because the command <code>cmake -DCMAKE_INSTALL_PREFIX=/usr/local ../</code> installed only pandoc, so the command <code>(cd .. &amp;&amp; ./bin/npm --python=&quot;$PYTHON&quot; install)</code> couldn’t find the Node.js binary. I decided to build an image up to that point and run a container to interactively look for a solution from the shell.</p>
<p>I retrieved Node.js with the command <code>(cd .. &amp;&amp; ./external/node/install-node.sh)</code>, but the installation failed again. I ran the command <code>file ../ext/node/bin/node</code> and learned that the requested program interpreter is <code>/lib64/ld-linux-x86-64.so.2</code>. The <em>libc6-compat</em> package contains that file and other compatibility libraries for <em>glibc</em>, so I added it and tried to install Node.js again. However, it didn’t help. I ended up with this error message:</p>
<div>
<div>
<pre><code>Error relocating ../ext/node/bin/node: __register_atfork: symbol not found
</code></pre>
</div>
</div>
<p>As an alternative to <em>libc6-compat</em>, I found the <em>glibc</em> package for Alpine on GitHub (<a rel="nofollow" href="https://github.com/sgerrand/alpine-pkg-glibc" target="_blank">link to repository</a>) and ran the following commands to retrieve and install the package:</p>
<div>
<div>
<pre><code>wget <span>-q</span> <span>-O</span> /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
apk add glibc-2.28-r0.apk <span>&amp;&amp;</span> rm glibc-2.28-r0.apk
</code></pre>
</div>
</div>
<p>I tried to run the script again, but the binary was looking for the libraries in the wrong path. That problem was easy to fix with <em>patchelf</em>:</p>
<div>
<div>
<pre><code>patchelf <span>--set-rpath</span> /usr/lib:/usr/glibc-compat/lib:/lib /shiny-server/ext/node/bin/node
patchelf <span>--add-needed</span> /lib/libc.musl-x86_64.so.1 /shiny-server/ext/node/bin/node
</code></pre>
</div>
</div>
<p>Although the location of the libraries was no longer an issue, rebuilding the modules still failed:</p>
<div>
<div>
<pre><code>/shiny-server/tmp <span># (cd .. &amp;&amp; ./bin/node ./ext/node/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js --python=&quot;/usr/bin/python&quot; rebuild)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
/shiny-server/ext/node/bin/node.bin: /usr/lib/libstdc++.so.6: no version information available <span>(</span>required by /shiny-server/ext/node/bin/node.bin<span>)</span>
Segmentation fault <span>(</span>core dumped<span>)</span>
</code></pre>
</div>
</div>
<p>I ran <code>ldd</code> from inside the container and got the same error as before, stating that __register_atfork was not found:</p>
<div>
<div>
<pre><code>/shiny-server/tmp <span># ldd ../ext/node/bin/node</span>
        /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
        libdl.so.2 <span>=></span> /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
        librt.so.1 <span>=></span> /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
        libstdc++.so.6 <span>=></span> /usr/lib/libstdc++.so.6 <span>(</span>0x7f6478413000<span>)</span>
        libm.so.6 <span>=></span> /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
        libgcc_s.so.1 <span>=></span> /usr/lib/libgcc_s.so.1 <span>(</span>0x7f6478201000<span>)</span>
        libpthread.so.0 <span>=></span> /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
        libc.so.6 <span>=></span> /lib64/ld-linux-x86-64.so.2 <span>(</span>0x7f6478766000<span>)</span>
Error relocating ../ext/node/bin/node: __register_atfork: symbol not found
Error relocating ../ext/node/bin/node: backtrace: symbol not found
</code></pre>
</div>
</div>
<p>The <em>glibc</em> repository has an <a rel="nofollow" href="https://github.com/sgerrand/alpine-pkg-glibc/issues/33" target="_blank">open issue</a> that reported the same problem (__register_atfork: symbol not found) in 2016, but I couldn’t find the solution to it anywhere.</p>
<p>I decided to change my approach, so I tried to install <em>nodejs</em> and <em>npm</em> packages from the native repositories. The only Node.js version available from Alpine’s 3.8 repository was 8.11.4. Shiny Server comes with a script that downloads version 8.11.3, so I hoped that the difference of one patch version wouldn’t be a problem.</p>
<p>With <em>npm</em> and <em>nodejs</em> packages installed from the native repository, I modified the instructions to rebuild the modules before installing Shiny Server, and the following instruction successfully created a layer of the image:</p>
<div>
<div>
<pre><code><span>RUN </span><span>echo</span> <span>'http://dl-cdn.alpinelinux.org/alpine/v3.6/main'</span> <span>>></span> /etc/apk/repositories <span>&amp;&amp;</span> <span>\
</span>    apk upgrade <span>--update</span> <span>&amp;&amp;</span> <span>\
</span>    apk add <span>--no-cache</span> <span>$ALL_DEPS</span> <span>&amp;&amp;</span> <span>\
</span>    R <span>-e</span> <span>&quot;install.packages(c('shiny'), repos='http://cran.rstudio.com/')&quot;</span> <span>&amp;&amp;</span> <span>\
</span>    git clone https://github.com/velaco/shiny-server.git <span>&amp;&amp;</span> <span>\
</span>    <span>cd </span>shiny-server <span>&amp;&amp;</span> mkdir tmp <span>&amp;&amp;</span> <span>cd </span>tmp <span>&amp;&amp;</span> <span>\
</span>    cmake <span>-DCMAKE_INSTALL_PREFIX</span><span>=</span>/usr/local ../ <span>&amp;&amp;</span> <span>\
</span>    make <span>&amp;&amp;</span> mkdir ../build <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> npm <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> <span>--unsafe-perm</span> install<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> node /usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> rebuild<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    make install
</code></pre>
</div>
</div>
<h3>Post-installation</h3>
<p>The post-installation is quite straightforward. You need to create a link to the shiny-server executable from <code>/usr/bin</code>, create the shiny user, and the directories for hosting the apps, logs, configuration files, etc. I decided to leave out the logs and not to touch the permissions because the script executed on running the container does that, so this is what the post-installation part of the instructions looked like:</p>
<div>
<div>
<pre><code>RUN ln <span>-s</span> /usr/local/shiny-server/bin/shiny-server /usr/bin/shiny-server <span>&amp;&amp;</span> <span>\</span>
    addgroup <span>-g</span> 82 <span>-S</span> shiny<span>;</span> <span>\</span>
    adduser <span>-u</span> 82 <span>-D</span> <span>-S</span> <span>-G</span> shiny shiny <span>&amp;&amp;</span> <span>\</span>
    mkdir <span>-p</span> /srv/shiny-server <span>&amp;&amp;</span> <span>\</span>
    mkdir <span>-p</span> /var/lib/shiny-server <span>&amp;&amp;</span> <span>\</span>
    mkdir <span>-p</span> /etc/shiny-server
    
COPY shiny-server.conf /etc/shiny-server/shiny-server.conf
COPY shiny-server.sh /usr/bin/shiny-server.sh

<span># Move sample apps to test installation, clean up</span>
RUN chmod 744 /usr/bin/shiny-server.sh <span>&amp;&amp;</span> <span>\</span>
    mv /shiny-server/samples/sample-apps /srv/shiny-server/ <span>&amp;&amp;</span> <span>\</span>
    mv /shiny-server/samples/welcome.html /srv/shiny-server/ <span>&amp;&amp;</span> <span>\</span>
    rm <span>-rf</span> /shiny-server/
    
EXPOSE 3838

CMD <span>[</span><span>&quot;/usr/bin/shiny-server.sh&quot;</span><span>]</span>
</code></pre>
</div>
</div>
<p>There were no problems with this part of the instructions, so the image was built successfully.</p>
<h3>Testing the Image</h3>
<p>With anticipation, I executed the command</p>
<p><code>run --rm -it velaco/alpine-r:shiny-3.5.0-r1</code></p>
<p>and… nothing happened. It was possible to run the container and start a shell, but as soon as I executed <code>exec /usr/bin/shiny-server</code>, it stopped working without giving me any messages.</p>
<p>I ran the container again, this time without security restrictions, and used strace on <code>/usr/bin/shiny-server</code> to find out at which point it exits. Here’s what I found:</p>
<div>
<div>
<pre><code>execve<span>(</span><span>&quot;/usr/local/shiny-server/ext/node/bin/shiny-server&quot;</span>, <span>[</span><span>&quot;/usr/local/shiny-server/ext/node&quot;</span>..., <span>&quot;/usr/local/shiny-server/lib/main&quot;</span>...], 0x7ffce0ae1518 /<span>*</span> 11 vars <span>*</span>/<span>)</span> <span>=</span> <span>-1</span> ENOENT <span>(</span>No such file or directory<span>)</span>
</code></pre>
</div>
</div>
<p>Turns out that the script Shiny Server uses to install Node.js contains a few instructions I skipped during the installation:</p>
<div>
<div>
<pre><code>cp ext/node/bin/node ext/node/bin/shiny-server
rm ext/node/bin/npm
<span>(</span><span>cd </span>ext/node/lib/node_modules/npm <span>&amp;&amp;</span> ./scripts/relocate.sh<span>)</span>
</code></pre>
</div>
</div>
<p>There was no way I could run those instructions with Node.js installed from native packages, so I decided to modify the installation instructions to compile it from source:</p>
<div>
<div>
<pre><code><span>RUN </span><span>echo</span> <span>'http://dl-cdn.alpinelinux.org/alpine/v3.6/main'</span> <span>>></span> /etc/apk/repositories <span>&amp;&amp;</span> <span>\
</span>    apk upgrade <span>--update</span> <span>&amp;&amp;</span> <span>\
</span>    apk add <span>--no-cache</span> <span>$ALL_DEPS</span> <span>&amp;&amp;</span> <span>\
</span>    R <span>-e</span> <span>&quot;install.packages(c('shiny'), repos='http://cran.rstudio.com/')&quot;</span> <span>&amp;&amp;</span> <span>\
</span>    git clone https://github.com/velaco/shiny-server.git <span>&amp;&amp;</span> <span>\
</span>    <span>cd </span>shiny-server <span>&amp;&amp;</span> mkdir tmp <span>&amp;&amp;</span> <span>cd </span>tmp <span>&amp;&amp;</span> <span>\
</span>    <span>DIR</span><span>=</span><span>`</span><span>pwd</span><span>`</span> <span>&amp;&amp;</span> <span>PATH</span><span>=</span><span>$DIR</span>/../bin:<span>$PATH</span> <span>&amp;&amp;</span> <span>\
</span>    cmake <span>-DCMAKE_INSTALL_PREFIX</span><span>=</span>/usr/local ../ <span>&amp;&amp;</span> <span>\
</span>    wget https://nodejs.org/dist/v8.11.3/node-v8.11.3.tar.xz <span>&amp;&amp;</span> <span>\
</span>    mkdir node_source <span>&amp;&amp;</span> <span>\
</span>    <span>tar </span>xf node-v8.11.3.tar.xz <span>--strip-components</span><span>=</span>1 <span>-C</span> <span>&quot;node_source&quot;</span> <span>&amp;&amp;</span> <span>\
</span>    rm node-v8.11.3.tar.xz <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd </span>node_source <span>&amp;&amp;</span> ./configure <span>--prefix</span><span>=</span>/shiny-server/ext/node<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd </span>node_source <span>&amp;&amp;</span> make<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd </span>node_source <span>&amp;&amp;</span> make install<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    cp /shiny-server/ext/node/bin/node /shiny-server/ext/node/bin/shiny-server <span>&amp;&amp;</span> <span>\
</span>    rm /shiny-server/ext/node/bin/npm <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> ../ext/node/lib/node_modules/npm <span>&amp;&amp;</span> ./scripts/relocate.sh<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    make <span>&amp;&amp;</span> mkdir ../build <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> ./bin/npm <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> <span>--unsafe-perm</span> install<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    <span>(</span><span>cd</span> .. <span>&amp;&amp;</span> ./bin/node ./ext/node/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js <span>--python</span><span>=</span><span>&quot;/usr/bin/python&quot;</span> rebuild<span>)</span> <span>&amp;&amp;</span> <span>\
</span>    make install
</code></pre>
</div>
</div>
<p>Building the image this way took more than 2 hours, but when I started the container and got confirmation that the server was running, I started celebrating. I should have waited a bit longer to celebrate because when I checked the example app in my browser, I learned that I still had work to do:</p>
<p><img alt="Shiny Alpine Docker" src="https://i2.wp.com/velaco.github.io/images/shiny-alpine-docker/alpine-shiny-example-error.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>Apparently, the command <code>su</code> in Alpine Linux doesn’t understand the <code>--login</code> option. The server is configured to <code>run_as shiny</code> and the container was running as root, so I <del>guessed</del> hoped that was the only reason it had to execute <code>su</code> at some point.</p>
<p>When I added the <code>USER shiny</code> instruction to the Dockerfile, the <code>su</code> command was no longer necessary. However, the server still didn’t work because the container executes a script to create the log directory. User <code>shiny</code> didn’t have permission to create the log directory, so I created it from the Dockerfile and set <code>shiny:shiny</code> as the owner of pretty much everything. (At this point I just wanted to get it over with, so some changes were probably not necessary and there was probably a better solution.)</p>
<p>With a log directory and <code>shiny</code> as the default user, the server successfully started the example Shiny app:</p>
<p><img alt="Shiny Alpine Docker" src="https://i1.wp.com/velaco.github.io/images/shiny-alpine-docker/alpine-shiny-example-success.png?w=456&ssl=1" data-recalc-dims="1"></p>
<h2>Next Steps</h2>
<p>The image I created runs Shiny Server on Alpine Linux, but I wouldn’t feel comfortable using it in production yet. Here are my goals for improving the current images:</p>
<ul>
<li><strong>Make sure the R installation passes all tests</strong>. It doesn’t have to pass every test without a single warning, but it should at least pass them all without fatal errors.</li>
<li><strong>Remove build dependencies from the image</strong>. The virtual size of this image is currently just over 500 MB. It can be reduced by removing some dependencies that are not required for running the server and probably some other files that are not necessary for running apps (e.g., documentation files, test suites, etc.).</li>
<li><strong>Compile Node.js from source in a base container</strong>. Node took forever to compile and install. The image alpine-r:shiny-3.5.0-r1 can’t automatically build on Docker Hub because it exceeds the time limit allowed for automated builds. Maybe it would be a better idea to compile Node.js in an separate image and use that image as a base for building one with Shiny Server.</li>
</ul>
<p>For now I’ll take a short break from this project to clear my head and get back to it with a fresh pair of eyes. Anyone interested in contributing and improving it can find the Dockerfiles in the <a rel="nofollow" href="https://github.com/velaco/alpine-r/" target="_blank">velaco/alpine-r repository</a> on GitHub.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://velaco.github.io/my-dockerfile-for-r-shiny-based-on-alpine-linux-II/"> Curiosity Killed the Cat</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 rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/cY8-vOF4ejg" height="1"></a></div>