The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
It might look like Nix is an alternative to Docker, but that’s not really the case. Docker is a containerisation tool, while Nix is a package manager. You can use Nix in such a way that you don’t need Docker anymore, but if you’re already invested in Docker, you don’t have to abandon it and can still benefit from Nix.
This Dockerfile
uses ubuntu:latest
as a
base image, and then uses the Nix package manager to set up a complete
development environment:
FROM ubuntu:latest
RUN apt update -y
RUN apt install curl -y
# We don't have R nor {rix} in this image, so we can bootstrap it by downloading
# the default.nix file that comes with {rix}. You can also download it beforehand
# and then copy it to the Docker image
RUN curl -O https://raw.githubusercontent.com/ropensci/rix/main/inst/extdata/default.nix
# Copy a script to generate the environment of interest using {rix}
COPY generate_env.R .
# The next 4 lines install Nix inside Docker. See the Determinate Systems installer's documentation
RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \
--extra-conf "sandbox = false" \
--init none \
--no-confirm
# Adds Nix to the path, as described by the Determinate Systems installer's documentation
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
# This will overwrite the default.nix we downloaded previously with a new
# expression generated from running `generate_env.R`
RUN nix-shell --run "Rscript generate_env.R"
# We now build the environment
RUN nix-build
# Finally, we run `nix-shell`. This will get executed when running
# containers from this image. You can of course put anything in here
CMD nix-shell
It doesn’t matter that we are using ubuntu:latest
as a
base image, which is usually not recommended for reproducibility
purposes, since it is Nix that takes care of ensuring that our
environment is reproducible.
Here is an example of the generate_env.R
file:
library(rix)
rix(
r_ver = "4.3.1",
r_pkgs = c("dplyr", "ggplot2"),
ide = "other",
project_path = ".",
shell_hook = "R",
overwrite = TRUE
)
Using Nix to handle the setup of the environment, even inside Docker, creates a nice separation of concerns. On one hand, you can continue using Docker to serve applications, and on the other hand, you can use Nix to ensure you don’t have to store images, as you can always rebuild the correct environment in a completely reproducible manner.
Dockerizing a Shiny application using Nix is very easy as
well. You can keep almost exactly the same Dockerfile
as
above, you only need to add the required ui.R
and
server.R
files (and any other files needed by your app),
and expose the port you want:
FROM ubuntu:latest
RUN apt update -y
RUN apt install curl -y
# Get a default.nix with R and rix
RUN curl -O https://raw.githubusercontent.com/ropensci/rix/main/inst/extdata/default.nix
# Copy a script to generate the environment of interest using rix
COPY generate_env.R .
# Copy the required scripts for the app
COPY ui.R .
COPY server.R .
RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \
--extra-conf "sandbox = false" \
--init none \
--no-confirm
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
# This will overwrite the default.nix we downloaded with a new one
RUN nix-shell --run "Rscript generate_env.R"
EXPOSE 3838
RUN nix-build
CMD nix-shell --run 'Rscript -e "shiny::runApp(port = 3838, host = \"0.0.0.0\")"'
adapt the generate_env.R
script:
library(rix)
rix(
r_ver = "4.2.2",
r_pkgs = "shiny",
ide = "other",
project_path = ".",
overwrite = TRUE
)
Here is the code of a simple Shiny app (it’s the K-means app from the Shiny examples gallery):
# k-means only works with numerical variables,
# so don't give the user the option to select
# a categorical variable
vars <- setdiff(names(iris), "Species")
pageWithSidebar(
headerPanel("Iris k-means clustering"),
sidebarPanel(
selectInput("xcol", "X Variable", vars),
selectInput("ycol", "Y Variable", vars, selected = vars[[2]]),
numericInput("clusters", "Cluster count", 3, min = 1, max = 9)
),
mainPanel(
plotOutput("plot1")
)
)
function(input, output, session) {
# Combine the selected variables into a new data frame
selectedData <- reactive({
iris[, c(input$xcol, input$ycol)]
})
clusters <- reactive({
kmeans(selectedData(), input$clusters)
})
output$plot1 <- renderPlot({
palette(c(
"#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
"#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"
))
par(mar = c(5.1, 4.1, 0, 1))
plot(selectedData(),
col = clusters()$cluster,
pch = 20, cex = 3
)
points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
})
}
Build the image with:
docker build -t shiny_app .
and run a container with:
docker run --rm -p 3838:3838 --name my_container shiny_app
You can also your image from the NixOS Docker image instead of Ubuntu, in which case you don’t need to install Nix. NixOS is a full GNU/Linux distribution that uses Nix as its system package manager.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.