Конфигурация приложений Rust: библиотеки config, envy и dotenvy

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Конфигурация приложений Rust: библиотеки config, envy и dotenvy

При разработке приложений на Rust управление конфигурацией — одна из ключевых задач. От правильного подхода к загрузке настроек зависит гибкость, безопасность и удобство развертывания. В экосистеме Rust существует несколько зрелых решений, которые позволяют читать конфигурацию из файлов, переменных окружения и других источников. В этой статье мы рассмотрим три популярных инструмента: config, envy и dotenvy.

1. Библиотека config — универсальный менеджер конфигурации

config — это мощная библиотека для загрузки иерархических конфигураций. Она поддерживает несколько форматов (JSON, TOML, YAML, HJSON, INI), а также переменные окружения и удаленные источники. Основная идея — объединить все источники в единое дерево настроек.

Установка

[dependencies]
config = "0.14"
serde = { version = "1.0", features = ["derive"] }

Пример использования

use config::{Config, File, Environment};
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct AppConfig {
    server: ServerConfig,
    database: DatabaseConfig,
}

#[derive(Debug, Deserialize)]
struct ServerConfig {
    host: String,
    port: u16,
}

#[derive(Debug, Deserialize)]
struct DatabaseConfig {
    url: String,
    pool_size: u32,
}

fn load_config() -> Result<AppConfig, config::ConfigError> {
    let cfg = Config::builder()
        .add_source(File::with_name("config/default"))  // Базовые настройки
        .add_source(File::with_name("config/local").required(false)) // Локальные переопределения
        .add_source(Environment::with_prefix("APP")) // Переменные окружения с префиксом APP_
        .build()?;

    cfg.try_deserialize()
}

fn main() {
    match load_config() {
        Ok(config) => println!("Loaded config: {:?}", config),
        Err(e) => eprintln!("Config error: {}", e),
    }
}

Библиотека автоматически объединяет источники: значения из последующих источников перезаписывают предыдущие. Это позволяет легко организовать иерархию: default → environment → local override.

2. Библиотека envy — конфигурация из переменных окружения

envy — минималистичная библиотека, которая загружает конфигурацию исключительно из переменных окружения. Идеально подходит для 12-factor приложений, где настройки должны быть отделены от кода.

Установка

[dependencies]
envy = "0.4"
serde = { version = "1.0", features = ["derive"] }

Пример использования

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct AppConfig {
    #[serde(rename = "SERVER_HOST")]
    host: String,
    #[serde(rename = "SERVER_PORT")]
    port: u16,
    #[serde(rename = "DATABASE_URL")]
    db_url: String,
}

fn load_config() -> Result<AppConfig, envy::Error> {
    envy::from_env::<AppConfig>()
}

fn main() {
    match load_config() {
        Ok(config) => println!("Env config: {:?}", config),
        Err(e) => eprintln!("Envy error: {}", e),
    }
}

Для работы достаточно установить переменные окружения:

export SERVER_HOST=127.0.0.1
export SERVER_PORT=8080
export DATABASE_URL=postgres://user:pass@localhost/db

envy поддерживает вложенные структуры через разделители (например, DATABASE__HOST), а также опциональные поля с значением по умолчанию.

3. Библиотека dotenvy — загрузка .env файлов

dotenvy — это форк популярной библиотеки dotenv, предназначенный для загрузки переменных окружения из .env файлов. Особенно полезна при разработке, когда нужно быстро задать локальные настройки.

Установка

[dependencies]
dotenvy = "0.15"

Пример использования

use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Загружаем .env файл из текущей директории
    dotenvy::dotenv()?;

    // Теперь можно читать переменные стандартным способом
    let host = env::var("SERVER_HOST").unwrap_or_else(|_| "localhost".to_string());
    let port: u16 = env::var("SERVER_PORT")
        .unwrap_or_else(|_| "3000".to_string())
        .parse()?;

    println!("Server running on {}:{}", host, port);
    Ok(())
}

Содержимое .env файла:

SERVER_HOST=0.0.0.0
SERVER                    

Рекомендаций