部署 Shiny 应用
将应用发布到 shinyapps.io、Shiny Server 和 Docker 容器环境
部署 Shiny 应用 是 CoddyKit 上的免费 R Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。
部署选项概览
Shiny 应用可以根据预算、预期流量和控制需求部署到多个平台:
- shinyapps.io:由 Posit 管理的云托管服务——最简单,并提供免费套餐。
- Shiny Server(开源版):自行托管在 Linux 上,免费。
- Posit Connect:商业级企业平台,同时支持 R Markdown 和 Plumber。
- Docker + rocker/shiny:提供最大的可移植性和控制能力。
# Summary of deployment options and their trade-offs:
# shinyapps.io: managed, auto-scaling, per-instance pricing
# Shiny Server: self-hosted, unlimited users, needs sysadmin
# Posit Connect: enterprise SSO, scheduling, REST APIs
# Docker: any cloud provider, reproducible environments
cat('Choose based on: scale, budget, infra control needs')用于部署的 app.R 结构
可部署的 Shiny 应用必须包含一个单独的 app.R 文件(同时包含 ui 和 server),或者包含两个文件 ui.R 和 server.R。所有程序包依赖项都必须在文件顶部使用 library() 声明。数据文件必须位于同一目录中,或能够通过相对于应用目录的路径访问。
# Minimal app.R for deployment
library(shiny)
library(ggplot2)
library(dplyr)
# Load data relative to app directory
data <- readRDS('data/processed_data.rds')
ui <- fluidPage(
titlePanel('My Deployed App'),
sidebarLayout(
sidebarPanel(selectInput('var', 'Variable:', choices = names(data))),
mainPanel(plotOutput('main_plot'))
)
)
server <- function(input, output, session) {
output$main_plot <- renderPlot({
ggplot(data, aes_string(x = input$var)) + geom_histogram()
})
}
shinyApp(ui, server)rsconnect::deployApp()
rsconnect 程序包负责将应用部署到 shinyapps.io 和 Posit Connect。首先配置账户凭据,然后在应用目录中调用 rsconnect::deployApp()。它会自动打包所有 R 文件、数据和清单文件。
library(rsconnect)
# One-time setup: link your shinyapps.io account
# rsconnect::setAccountInfo(
# name = 'your_account_name',
# token = 'YOUR_TOKEN',
# secret = 'YOUR_SECRET'
# )
# Deploy the app in the current directory
rsconnect::deployApp(
appDir = '.', # or 'path/to/app'
appName = 'my_analysis_app',
forceUpdate = TRUE
)shinyapps.io 设置
shinyapps.io 是获取公共网址最快捷的方式。在 shinyapps.io 创建免费账户,从控制面板复制令牌和密钥,然后调用 setAccountInfo()。免费套餐每月允许使用 5 个应用和 25 个活跃小时。
library(rsconnect)
# Copy credentials from shinyapps.io -> Account -> Tokens
rsconnect::setAccountInfo(
name = 'your_username',
token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
secret = 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
)
# Verify the connection
rsconnect::accountInfo()
# List currently deployed apps
rsconnect::applications()Shiny Server 开源版
Shiny Server 运行在 Linux(Ubuntu/RHEL)上,并从 /srv/shiny-server/ 目录提供 Shiny 应用。每个子目录都会成为一个应用,对应的地址为 http://server:3838/subdirname/。它是免费的,并支持不限数量的并发用户(受服务器容量限制)。
# Install Shiny Server on Ubuntu:
# sudo apt-get install r-base
# sudo R -e 'install.packages(c("shiny", "rmarkdown"))'
# wget https://download3.rstudio.org/ubuntu-20.04/x86_64/shiny-server-1.5.21.1012-amd64.deb
# sudo dpkg -i shiny-server-1.5.21.1012-amd64.deb
# Deploy an app:
# sudo cp -r /path/to/myapp /srv/shiny-server/myapp
# Access at: http://your-server:3838/myapp
# Config file: /etc/shiny-server/shiny-server.conf
cat('Shiny Server config controls ports, auth, and app paths')使用 rocker/shiny 的 Docker
rocker/shiny Docker 镜像提供预配置的 Shiny Server。将应用目录挂载到容器中即可立即提供应用服务。Docker 可确保可复现性——同一个镜像在任何主机上运行时都保持一致。
# Dockerfile for a custom Shiny app
# FROM rocker/shiny:4.4.0
#
# # Install R package dependencies
# RUN R -e 'install.packages(c("ggplot2","dplyr","DT"))'
#
# # Copy app files
# COPY myapp/ /srv/shiny-server/myapp/
#
# EXPOSE 3838
# Build and run:
# docker build -t my-shiny-app .
# docker run -p 3838:3838 my-shiny-app
# Access at: http://localhost:3838/myapp使用 renv 管理可复现的依赖项
renv 会创建项目级程序包库,并通过锁定文件(renv.lock)记录精确的程序包版本。部署时,该锁定文件可确保服务器或 Docker 镜像安装与开发期间完全相同的程序包版本。
library(renv)
# Initialise renv in the project (creates renv.lock)
renv::init()
# After installing/updating packages, record the state
renv::snapshot()
# On the server: restore exact versions from lockfile
renv::restore()
# Check lockfile for a specific package version
renv::dependencies() # lists all used packages用于配置的环境变量
绝不要将 API 密钥、数据库密码或特定环境的设置硬编码到应用代码中。请使用环境变量,并通过 Sys.getenv('VAR_NAME', unset = NA) 读取。在本地环境中将其设置在 .Renviron 中,在生产环境中则设置在托管平台的环境配置中。
# In .Renviron (never commit this file):
# DB_HOST=prod-db.example.com
# DB_PASSWORD=secret123
# API_KEY=key_abc
# In app.R:
db_host <- Sys.getenv('DB_HOST', unset = 'localhost')
db_pass <- Sys.getenv('DB_PASSWORD', unset = '')
api_key <- Sys.getenv('API_KEY', unset = '')
if (api_key == '') {
warning('API_KEY not set — some features disabled')
}Posit Connect 概览
Posit Connect 是用于部署 Shiny 应用、R Markdown 文档、Plumber API 等内容的企业级平台。它支持:
- 通过 LDAP 或 SAML 实现单点登录(SSO)
- 按计划执行 R Markdown 报告
- 在应用级别进行访问控制
- 自动扩缩容和负载均衡
部署使用与 shinyapps.io 相同的 rsconnect::deployApp() 工作流程。
library(rsconnect)
# Configure connection to Posit Connect server
rsconnect::addServer(
url = 'https://connect.yourcompany.com',
name = 'my_connect_server'
)
# Authenticate with API key
rsconnect::connectApiUser(
account = 'jsmith',
server = 'my_connect_server',
apiKey = Sys.getenv('CONNECT_API_KEY')
)
# Deploy
rsconnect::deployApp(server = 'my_connect_server')部署前检查清单
将 Shiny 应用部署到生产环境之前,请确认:
- 所有文件路径都使用相对路径,而不是绝对路径。
- 敏感数据(API 密钥、密码)都从环境变量中读取。
- 程序包依赖项通过
library()或renv.lock明确声明。 - 大型数据文件在 server.R 顶部加载一次,而不是在响应式代码内部加载。
- 错误消息不会向最终用户暴露内部信息。
# Production-hardened app.R patterns
# Load data once at startup (not per-session)
app_data <- readRDS('data/processed.rds') # outside server()
server <- function(input, output, session) {
# Reference app_data directly — already in memory
output$plot <- renderPlot({
subset_data <- app_data[app_data$group == input$grp, ]
plot(subset_data$x, subset_data$y)
})
# Sanitise error messages
tryCatch({
risky_operation()
}, error = function(e) {
showNotification('An error occurred.', type = 'error')
# log the real error internally, not to user
message('Error: ', conditionMessage(e))
})
}扩展规模时的注意事项
Shiny 应用基于会话运行:每位用户都会获得自己的 R 进程(或工作进程)。扩展规模的策略包括:
- 在启动时加载预先计算的数据,而不是为每个会话重复计算。
- 对于多个会话共享的昂贵计算,使用
bindCache()进行响应式缓存。 - 多个工作进程:Shiny Server Pro 和 Posit Connect 会启动并行的 R 进程。
- 数据库后端:使用 DBI/pool 进行并发数据库访问。
library(shiny)
library(pool)
# Create a database connection pool at startup
# (shared across all sessions)
pool <- dbPool(
drv = RPostgres::Postgres(),
host = Sys.getenv('DB_HOST'),
dbname = 'analytics',
user = Sys.getenv('DB_USER'),
password = Sys.getenv('DB_PASSWORD'),
minSize = 2,
maxSize = 10
)
onStop(function() { poolClose(pool) })
server <- function(input, output, session) {
output$tbl <- renderTable({
dbGetQuery(pool, 'SELECT * FROM metrics LIMIT 100')
})
}快速检查
在已部署的 Shiny 应用中,处理 API 密钥和数据库密码的推荐方式是什么?
部署 Shiny 应用回顾
部署 Shiny 应用的要点:
- 部署选项:shinyapps.io(最简单)、Shiny Server(自行托管)、Posit Connect(企业级)、Docker。
- app.R 必须使用
library()声明所有依赖项;使用renv::snapshot()保存可复现的版本。 rsconnect::deployApp()会打包应用并将其推送到 shinyapps.io 或 Posit Connect。- 使用
rocker/shiny的 Docker 可提供最大的可移植性。 - 使用
Sys.getenv()管理凭据——绝不要将机密信息硬编码。 - 在启动时加载大型数据集(位于
server()外部),以便在多个会话之间共享。 - 使用连接池(
pool程序包)进行并发数据库访问。
# Minimal production-ready structure
# myapp/
# app.R <- ui + server + shinyApp()
# data/ <- processed datasets
# R/ <- modules and helpers
# renv.lock <- package version snapshot
# .Renviron <- local env vars (gitignored)
# Deploy:
library(rsconnect)
rsconnect::deployApp(
appDir = 'myapp',
appName = 'my_production_app'
)用 AI 导师学习 R — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 43
- 课程
- 159
常见问题解答
「部署 Shiny 应用」课时是免费的吗?
是的 — 「部署 Shiny 应用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。
「部署 Shiny 应用」这节课中我会学到什么?
将应用发布到 shinyapps.io、Shiny Server 和 Docker 容器环境 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 R Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「部署 Shiny 应用」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 R Academy 课中编写并运行代码吗?
能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。