Готовые к копированию рецепты для самых частых проектов. Каждый — это Dockerfile, inquir.yaml и пара команд: положите файлы в папку проекта, разверните, откройте адрес. Сборка идёт на Inquir, Docker на компьютере не нужен. Каждый рецепт на этой странице развёрнут на Inquir Compute ровно в таком виде.
Что написано в inquir.yaml: на каком порту слушает приложение, какой адрес отвечает, когда оно работает (проверка работоспособности), и сколько ему CPU и памяти. Сервис всегда называется web. Порт в inquir.yaml должен совпадать с портом, который слушает ваш сервер или nginx: если меняете одно, поменяйте и другое.
Выберите рецепт:
- Сайт на React (Vite)
- Статический HTML-сайт
- API на Node.js (Express)
- API на Python (FastAPI)
- Подключить базу Postgres
Сайт на React (Vite)#
Приложение на React, собранное Vite и отдаваемое nginx. Результат: сайт по адресу https://my-site-xxxxxx.apps.inquir.org с HTTPS; ссылки вида /about открываются напрямую, файлы сжимаются и кешируются браузером. Нужно: Node.js 20.19+ на компьютере — только чтобы создать проект; сам сайт собирается на Inquir.
Полный пример: inquir-examples/static-react-vite на GitHub.
1. Создайте проект
# Skip this if you already have a React project npm create vite@9.2.1 my-site -- --template react cd my-site npm install
2. Добавьте три файла рядом с package.json
Копируйте как есть. Менять может понадобиться только порт (8080 во всех трёх файлах) и папку сборки, если проект собирается не в dist/.
my-site/ ├── Dockerfile ← new ├── nginx.conf ← new ├── inquir.yaml ← new ├── package.json ├── package-lock.json ├── index.html └── src/
# Step 1: build the site with Node.js FROM node:22.23.4-alpine@sha256:fe4f6d74e20370acb04ad889077d14d0f64a9c8ea6a42bc60cddf1e844699914 AS build WORKDIR /app COPY package*.json ./ RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi COPY . . # Vite writes the finished site to dist/ RUN npm run build # Step 2: serve the finished files with nginx (runs as a regular user, port 8080) FROM nginxinc/nginx-unprivileged:1.30.6-alpine@sha256:f5116ed4606f3eb015dd4a8e28cb9b351476dc0ad4bc6e9f93b19cec130cdf03 COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/dist/ /usr/share/nginx/html/ EXPOSE 8080
server { listen 8080; # the same port as runtime.port in inquir.yaml server_name _; root /usr/share/nginx/html; index index.html; absolute_redirect off; # Compress text files. gzip_proxied is needed: requests reach nginx through a proxy. gzip on; gzip_proxied any; gzip_vary on; gzip_types text/css application/javascript text/javascript application/json image/svg+xml text/plain; # Health check: the platform calls it before sending visitors to a new version. location = /healthz { access_log off; default_type text/plain; return 200 "ok\n"; } # Files in /assets/ have a hash in their names: browsers may keep them for a year. location /assets/ { add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # Any other path: the file if it exists, otherwise index.html (React Router links work). location / { add_header Cache-Control "no-cache"; try_files $uri $uri/ /index.html; } }
version: 1 services: web: # always "web" runtime: port: 8080 # the port nginx listens on (nginx.conf) healthcheck: type: http path: /healthz resources: # plenty for a static site cpuVCpus: 0.25 memoryMb: 128
3. Разверните
Из терминала. Вместо my-site можно взять любое имя — оно войдёт в адрес.
# In the my-site folder inquir apps create my-site --ingress public # once: a new app with a public address inquir apps deploy my-site --promote # build, start, then send visitors to it # Build succeeded in 34692ms # Release ef51e99f is serving # Production now serves ef51e99f # https://my-site-2mk7b4.apps.inquir.org <- your site # After every change: the same command inquir apps deploy my-site --promote
Из консоли, через GitHub.
- Отправьте проект вместе с новыми файлами в репозиторий GitHub.
- В консоли откройте Приложения, откройте проект (или создайте его кнопкой Новый проект) и выберите Создать → Репозиторий GitHub. В первый раз нажмите Подключить GitHub и разрешите доступ к репозиторию.
- Выберите репозиторий и укажите Внутренний HTTP-порт
8080. Ветку, корневую директорию и путь к Dockerfile оставьте как есть, если файлы лежат в корне репозитория. - Нажмите Развернуть приложение. Inquir соберёт проект и запустит его; каждый push в эту ветку разворачивается снова.
- Дайте публичный адрес: в приложении откройте Настройки → Сеть → Публичный доступ и нажмите Создать адрес.
Откройте сайт. Адрес печатается в конце развёртывания и виден в разделе Настройки → Сеть. Должна открыться стартовая страница Vite + React; /healthz отвечает ok.
Свой домен. Привяжите его из терминала (ниже) или в разделе Настройки → Сеть, добавьте две показанные DNS-записи там, где купили домен, и подтвердите — HTTPS выпустится автоматически. Подробно: Собственные домены.
# Prints two DNS records to add where you bought the domain inquir apps domain my-site www.example.com # Once the records are live: the site answers on your domain, with HTTPS inquir apps domain my-site www.example.com --verify
Если что-то не работает
- Сборка падает на
npm ci.package-lock.jsonне совпадает сpackage.json: выполнитеnpm installу себя и разверните снова. Если сборка упала, команда подскажет, как открыть её журнал. - Развёртывание ждёт, а потом не проходит проверку работоспособности. Порт должен совпадать везде:
listenв nginx.conf,portв inquir.yaml и, для GitHub, Внутренний HTTP-порт. - Страница открывается из меню, но после обновления — 404. В nginx.conf нет последнего блока (
try_files … /index.html) или он изменён. - Адрес не открывается. Приложение приватно, пока у него нет публичного адреса:
inquir apps update <app> --ingress publicили Создать адрес в разделе «Настройки → Сеть».
Подробнее
Кеширование. Vite складывает JS и CSS в /assets/ с хешем в имени каждого файла, поэтому браузеры могут хранить их год. index.html отдаётся с no-cache, и посетители видят новую версию сразу после развёртывания.
Сжатие. Оставьте gzip_proxied any: запросы приходят к nginx через прокси платформы, и без этой строки nginx отдаёт файлы несжатыми.
Create React App. Те же файлы; в Dockerfile замените /app/dist/ на /app/build/, а в nginx.conf — /assets/ на /static/.
Next.js как статический сайт. Добавьте output: 'export' в next.config, в Dockerfile замените /app/dist/ на /app/out/, а в nginx.conf — /assets/ на /_next/static/ и последний try_files на $uri $uri.html $uri/ /index.html. Приложение Next.js с серверным рендерингом или API-маршрутами — не статический сайт: оно работает как Node.js-сервер, как в рецепте API на Node.js.
Настройки, которые вшиваются при сборке (VITE_*). Vite записывает значения VITE_* в файлы во время сборки, поэтому переменные запущенного приложения до них не доходят. Укажите их в build.args в inquir.yaml и передайте через Dockerfile:
# inquir.yaml: values baked into the site at build time version: 1 services: web: build: args: VITE_API_URL: https://api.example.com runtime: port: 8080 healthcheck: { type: http, path: /healthz } # Dockerfile, in step 1 before "RUN npm run build": ARG VITE_API_URL ENV VITE_API_URL=$VITE_API_URL
Статический HTML-сайт#
Самый короткий способ выложить HTML, CSS и JavaScript: nginx отдаёт вашу папку public/. Нужны только файлы.
Полный пример: inquir-examples/static-html на GitHub.
1. Положите сайт в public/ и добавьте два файла
Ничего менять не нужно, если только вы не переименуете папку public/ (тогда поменяйте её и в Dockerfile).
my-page/ ├── Dockerfile ├── inquir.yaml └── public/ ← your site: index.html, CSS, images, JS ├── index.html └── style.css
# nginx that runs as a regular user and listens on port 8080 FROM nginxinc/nginx-unprivileged:1.30.6-alpine@sha256:f5116ed4606f3eb015dd4a8e28cb9b351476dc0ad4bc6e9f93b19cec130cdf03 # Your site: everything in the public/ folder COPY public/ /usr/share/nginx/html/ EXPOSE 8080
version: 1 services: web: # always "web" runtime: port: 8080 # nginx listens here healthcheck: type: http path: / # the home page must answer resources: cpuVCpus: 0.25 memoryMb: 128
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>My site</title> <link rel="stylesheet" href="/style.css" /> </head> <body> <h1>Hello from Inquir Compute</h1> <p>Edit public/index.html and deploy again.</p> </body> </html>
2. Разверните
Из терминала. Вместо my-site можно взять любое имя — оно войдёт в адрес.
# In the my-page folder inquir apps create my-page --ingress public inquir apps deploy my-page --promote # https://my-page-6w79j4.apps.inquir.org <- your site
Из консоли, без GitHub.
- В консоли откройте Приложения и нажмите Создать в браузере. Введите Название приложения и нажмите Создать приложение — откроется редактор в браузере.
- Создайте в редакторе файлы из этого рецепта и вставьте их содержимое.
- Нажмите Развернуть на нижней панели. Inquir соберёт файлы и запустит сайт.
- Дайте публичный адрес: в приложении откройте Настройки → Сеть → Публичный доступ и нажмите Создать адрес.
Откройте сайт по напечатанному адресу. Чтобы изменить его, поправьте файлы и разверните снова.
Свой домен. Привяжите его из терминала (ниже) или в разделе Настройки → Сеть, добавьте две показанные DNS-записи там, где купили домен, и подтвердите — HTTPS выпустится автоматически. Подробно: Собственные домены.
Если что-то не работает
- Развёртывание не проходит проверку работоспособности. Проверка открывает главную страницу, поэтому
public/index.htmlдолжен существовать. - Одна страница отдаёт 404. На сервере имена файлов различают регистр:
About.htmlиabout.html— разные файлы. - Адрес не открывается. Приложение приватно, пока у него нет публичного адреса:
inquir apps update <app> --ingress publicили Создать адрес в разделе «Настройки → Сеть».
Подробнее
Нужны сжатие, долгое кеширование или одностраничное приложение со своими маршрутами? Возьмите nginx.conf из рецепта для React, добавьте в Dockerfile COPY nginx.conf /etc/nginx/conf.d/default.conf и укажите путь проверки /healthz.
API на Node.js (Express)#
API на Express, который слушает порт из переменной PORT — её задаёт Inquir. Результат: https://my-api-xxxxxx.apps.inquir.org/api/hello. Fastify или Hono — так же: Dockerfile тот же, меняется CMD.
Полный пример: inquir-examples/node-api на GitHub.
1. Проект: четыре файла
Выполните npm install один раз, чтобы появился package-lock.json и каждая сборка ставила те же версии. Порт задаётся в inquir.yaml — Inquir передаёт его приложению в PORT; 3000 в server.js — только значение по умолчанию для запуска на своём компьютере.
{ "name": "my-api", "private": true, "type": "module", "scripts": { "start": "node server.js" }, "dependencies": { "express": "^5.2.1" } }
import express from 'express'; const app = express(); app.use(express.json()); // Health check: the platform calls it before sending traffic to a new version. app.get('/healthz', (req, res) => res.send('ok')); app.get('/api/hello', (req, res) => { res.json({ message: 'Hello from Inquir Compute', time: new Date().toISOString() }); }); // The platform sets PORT to runtime.port from inquir.yaml. const port = Number(process.env.PORT) || 3000; const server = app.listen(port, () => console.log(`listening on ${port}`)); // Finish open requests before a new version replaces this one. process.on('SIGTERM', () => server.close(() => process.exit(0)));
FROM node:22.23.4-alpine@sha256:fe4f6d74e20370acb04ad889077d14d0f64a9c8ea6a42bc60cddf1e844699914 WORKDIR /app ENV NODE_ENV=production COPY package*.json ./ RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi COPY . . # Run as the regular "node" user that the image ships with USER node EXPOSE 3000 CMD ["node", "server.js"]
version: 1 services: web: # always "web" runtime: port: 3000 # the port server.js listens on healthcheck: type: http path: /healthz resources: cpuVCpus: 0.25 memoryMb: 256
2. Разверните и вызовите
# In the my-api folder (npm install once, so package-lock.json exists) inquir apps create my-api --ingress public inquir apps deploy my-api --promote curl https://my-api-88n5um.apps.inquir.org/api/hello # {"message":"Hello from Inquir Compute","time":"2026-10-22T18:16:37.443Z"}
Из консоли: те же шаги, что для сайта на React, — GitHub с Внутренним HTTP-портом 3000 или Создать в браузере с этими файлами.
Если что-то не работает
- Развёртывание не проходит проверку работоспособности. Сервер должен слушать
PORTна всех адресах:app.listen(port), а неapp.listen(port, 'localhost'). - Приложение запускается и останавливается. Посмотрите, что оно напечатало:
inquir apps logs <app> --tail 100. Если не найден пакет — его нет в файле зависимостей. - Адрес не открывается. Приложение приватно, пока у него нет публичного адреса:
inquir apps update <app> --ingress publicили Создать адрес в разделе «Настройки → Сеть».
API на Python (FastAPI)#
Приложение на FastAPI под uvicorn. Результат: https://my-api-xxxxxx.apps.inquir.org/api/hello и интерактивная документация API на /docs.
Полный пример: inquir-examples/python-fastapi на GitHub.
1. Проект: четыре файла
Новые пакеты добавляйте в requirements.txt с точной версией. Порт задаётся в inquir.yaml; Dockerfile читает его из PORT.
fastapi==0.141.1 uvicorn[standard]==0.54.0
from datetime import datetime, timezone from fastapi import FastAPI app = FastAPI() # Health check: the platform calls it before sending traffic to a new version. @app.get("/healthz") def healthz(): return {"ok": True} @app.get("/api/hello") def hello(): return {"message": "Hello from Inquir Compute", "time": datetime.now(timezone.utc).isoformat()}
FROM python:3.12.15-slim@sha256:cb33f7f771ecec2ef1225cf39b159591a040391bd73e4c01f00fdfc4c47611d2 ENV PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1 PIP_DISABLE_PIP_VERSION_CHECK=1 WORKDIR /app COPY requirements.txt ./ RUN pip install -r requirements.txt COPY . . # Run as a regular user, not root RUN useradd --create-home --uid 10001 app USER app EXPOSE 8000 # The platform sets PORT to runtime.port from inquir.yaml CMD ["sh", "-c", "exec uvicorn main:app --host 0.0.0.0 --port ${PORT:-8000} --proxy-headers --forwarded-allow-ips='*'"]
version: 1 services: web: # always "web" runtime: port: 8000 # the port uvicorn listens on healthcheck: type: http path: /healthz resources: cpuVCpus: 0.25 memoryMb: 256
2. Разверните и вызовите
# In the my-api folder inquir apps create my-api --ingress public inquir apps deploy my-api --promote curl https://my-api-uqprbk.apps.inquir.org/api/hello # {"message":"Hello from Inquir Compute","time":"2026-10-22T18:16:43.033814+00:00"}
Из консоли: те же шаги, что для сайта на React, — GitHub с Внутренним HTTP-портом 8000 или Создать в браузере с этими файлами.
Если что-то не работает
- Развёртывание не проходит проверку работоспособности. uvicorn должен слушать
--host 0.0.0.0, как в Dockerfile; адрес по умолчанию127.0.0.1недоступен снаружи контейнера. - Приложение запускается и останавливается. Посмотрите, что оно напечатало:
inquir apps logs <app> --tail 100. Если не найден пакет — его нет в файле зависимостей. - Адрес не открывается. Приложение приватно, пока у него нет публичного адреса:
inquir apps update <app> --ingress publicили Создать адрес в разделе «Настройки → Сеть».
Подробнее
Flask или Django. Dockerfile тот же, последняя строка — gunicorn: CMD ["sh", "-c", "exec gunicorn app:app --bind 0.0.0.0:${PORT:-8000}"] (для Django — myproject.wsgi вместо app:app), и gunicorn в requirements.txt.
Подключить базу Postgres#
Любой из рецептов API получает базу Postgres за несколько шагов. База приватная: к ней подключаются только ваши приложения, а пароль не появляется в терминале. В пробный период помещается одна база.
1. Используйте DATABASE_URL в коде
Добавьте драйвер и обработчик, который берёт адрес из переменной DATABASE_URL:
// npm install pg import pg from 'pg'; const db = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 5 }); app.get('/api/db', async (req, res) => { const { rows } = await db.query('select now() as now, version() as version'); res.json(rows[0]); });
# requirements.txt: psycopg[binary]==3.3.6 import os import psycopg @app.get("/api/db") def db_time(): with psycopg.connect(os.environ["DATABASE_URL"]) as conn: now, version = conn.execute("select now(), version()").fetchone() return {"now": now.isoformat(), "version": version}
2. Создайте базу и подключите её к приложению
# A Postgres 16 database with its own disk, in the same project as my-api # (inquir apps create my-api printed the project's name) inquir apps create my-db --template postgres --project <project> # Hand my-api the address: DATABASE_URL appears in its variables. # "no verified private address yet"? Wait a minute and run it again. inquir apps connect my-db my-api
3. Разверните новый код
# In the my-api folder: the new code picks DATABASE_URL up inquir apps deploy my-api --promote curl https://my-api-88n5um.apps.inquir.org/api/db # {"now":"2026-10-22T18:21:23.413Z","version":"PostgreSQL 16.15 on x86_64-pc-linux-musl, ..."} # Later, after changing only a variable (not the code): inquir apps redeploy my-api
В консоли: на холсте проекта выберите Создать → База данных, тип postgres, и нажмите Создать базу данных. Когда она запустится, откройте её вкладку База данных, нажмите Подключиться и скопируйте строку Приватный (Внутри сети Inquir). Затем откройте свой API, на вкладке Переменные добавьте DATABASE_URL с этим значением, сохраните и разверните новый код (push в GitHub или Развернуть заново, если код уже там).
Если что-то не работает
- connect отвечает «no verified private address yet». База ещё запускается: подождите минуту и повторите команду.
Дальше: пошаговое руководство объясняет предварительные версии, перевод в продакшен и откат; Контейнерные приложения — всё, что умеют inquir.yaml и консоль.