skip to Main Content

I’m trying to dockerize my shiny app made with {golem} (the app is packaged as a library) and I’m running into problems because I have some bootstrap dependencies in my custom.scss file (such as @include media-breakpoint-up(lg)) and it seems that these dependencies cannot be automatically linked inside a docker container, while working locally. I am using {bslib} inside the app as well.

Everything works smoothly when installing/running the app locally (even on a remote server), but when trying to dockerize the app, it cannot interpret the custom.scss file, the link with bootstrap dependencies don’t work. The error when listening to the app is Error: File to import not found or unreadable: /tmp/RtmpWzfgRD/R.INSTALL682a228ec/<APPNAME>/inst/app/www/custom.scss. on line 71:1 of /stdin >> @import "/tmp/RtmpWzfgRD/R.INSTALL682a228ec/<APPNAME>/inst/app/www/custom.scs ^

The theme in my app_ui.R file is built as follow :

bslib::bs_theme(version = 5, preset = "bootstrap") |>
    bslib::bs_add_rules(sass::sass_file("./inst/app/www/custom.scss")) # add complementary scss file

The .scss file can be viewed here (it’s called custom_bs5.scss in this version on GitHub) : https://github.com/mick-weber/eneRgyVD/blob/main/inst/app/www/custom_bs5.scss

I have achieved the following :

  • The app works perfectly locally, custom.scss is correctly interpreted and the @include media-breakpoint-up(lg) features work as expected, though no explicit import to bootstrap dependencies is made inside custom.scss

  • Adding the whole bootstrap github repository inside the app and importing it from custom.scss with @ import 'bootstrap-main/scss/bootstrap'; : this launches the app correctly but messes with the whole theme really bad, I can barely recognize the app.

  • The app within a docker container works fine as long as there’s no mention of these @include media-breakpoint-up(lg) calls. The dockerfile contains all R librairies (loaded with renv.lock) see below for the content of the dockerfiles

Is there anything I’m missing ? Why can’t my docker container make the same implicit link between the @include media-breakpoint-up(lg) queries and the bootstrap files ? If any explicit links must be made, how should I make them (e.g. @import ... but linking to which files in my docker container ?)

Dockerfiles are generated with golem::add_dockerfile_with_renv(lockfile = 'renv.lock') :

Dockerfile_base :

FROM rocker/verse:4.4.1
RUN apt-get update -y && apt-get install -y  make pandoc zlib1g-dev libicu-dev libxml2-dev libx11-dev git libcurl4-openssl-dev libssl-dev libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev libjpeg-dev libpng-dev libtiff-dev libgdal-dev gdal-bin libgeos-dev libproj-dev libsqlite3-dev libudunits2-dev && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /usr/local/lib/R/etc/ /usr/lib/R/etc/
RUN echo "options(renv.config.pak.enabled = FALSE, repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl', Ncpus = 4)" | tee /usr/local/lib/R/etc/Rprofile.site | tee /usr/lib/R/etc/Rprofile.site
RUN R -e 'install.packages("remotes")'
RUN R -e 'remotes::install_version("renv", version = "1.0.11")'

Dockerfile :

FROM energyvd_base
COPY renv.lock renv.lock
RUN R -e 'options(renv.config.pak.enabled = FALSE);renv::restore(exclude = "eneRgyVD")'
COPY eneRgyVD_*.tar.gz /app.tar.gz
RUN R -e 'remotes::install_local("/app.tar.gz",upgrade="never")'
RUN rm /app.tar.gz
EXPOSE 80
USER rstudio
CMD R -e "options('shiny.port'=80,shiny.host='0.0.0.0');library(eneRgyVD);eneRgyVD::run_app()"

Running procedure :

docker build -f Dockerfile_base --progress=plain -t energyvd_base .
docker build -f Dockerfile --progress=plain -t energyvd:latest .
docker run -p 80:80 energyvd:latest

EDIT :

With this code I managed to create a custom.css file which does not mess up with my theme :

sass::sass(input = sass::sass_file("inst/app/www/custom.scss"),
           output = "inst/app/www/custom.css",
           cache = NULL,
           options = sass::sass_options(
             include_path = system.file("lib/bs5/scss/", package = "bslib")))

I can then use custom.css instead of custom.scss as follow :

bslib::bs_theme(version = 5) |>
bslib::bs_add_rules(sass::sass_file("inst/app/www/custom.css"))

It’s still not exactly what I wanted since I’d like to refer to the .scss file directly without having to make the .css conversion manually, but I’m almost there !

2

Answers


  1. Let me help you with that Bootstrap issue in Docker. Here’s what’s up:

    Your Bootstrap isn’t playing nice with Docker, but don’t worry! Here are some practical solutions:

    Solution 1: Direct Import

    Add these Bootstrap imports to your custom.scss:

    @import "bootstrap/scss/functions";
    @import "bootstrap/scss/variables";
    @import "bootstrap/scss/mixins";
    
    // Rest of your styles here...
    

    Solution 2: Using bslib’s Path

    Tweak your app_ui.R like this:

    app_ui <- function(request) {
      bslib::bs_theme(version = 5, preset = "bootstrap") |>
        bslib::bs_add_rules(
          sass::sass_file(
            "inst/app/www/custom.scss",
            options = sass::sass_options(
              include_path = system.file("node_modules", package = "bslib")
            )
          )
        )
      # Rest of your UI code...
    }
    

    Solution 3: Bootstrap in Docker

    Add this to your Dockerfile:

    # ... your existing Dockerfile stuff ...
    
    # Installing Bootstrap
    RUN R -e 'bslib::bs_theme_dependencies()'
    
    # ... rest of the file ...
    

    What’s Going On:

    • Docker can’t find Bootstrap dependencies that work fine on your machine
    • The error shows it can’t locate the SCSS file in that temp directory
    • Making imports explicit or using bslib files will fix this
    • Double-check that bslib is properly listed in your renv.lock

    Pro Tip:

    For quick SCSS testing during development, use this command:

    docker run -p 80:80 -v $(pwd)/inst/app/www:/app/www energyvd:latest
    
    Login or Signup to reply.
  2. The issue you’re experiencing is because recent versions of bslib handle Node dependencies differently. Instead of looking for node_modules directly, you can try this approach:

    # Get the bslib installation path
    bslib_path <- system.file(package = "bslib")
    
    # Check for the actual Bootstrap files
    bootstrap_path <- file.path(bslib_path, "lib", "bs")
    
    # If you need specific Bootstrap files, you can look here:
    bs_files <- list.files(bootstrap_path, recursive = TRUE)
    

    The Bootstrap files are now typically located in the lib/bs directory within the package installation path. If you’re trying to access specific Bootstrap components, you might want to use bslib’s built-in functions instead of accessing the files directly:

    library(bslib)
    
    # Use bs_theme() to customize Bootstrap
    my_theme <- bs_theme(version = 5)  # or whichever version you need
    

    What specific Bootstrap components are you trying to access? This might help me provide a more targeted solution.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search