feat: override port via environment variable
My understanding is that the environment variable SHINY_PORT can be used to override the port used by a shiny app. However this doesn't seem to be the case and, instead, leads to a spurious warning when used.
See the following repro. It results in the following warning message:
Warning in runApp(x) :
Shiny Server v0.3.4 or later is required; please upgrade!
Listening on http://127.0.0.1:9001
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30
)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x,
breaks = bins, col = "darkgray", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times"
)
})
}
Sys.setenv("SHINY_PORT" = "3000")
# Run the application
shinyApp(ui = ui, server = server, options = list(port = 9001))
My understanding is that the environment variable
SHINY_PORTcan be used to override the port used by a shiny app.
Did you see this somewhere in the Shiny docs? It'd be useful to track down and to understand.
From a quick code search here, SHINY_PORT isn't used to set the port used by Shiny. It appears to be an environment variable set by Shiny Server for its own purposes and within the R package we use its presence as a signal that the app is being run by Shiny server.
https://github.com/rstudio/shiny/blob/55b37fdeb3edf9524c5d4a715c3bc96568c327c2/R/server.R#L510-L514
The error you encounter is expected from these lines
https://github.com/rstudio/shiny/blob/55b37fdeb3edf9524c5d4a715c3bc96568c327c2/R/runapp.R#L203-L213
because Shiny thinks it's running inside Shiny Server and does a version check.
I think there's clearly room for improvement, but it could be tricky to handle in a way that doesn't break assumptions across Shiny packages and services.
Personally, I'd use a different environment variable passed directly to shinyApp() (untested, port might need to be coerced to int/numeric):
shinyApp(ui = ui, server = server, options = list(port = Sys.setenv("APP_PORT", 9001))
I've seen a lot of people use the existence of a SHINY_PORT envvar as a way to checke whether the app is running locally or not. This may or may not be documented, but it is advise commonly provided online and is widely used.
Anyone who sees that envvar can very reasonably assume that this envvar would set the port that shiny runs on. I also thought that when I first saw it.
@JosiahParry The correct way to set the port is with options(shiny.port = 3000). It looks very similar, there's no intuitive way to know that these two variables are so different. But that's what you're looking for!
Thanks, @daattali! It would be nice though if SHINY_PORT did what I had hoped :P nonetheless it would be nice to have it documented even if it is along the lines of "beware of the ghouls on stack overflow!"
I've seen a lot of people use the existence of a
SHINY_PORTenvvar as a way to checke whether the app is running locally or not. This may or may not be documented, but it is advise commonly provided online and is widely used.
It's really unfortunate that this this advice is out there in the world (related: #2923) because it makes it a lot harder to change how SHINY_PORT is used.
Given that history, I can confidently say we will not be introducing a new environment variable to override the app port -- unless there is a specific use case where it is currently impossible to change the app port and we would need to introduce an environment variable to make it possible.
My recommendation would be to introduce your own environment variable for your own apps, using one of the two options below:
# Option 1: Reflect envvar → R option
# (possibly checking first if the option is already set)
options(shiny.port = as.integer(Sys.getenv("MY_SHINY_PORT", "8181")))
# Option 2: Set port option directly in `shinyApp()` object options
shinyApp(
ui,
server,
options = list(port = as.integer(Sys.getenv("MY_SHINY_PORT", "8181")))
)
I would recommend the above as best practice even if SHINY_PORT does what you expected; it's easy for a global envvar to have conflicts between apps and use-cases and I'd recommend instead having app-specific variables.
I'm going to close issue because I don't anticipate we'll take further action toward making SHINY_PORT set the app port, but please feel free to follow up if there are use cases we haven't discussed so far.