├── .gitignore ├── Caddyfile ├── LICENSE ├── README.md ├── docker-compose-prod.yml ├── docker-compose.yml ├── log ├── index.R └── log.Rproj ├── pink ├── Dockerfile └── app │ └── app.R └── site ├── 404.html ├── apps.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | 8 | # User-specific files 9 | .Ruserdata 10 | 11 | # Example code in package build process 12 | *-Ex.R 13 | 14 | # Output files from R CMD build 15 | /*.tar.gz 16 | 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | 20 | # RStudio files 21 | .Rproj.user/ 22 | 23 | # produced vignettes 24 | vignettes/*.html 25 | vignettes/*.pdf 26 | 27 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 28 | .httr-oauth 29 | 30 | # knitr and R markdown default cache directories 31 | *_cache/ 32 | /cache/ 33 | 34 | # Temporary files created by R markdown 35 | *.utf8.md 36 | *.knit.md 37 | 38 | # R Environment Variables 39 | .Renviron 40 | 41 | /log/*.log 42 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | { 2 | email {$EMAIL} 3 | } 4 | 5 | {$HOST} { 6 | root * /srv 7 | handle_path /hello/* { 8 | reverse_proxy hello:3838 9 | } 10 | handle_path /pink/* { 11 | reverse_proxy pink:3838 12 | } 13 | handle_path /covidapp/* { 14 | reverse_proxy covidapp:3838 15 | } 16 | file_server 17 | handle_errors { 18 | @404 { 19 | expression {http.error.status_code} == 404 20 | } 21 | rewrite @404 /404.html 22 | file_server 23 | } 24 | log { 25 | output file /var/log/caddy/access.log 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Analythium Solutions Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Compose Example with Shiny and Caddy Server 2 | 3 | This repository is a companion to the following blog posts: 4 | 5 | - [Shiny Apps with Docker Compose, Part 1: Development](https://hosting.analythium.io/shiny-apps-with-docker-compose-part-1-development/) 6 | - [Shiny Apps with Docker Compose, Part 2: Production](https://hosting.analythium.io/shiny-apps-with-docker-compose-part-2-production/) 7 | 8 | ## Development 9 | 10 | Change the `EMAIL` environment variable in the `docker-compose.yml` file. 11 | 12 | ```bash 13 | docker-compose up -d 14 | ``` 15 | 16 | ## Production 17 | 18 | Change the `EMAIL` environment variable in the `docker-compose.yml` file. 19 | Change the `HOST` environment variable in the `docker-compose-prod.yml` file. 20 | 21 | ```bash 22 | docker-compose -f docker-compose.yml -f docker-compose-prod.yml up -d 23 | ``` 24 | -------------------------------------------------------------------------------- /docker-compose-prod.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | caddy: 5 | environment: 6 | - HOST="example.com" 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | hello: 5 | image: registry.gitlab.com/analythium/shinyproxy-hello/hello:latest 6 | restart: unless-stopped 7 | ports: 8 | - "9000:3838" 9 | pink: 10 | build: ./pink 11 | restart: always 12 | expose: 13 | - "3838" 14 | covidapp: 15 | image: analythium/covidapp-shiny:minimal 16 | restart: always 17 | expose: 18 | - "3838" 19 | caddy: 20 | image: caddy:2.3.0-alpine 21 | restart: always 22 | ports: 23 | - "80:80" 24 | - "443:443" 25 | volumes: 26 | - $PWD/Caddyfile:/etc/caddy/Caddyfile 27 | - $PWD/site:/srv 28 | - $PWD/log:/var/log/caddy 29 | - caddy_data:/data 30 | - caddy_config:/config 31 | depends_on: 32 | - hello 33 | - pink 34 | - covidapp 35 | environment: 36 | - HOST=":80" 37 | - EMAIL="your.name@yourdomain.com" 38 | volumes: 39 | caddy_data: 40 | caddy_config: 41 | -------------------------------------------------------------------------------- /log/index.R: -------------------------------------------------------------------------------- 1 | HOST <- "159.203.22.73" # your IP or HOST name here 2 | 3 | system2("scp", 4 | c( 5 | sprintf( 6 | "root@%s:/root/docker-compose-shiny-example/log/access.log", 7 | HOST 8 | ), 9 | "access.log" 10 | ) 11 | ) 12 | 13 | 14 | x <- lapply( 15 | readLines("access.log"), 16 | jsonlite::fromJSON) 17 | 18 | ## timestamp 19 | ts <- as.POSIXct(sapply(x, "[[", "ts"), origin = "1970-01-01") 20 | ## URI 21 | uri <- sapply(x, function(z) z$request$uri) 22 | 23 | ## find bare URIs 24 | s <- endsWith(req_uri, "/") & !endsWith(req_uri, "/websocket/") 25 | 26 | table(req_uri[s], as.Date(ts[s])) 27 | 28 | # 2021-06-15 2021-06-16 29 | # / 8 2 30 | # /covidapp/ 3 0 31 | # /hello/ 5 0 32 | # /pink/ 5 1 33 | -------------------------------------------------------------------------------- /log/log.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: XeLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | -------------------------------------------------------------------------------- /pink/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.gitlab.com/analythium/shinyproxy-hello/hello:latest 2 | WORKDIR /home/app 3 | RUN rm -rf * 4 | COPY app . 5 | CMD ["R", "-e", "shiny::runApp('/home/app')"] 6 | -------------------------------------------------------------------------------- /pink/app/app.R: -------------------------------------------------------------------------------- 1 | library(shiny) 2 | ui <- fluidPage( 3 | mainPanel( 4 | sliderInput("obs", 5 | "Number of observations", 6 | min = 1, 7 | max = 1000, 8 | value = 100 9 | ), 10 | plotOutput("distPlot") 11 | ) 12 | ) 13 | server <- function(input, output) { 14 | output$distPlot <- renderPlot({ 15 | dist <- runif(input$obs) 16 | hist(dist, 17 | col = "pink", 18 | xlab = "Random values" 19 | ) 20 | }) 21 | } 22 | shinyApp(ui = ui, server = server) -------------------------------------------------------------------------------- /site/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |