Развёртывание приложений Shiny
Публикуйте приложения на shinyapps.io, Shiny Server и в средах на основе Docker
«Развёртывание приложений Shiny» — бесплатный урок R Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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 — самый быстрый способ получить общедоступный URL. Создайте бесплатную учетную запись на сайте 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) и предоставляет приложения Shiny из каталога /srv/shiny-server/. Каждый вложенный каталог становится приложением по адресу 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')Docker с rocker/shiny
Образ Docker rocker/shiny содержит предварительно настроенный 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/myapprenv для воспроизводимых зависимостей
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, API Plumber и других материалов. Она поддерживает:
- единую систему входа (SSO) через LDAP или SAML
- запланированный запуск отчетов R Markdown
- управление доступом на уровне приложения
- автоматическое масштабирование и балансировку нагрузки
Развертывание выполняется с помощью того же процесса rsconnect::deployApp(), что и в shinyapps.io.
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')
})
}Быстрая проверка
Как рекомендуется хранить ключи API и пароли к базам данных в развернутом приложении Shiny?
Итоги развертывания приложений Shiny
Основные выводы из урока «Развертывание приложений Shiny»:
- Варианты развертывания: shinyapps.io (самый простой), Shiny Server (самостоятельное размещение), Posit Connect (корпоративный вариант), Docker.
- app.R должен объявлять все зависимости с помощью
library(); для воспроизводимых версий используйтеrenv::snapshot(). rsconnect::deployApp()упаковывает приложение и отправляет его в shinyapps.io или Posit Connect.- Docker с
rocker/shinyобеспечивает максимальную переносимость. - Для учетных данных используйте
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'
)Часто задаваемые вопросы
Урок «Развёртывание приложений Shiny» бесплатный?
Да — полный текст урока «Развёртывание приложений Shiny» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс R Academy, подпишись на CoddyKit PRO. Курс R Academy содержит 4 уроков всего.
Чему я научусь в уроке «Развёртывание приложений Shiny»?
Публикуйте приложения на shinyapps.io, Shiny Server и в средах на основе Docker Ты практикуешь R Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать R Academy?
Предыдущий опыт не требуется. R Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Развёртывание приложений Shiny»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке R Academy?
Да. Каждый урок R Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Глубокое погружение в реактивное программирование
- Модули Shiny для повторного использования кода
- Динамический интерфейс с renderUI и insertUI
- Развёртывание приложений Shiny