This repository contains supporting material ofr the following blog posts on the Hosting Data Apps (hosting.analythium.io) website:
- How to Set Up Quarto with Docker, Part 1: Static Content
- How to Set Up Quarto with Docker, Part 2: Dynamic Content
Quarto is is an open-source scientific and technical publishing system built on Pandoc.
The examples in this repository focus on R related Quarto documents. We review the different options for dockerizing static and interactive Quarto documents.
We build a parent image with Quarto installed so that we can use this image in subsequent FROM
instructions.
The Dockerfile.base
is based on a Ubuntu based image.
This part in the Dockerfile will install the Quarto command line tool:
...
RUN curl -LO https://quarto.org/download/latest/quarto-linux-amd64.deb
RUN gdebi --non-interactive quarto-linux-amd64.deb
...
If you want a specific version, use:
...
ARG QUARTO_VERSION="0.9.522"
RUN curl -o quarto-linux-amd64.deb -L https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.deb
RUN gdebi --non-interactive quarto-linux-amd64.deb
...
Now we can build the image:
docker build \
-f Dockerfile.base \
-t analythium/r2u-quarto:20.04 .
Run the container interactively to check the installation:
docker run -it --rm analythium/r2u-quarto:20.04 bash
Type quarto check
, you should see check marks:
root@d8377016be7f:/# quarto check
[✓] Checking Quarto installation......OK
Version: 1.0.36
Path: /opt/quarto/bin
[✓] Checking basic markdown render....OK
[✓] Checking Python 3 installation....OK
Version: 3.8.10
Path: /usr/bin/python3
Jupyter: (None)
Jupyter is not available in this Python installation.
Install with python3 -m pip install jupyter
[✓] Checking R installation...........OK
Version: 4.2.1
Path: /usr/lib/R
LibPaths:
- /usr/local/lib/R/site-library
- /usr/lib/R/site-library
- /usr/lib/R/library
rmarkdown: 2.14
[✓] Checking Knitr engine render......OK
Type exit
to quit the session.
Render the R example for air quality:
docker build \
-f Dockerfile.static-file \
-t analythium/quarto:static-file .
docker run -p 8080:8080 analythium/quarto:static-file
Projects contain multiple files, like website and books.
Use the following command to create a website template locally: quarto create-project static-website --type website
.
Render the project as quarto render static-website --output-dir output
.
Then use this Dockerfile:
FROM ghcr.io/openfaas/of-watchdog:0.9.6 AS watchdog
FROM alpine:latest
RUN mkdir /app
COPY static-website/output /app
COPY --from=watchdog /fwatchdog .
ENV mode="static"
ENV static_path="/app"
HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1
CMD ["./fwatchdog"]
docker build \
-f Dockerfile.static-website \
-t analythium/quarto:static-website .
docker run -p 8080:8080 analythium/quarto:static-website
Use the following command to create a book template locally: quarto create-project static-book --type book
.
Render the project as quarto render static-book --output-dir output
.
Then use this Dockerfile:
FROM ghcr.io/openfaas/of-watchdog:0.9.6 AS watchdog
FROM alpine:latest
RUN mkdir /app
COPY static-book/output /app
COPY --from=watchdog /fwatchdog .
ENV mode="static"
ENV static_path="/app"
HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1
CMD ["./fwatchdog"]
Note: we need a LaTeX installation, so we add quarto install tool tinytex
to the Dockerfile:
docker build \
-f Dockerfile.static-book \
-t analythium/quarto:static-book .
docker run -p 8080:8080 analythium/quarto:static-book
Render an interactive but static file:
docker build \
-f Dockerfile.static-widget \
-t analythium/quarto:static-widget .
docker run -p 8080:8080 analythium/quarto:static-widget
You can specify Shiny as the engine to run the dynamic Quarto document.
In this example we do not render the Quarto document up front. The render step will happen when the container is spin up. This is analogous to the R Markdown Shiny runtime.
We use the quarto serve index.qmd --port 8080 --host 0.0.0.0
command to specify port and host IPv4 address. The quarto serve
function will render the document before serving.
This example shows the classic Old Faithful histogram with the slider.
docker build -f Dockerfile.shiny -t analythium/quarto:shiny .
docker run -p 8080:8080 analythium/quarto:shiny
If you can't kill the container with Ctrl+C
, try getting the container ID with docker ps
and then use docker kill $ID
.
Note: you can serve the doc from R with quarto::quarto_serve("index.qmd")
.
Depending on the complexity of your document, rendering at the container launch time will significantly increase "cold start" time. But we can render the document as part of the Docker build process. This is analogous to the R Markdown prerendered Shiny runtime (shinyrmd).
When we render the file, the UI elements get rendered, while the code chunks marked as context: server
will wait until the rendered document is served. Read more about render and server contexts.
This example shows k-means clustering with custom page layout.
quarto serve
is called with the --no-render
flag to avoid unnecessary rendering.
docker build \
-f Dockerfile.shiny-prerendered \
-t analythium/quarto:shiny-prerendered .
docker run -p 8080:8080 analythium/quarto:shiny-prerendered