В этой статье мы рассмотрим переменные окружения (environment variables). По сути, это пары ключ-значение набора данных, которые хранятся на уровне операционной системы.
В этой статье мы узнаем о переменных окружения в Node.js с примерами. Содержание:
-
Переменные окружения в операциях с базой данных / асинхронные задачи
-
Управление секретами и лучшие практики безопасности с примерами
Переменные окружения
Переменные окружения — это набор данных в виде пар ключ-значение, доступных на уровне операционной системы. Этот набор данных доступен во всех основных оболочках командной строки операционных систем Windows, Mac и Linux.
Почему переменные окружения важны?
-
Разделение проблем
-
Безопасность
-
Переносимость
-
Масштабируемость
-
Совместимость
-
Интероперабельность
Необходимые условия для этого проекта
Предполагается, что у вас есть:
-
Базовые знания Node.js
-
Базовые знания JavaScript
-
Некоторые знания о разработке бэкенда
Установка Node и настройка проекта
Установить Node.js на машину можно разными способами. Для начала нужно зайти на официальный сайт Node и скачать оттуда нужную версию.
Давайте рассмотрим установку Node.js в операционной системе Linux, предпочтительно Ubuntu
Шаг 1. Откройте терминал
Шаг 2. Используйте скрипт curl или wget для установки nvm, используя git-репозиторий nvm. Запустите скрипт для установки nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash # OR wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
Шаг 3. Закройте и снова откройте терминал и выполните следующие действия, чтобы применить скрипт
export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Шаг 4. Подтверждение установки
Убедиться, что NVM установлен в вашей системе, можно с помощью следующей команды:
nvm --version
*Шаг 5. * Установка Node
Введите следующую команду для установки последней версии node:
nvm install latest
или
nvm install --lts
Шаг 6. Установка версии по умолчанию
Чтобы установить версию Node, которая будет использоваться в вашей системе по умолчанию, используйте команду:
nvm alias default 20.8.0
Шаг 7. Проверка установки
Чтобы проверить, установлен ли Node, введите команду:
node -v # сообщает текущую версию node в вашей системе. В нашем случае это 20.8.0
Инициализация проекта
Теперь, когда мы установили Node, давайте создадим новый проект, в котором мы будем использовать переменную окружения.
Создайте новую директорию, назовите ее env-demo и перейдите в нее:
mkdir env-demo cd env-demo
Теперь введите команду для инициализации нового проекта и заполните поля по своему усмотрению.
npm init
package name: (env-demo) version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC)
В итоге будет создан файл package.json, который будет выглядеть примерно так:
{ "name": "env-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
Инициализация первой переменной окружения
Шаг 1: Установите пакет dotenv
Сейчас у вас инициализирован проект в приведенном выше разделе и создан файл package.json. Чтобы установить пакет node dotenv, который используется для создания env-файлов, введите в терминале команду:
npm install dotenv --save
Пакет dotenv будет установлен и сохранен как зависимость в файле package.json. Это должно выглядеть примерно так:
{ "name": "env-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "dotenv": "^16.3.1" } }
Шаг 2 Создание файла .env
-
В корневой папке создайте новый файл и назовите его
.env. -
Откройте его в текстовом редакторе и создайте несколько пар ключ-значение. Это ваши переменные окружения. Вот пример
DATABASE_URL=sample-database-url PORT=3000 SECRET_KEY=mysecretkey
Шаг 3. Загрузка и чтение переменных окружения
В корневой папке создайте файл index.js, затем откройте терминал и введите следующую команду для установки Express.js:
npm install express --save
Express будет установлен и сохранен в качестве зависимости в файле package.json. Файл package.json будет выглядеть следующим образом:
{ "name": "env-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "dotenv": "^16.3.1", "express": "^4.18.2" } }
и структура вашего проекта выглядит следующим образом:

Теперь откройте файл index.js и введите следующую команду, чтобы запустить простой веб-сервер.
const express = require('express'); const app = express(); const port = 4000; // defaults to 4000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Server running on http://localhost:${port}/`); });
запустите код с помощью
node index.js
и перейдите на localhost://4000, чтобы получить hello world

Загрузка и чтение файла .env
Теперь, когда сервер запущен, давайте прочитаем файл .env, который мы создали в предыдущем шаге, и загрузим данные о порте из файла .env.
Откроем файл index.js и «потребуем» там библиотеку dotenv:
require('dotenv').config()
Теперь вы можете получить доступ к файлу .env с помощью process.env. Давайте воспользуемся process.env для доступа к номеру порта в файле index.js:
const express = require('express'); require('dotenv').config() const app = express(); const port = process.env.PORT || 4000; // Read from .env if not available then defaults to 4000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Server running on http://localhost:${port}/`); });
Теперь давайте перезапустим сервер и перейдем на localhost://3000. Вместо того, чтобы работать на 4000, наш сервер теперь работает на порту 3000, который он взял из файла .env
Вы также можете увидеть это в консоли:

Итак, вы успешно создали и сохранили файл env на своей машине.
В качестве другого примера вы можете получить доступ к DATABASE_URL следующим образом:
const dbUrl = process.env.DATABASE_URL; // Use dbUrl to connect to your database
Вот все файлы
index.js
const express = require('express'); require('dotenv').config() const app = express(); const port = process.env.PORT || 4000; // Read from .env if not available then defaults to 4000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Server running on http://localhost:${port}/`); });
package.json
{ "name": "env-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "dotenv": "^16.3.1", "express": "^4.18.2" } }
.env
DATABASE_URL=sample-database-url PORT=3000 SECRET_KEY=mysecretkey
Как использовать переменные окружения в асинхронных задачах
В этом разделе мы поговорим о том, как переменные окружения можно использовать в асинхронных задачах, таких как вызов API или операции с базой данных.
Переменные окружения особенно важны в этих задачах, потому что их можно использовать для безопасного хранения учетных данных и конечных точек.
Кроме того, эти переменные можно автоматизировать, поскольку они меняются в разных средах, таких как разработка, стейджинг и продакшен.
Шаг 1. Настройка переменных окружения
Откройте файл .env и отредактируйте его следующим образом:
API_URL=https://jsonplaceholder.typicode.com/todos/1 API_KEY=sfjks4325 PORT=3000
Шаг 2. Использование async / await с переменными окружения
Далее установите библиотеку axios, чтобы выполнять вызовы на удаленный сервер:
npm install axios --save
Эта команда установит axios и сохранит ее как зависимость в файле package.json.
Файл package.json должен выглядеть примерно так:
{ "name": "env-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "axios": "^1.5.1", "dotenv": "^16.3.1", "express": "^4.18.2" } }
Далее используйте axios для выполнения вызовов сайта jsonplaceholder и записи их в консоль.
Введите этот код в файл index.js
const express = require('express'); require('dotenv').config(); const axios = require('axios'); const app = express(); const port = process.env.PORT || 4000; // Read from .env if not available then defaults to 4000 const fetchData = async () => { const url = process.env.API_URL; const apiKey = process.env.API_KEY; try { const response = await axios.get(url, { headers: { 'Authorization': `Bearer ${apiKey}` } }); console.log(response.data); } catch (error) { console.error(`Error fetching data: ${error}`); } }; app.get('/', (req, res) => { fetchData() res.send('Hello World!') }) app.listen(port, () => { console.log(`Server running on http://localhost:${port}/`); });
Что мы здесь делаем:
-
Импортируем модули
express,dotenv,axios. -
Затем инициализируем приложение и порт с помощью переменных окружения.
-
Затем создаем асинхронную функцию
const fetchData = async ()=> (...) -
В этой функции мы используем url и apiKey из файла
.env. Хотя я должен отметить, что вам не нужен apiKey для вызова сайта jsonplaceholder. Я просто поместил этот ключ для демонстрации. -
Записываем данные в консоль.
-
Вызываем метод
fetchData()на маршруте get. Таким образом, каждый раз, когда кто-то переходит на/, вызывается метод и данные записываются в консоль.
Использование Async/await с переменными окружения в операциях с базой данных
Давайте рассмотрим еще один пример. На этот раз мы будем выполнять операции с базой данных с помощью переменных окружения.
Шаг 1: Настройка переменных окружения.
Откройте файл .env в текстовом редакторе и введите следующее:
DB_HOST=localhost DB_PORT=5432 DB_NAME=mydatabase DB_USER=username DB_PASSWORD=password
Шаг 2: Установите библиотеку pg
Следующим шагом будет установка библиотеки pg:
npm install pg --save
*Шаг 3: * Подключитесь к базе данных и выполните асинхронный запрос с помощью файла .env
Напишите следующий код, чтобы подключиться к базе данных и использовать учетные данные .env, которые мы только что создали:
const { Pool } = require('pg'); require('dotenv').config(); const pool = new Pool({ host: process.env.DB_HOST, port: process.env.DB_PORT, database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD }); const fetchUsers = async () => { try { const res = await pool.query('SELECT * FROM users'); console.log(res.rows); } catch (err) { console.error(`Error fetching users: ${err}`); } }; fetchUsers();
Мы не интегрируем этот пример в нашу обычную кодовую базу, потому что он является исключением и не будет полезен в дальнейшем в этом руководстве.
Расширенные возможности работы с переменными окружения в Node JS: кодирование, валидация и преобразование типов
Переменные окружения — это не только чтение и хранение. С помощью расширенных манипуляций с переменными окружения мы узнаем о:
-
кодировании
-
валидации и
-
преобразовании типов
1. Кодирование
Кодирование используется для различных целей в переменных окружения, в том числе для обеспечения безопасности. Наиболее популярный тип кодировки — base64.
Кодирование:
const decodedData = Buffer.from(encodedData, 'base64').toString('utf-8'); console.log(`Decoded: ${decodedData}`);
2. Валидация
Валидация используется для проверки того, является ли код правильным или нет. Например, url, который вы собираетесь использовать — является ли он корректным или нет и т.д.
Или, как в этом примере, мы проверяем, находится ли номер порта в указанном диапазоне или нет.
const validatePort = (port) => { const parsedPort = parseInt(port, 10); if (isNaN(parsedPort) || parsedPort < 1024 || parsedPort > 65535) { throw new Error('Invalid port number'); } return parsedPort; }; const port = validatePort(process.env.PORT);
3. Преобразование типа
Переменные окружения всегда имеют тип string. Но часто возникает необходимость использовать и другие типы данных, например int или booleans. Здесь поможет преобразование типов.
Пример целого числа:
const isProduction = process.env.NODE_ENV === 'production'; const retries = parseInt(process.env.RETRIES, 10) || 3;
Пример булевого значения
const shouldLog = process.env.SHOULD_LOG === 'true';
Комбинированный пример
Вот пример, объединяющий все расширенные манипуляции с env, доступные в переменных окружения.
// Encoding and decoding const apiKey = Buffer.from(process.env.API_KEY || '', 'base64').toString('utf-8'); // Validation if (apiKey.length !== 32) { throw new Error('Invalid API key length'); } // Type conversion const maxUsers = parseInt(process.env.MAX_USERS, 10); if (isNaN(maxUsers)) { throw new Error('MAX_USERS must be an integer'); }
Управление секретами и лучшие практики безопасности с примерами
В этом разделе мы узнаем об управлении секретами и лучших практиках безопасности с примерами. Вот шаги, которые вы можете предпринять для защиты переменной окружения, а также их примеры.
1. Никогда не делайте коммит файлов .env
Всегда следите за тем, чтобы файлы .env находились в gitignore и никогда не коммитились в git-репозиторий.
# Ignore dotenv environment variables file .env
2. Хеширование пароля
Всегда хэшируйте пароли, хранение паролей в виде обычного текста — плохая практика. Для хэширования паролей можно использовать, например, библиотеку bcryt.
const bcrypt = require('bcrypt'); const saltRounds = 10; async function hashPassword(plainPassword) { const hash = await bcrypt.hash(plainPassword, saltRounds); return hash; }
3. Кодирование переменных окружения
В качестве меры безопасности всегда кодируйте секреты, обычно они имеют кодировку base-64.
const buffer = Buffer.from(process.env.MY_SECRET, 'base64'); const decodedSecret = buffer.toString('utf-8');
4. Централизованное управление секретами
Для крупных проектов можно рассмотреть сервисы централизованного управления секретами — например, hashicorp vault, AWS secrets manager.
Они предлагают такие расширенные функции, как ротация секретов, автоматическая аренда и ротация, а также ведение журнала аудита.
Вот пример с node vault:
const vault = require("node-vault")({ endpoint: "https://vault-endpoint", token: process.env.VAULT_TOKEN, }); async function getDatabaseCreds() { const data = await vault.read("path/to/secret"); return { user: data.data.username, password: data.data.password, }; }
5. Принцип наименьших привилегий
Всегда следуйте принципу наименьших привилегий. API, которые не требуют идентификационных данных на запись, никогда не должны получать привилегии на запись.
Подводные камни
-
Хардкодинг служебной информации
-
Отсутствие валидации
-
Игнорирование окружения
-
Неадекватная безопасность
-
Плохая документация
-
Возврат в предыдущее значение (Fallback) по умолчанию
Нужен Chat API для вашего сайта или приложения
Поставщиком Chat API является DeadSimpleChat
-
Добавьте масштабируемый чат в приложение за считанные минуты
-
Одновременно 10 миллионов пользователей
-
Uptime 99,999%
-
Фичи модерации
-
Чат 1-1
-
Групповой чат
-
Полностью настраиваемый
-
Чат API и SDK
-
Предварительно созданный чат
Заключение
В этой статье мы узнали о переменных окружения и о том, как их использовать в Node.js.
Мы рассмотрели важные темы, связанные с управлением переменными окружения в Node.js. Этого должно быть достаточно для большинства случаев использования переменных окружения в приложениях Node.js.
Надеюсь, вам понравилась статья, и спасибо за чтение.
Всех разработчиков на JavaScript приглашаем на открытое занятие в OTUS «Построение графических приложений с применением библиотеки Konva.js». Записаться на урок можно на странице курса.
ссылка на оригинал статьи https://habr.com/ru/articles/779852/
Добавить комментарий