Самый простой, но рискованный способ:
# «Классический» деплой по SSH
ssh user@server
cd /var/www/my-app
git pull origin main
npm install
npm run build
pm2 restart allПроблемы: человеческий фактор, забыл шаг, разные версии на серверах, нет отката.
Код попадает в production автоматически после прохождения CI:
Push → CI (тесты, линт, сборка) → ✅ → Auto Deploy
❌ → Остановка, уведомлениеДве идентичные среды: Blue (текущая) и Green (новая версия).
Трафик → [Blue v1.0] ← текущая production
[Green v1.1] ← новая версия, тестируется
# После проверки — переключаем трафик:
Трафик → [Green v1.1] ← теперь production
[Blue v1.0] ← можно откатиться мгновенноНовая версия раскатывается постепенно — сначала на 5% пользователей, потом 25%, потом 100%.
95% трафика → [v1.0]
5% трафика → [v1.1] ← наблюдаем за метриками
# Если всё хорошо:
0% трафика → [v1.0]
100% трафика → [v1.1]Development → Staging → Production
(dev) (stage) (prod)| Окружение | Назначение | Данные |
|-----------|------------|--------|
| Development | Локальная разработка | Моковые данные |
| Staging | Предпродакшн тестирование | Копия production данных |
| Production | Реальные пользователи | Реальные данные |
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to staging
run: ./deploy.sh staging
env:
API_URL: ${{ vars.API_URL }}
API_KEY: ${{ secrets.API_KEY }}
deploy-production:
runs-on: ubuntu-latest
environment: production
needs: deploy-staging
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to production
run: ./deploy.sh production
env:
API_URL: ${{ vars.API_URL }}
API_KEY: ${{ secrets.API_KEY }}GitHub Environments позволяют настроить ручное подтверждение деплоя. Для production можно потребовать approval от тимлида.
Vercel — платформа для деплоя фронтенд-приложений (Next.js, React, Vue).
1. Подключить GitHub репозиторий к Vercel
2. Каждый push в main → автоматический деплой в production
3. Каждый PR → preview deployment с уникальным URL
Push в main → https://my-app.vercel.app (production)
Push в feature → https://my-app-abc123.vercel.app (preview)name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g vercel
- name: Pull Vercel config
run: vercel pull --yes --token ${{ secrets.VERCEL_TOKEN }}
- name: Build
run: vercel build --prod --token ${{ secrets.VERCEL_TOKEN }}
- name: Deploy
run: vercel deploy --prebuilt --prod --token ${{ secrets.VERCEL_TOKEN }}Netlify — ещё одна популярная платформа для фронтенда.
name: Deploy to Netlify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v3
with:
publish-dir: './dist'
production-branch: main
deploy-message: 'Deploy from GitHub Actions'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}Docker — инструмент контейнеризации. Упаковывает приложение вместе со всеми зависимостями в контейнер, который одинаково работает везде.
# Этап 1: сборка
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Этап 2: production-сервер
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]# Собрать образ
docker build -t my-app .
# Запустить контейнер
docker run -p 3000:80 my-app
# Открыть http://localhost:3000name: Docker Build & Push
on:
push:
branches: [main]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: myuser/my-app:latestСекреты хранятся в Settings → Secrets and variables → Actions.
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}Правила безопасности:
.env файлыsteps:
- name: Build
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ vars.API_URL }}
NODE_ENV: productionVariables видны в логах, Secrets — замаскированы (***).
CI каждый раз стартует с чистого окружения. Без кэша npm install загружает все пакеты заново — это медленно.
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # автоматическое кэширование!
- run: npm cisteps:
- uses: actions/checkout@v4
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ hashFiles('package-lock.json') }}
restore-keys: |
node-modules-
- run: npm ciКлюч кэша основан на хэше package-lock.json. Если зависимости не менялись — используется кэш. Это ускоряет CI в 2–3 раза.
Preview deployment — временный деплой для каждого Pull Request. Позволяет тестировать изменения до мержа.
name: Preview Deploy
on:
pull_request:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- name: Deploy Preview
id: deploy
run: |
url=$(vercel deploy --token ${{ secrets.VERCEL_TOKEN }})
echo "url=$url" >> "$GITHUB_OUTPUT"
- name: Comment PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '🚀 Preview: ${{ steps.deploy.outputs.url }}'
})Теперь каждый PR получает комментарий со ссылкой на preview — ревьюер может проверить изменения вживую.
Деплой — это не финальный шаг. После выкатки нужно следить за приложением.
- name: Health check
run: |
sleep 30
response=$(curl -s -o /dev/null -w "%{http_code}" https://my-app.com/api/health)
if [ "$response" != "200" ]; then
echo "Health check failed with status $response"
exit 1
fi
echo "Health check passed"- name: Smoke test
id: smoke
continue-on-error: true
run: |
curl -f https://my-app.com || exit 1
- name: Rollback on failure
if: steps.smoke.outcome == 'failure'
run: |
echo "Smoke test failed, rolling back..."
vercel rollback --token ${{ secrets.VERCEL_TOKEN }}1. ✅ Линтинг (ESLint, Prettier) на каждый PR
2. ✅ TypeScript проверка (tsc --noEmit) на каждый PR
3. ✅ Тесты на каждый PR и push в main
4. ✅ Сборка проекта (npm run build)
5. ✅ Preview deploy для PR
6. ✅ Автодеплой в staging при мерже в develop
7. ✅ Автодеплой в production при мерже в main
8. ✅ Health check после деплоя
9. ✅ Мониторинг ошибок (Sentry)
10. ✅ Branch protection rules — CI обязателен для мержа
Деплой в production только после успешного CI
name: Deploy
on:
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
deploy:
runs-on: ubuntu-latest
needs: verify
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy script
run: ./deploy.sh productionДвухэтапный Dockerfile для frontend-приложения
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Самый простой, но рискованный способ:
# «Классический» деплой по SSH
ssh user@server
cd /var/www/my-app
git pull origin main
npm install
npm run build
pm2 restart allПроблемы: человеческий фактор, забыл шаг, разные версии на серверах, нет отката.
Код попадает в production автоматически после прохождения CI:
Push → CI (тесты, линт, сборка) → ✅ → Auto Deploy
❌ → Остановка, уведомлениеДве идентичные среды: Blue (текущая) и Green (новая версия).
Трафик → [Blue v1.0] ← текущая production
[Green v1.1] ← новая версия, тестируется
# После проверки — переключаем трафик:
Трафик → [Green v1.1] ← теперь production
[Blue v1.0] ← можно откатиться мгновенноНовая версия раскатывается постепенно — сначала на 5% пользователей, потом 25%, потом 100%.
95% трафика → [v1.0]
5% трафика → [v1.1] ← наблюдаем за метриками
# Если всё хорошо:
0% трафика → [v1.0]
100% трафика → [v1.1]Development → Staging → Production
(dev) (stage) (prod)| Окружение | Назначение | Данные |
|-----------|------------|--------|
| Development | Локальная разработка | Моковые данные |
| Staging | Предпродакшн тестирование | Копия production данных |
| Production | Реальные пользователи | Реальные данные |
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to staging
run: ./deploy.sh staging
env:
API_URL: ${{ vars.API_URL }}
API_KEY: ${{ secrets.API_KEY }}
deploy-production:
runs-on: ubuntu-latest
environment: production
needs: deploy-staging
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Deploy to production
run: ./deploy.sh production
env:
API_URL: ${{ vars.API_URL }}
API_KEY: ${{ secrets.API_KEY }}GitHub Environments позволяют настроить ручное подтверждение деплоя. Для production можно потребовать approval от тимлида.
Vercel — платформа для деплоя фронтенд-приложений (Next.js, React, Vue).
1. Подключить GitHub репозиторий к Vercel
2. Каждый push в main → автоматический деплой в production
3. Каждый PR → preview deployment с уникальным URL
Push в main → https://my-app.vercel.app (production)
Push в feature → https://my-app-abc123.vercel.app (preview)name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g vercel
- name: Pull Vercel config
run: vercel pull --yes --token ${{ secrets.VERCEL_TOKEN }}
- name: Build
run: vercel build --prod --token ${{ secrets.VERCEL_TOKEN }}
- name: Deploy
run: vercel deploy --prebuilt --prod --token ${{ secrets.VERCEL_TOKEN }}Netlify — ещё одна популярная платформа для фронтенда.
name: Deploy to Netlify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v3
with:
publish-dir: './dist'
production-branch: main
deploy-message: 'Deploy from GitHub Actions'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}Docker — инструмент контейнеризации. Упаковывает приложение вместе со всеми зависимостями в контейнер, который одинаково работает везде.
# Этап 1: сборка
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Этап 2: production-сервер
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]# Собрать образ
docker build -t my-app .
# Запустить контейнер
docker run -p 3000:80 my-app
# Открыть http://localhost:3000name: Docker Build & Push
on:
push:
branches: [main]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: myuser/my-app:latestСекреты хранятся в Settings → Secrets and variables → Actions.
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}Правила безопасности:
.env файлыsteps:
- name: Build
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ vars.API_URL }}
NODE_ENV: productionVariables видны в логах, Secrets — замаскированы (***).
CI каждый раз стартует с чистого окружения. Без кэша npm install загружает все пакеты заново — это медленно.
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # автоматическое кэширование!
- run: npm cisteps:
- uses: actions/checkout@v4
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ hashFiles('package-lock.json') }}
restore-keys: |
node-modules-
- run: npm ciКлюч кэша основан на хэше package-lock.json. Если зависимости не менялись — используется кэш. Это ускоряет CI в 2–3 раза.
Preview deployment — временный деплой для каждого Pull Request. Позволяет тестировать изменения до мержа.
name: Preview Deploy
on:
pull_request:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- name: Deploy Preview
id: deploy
run: |
url=$(vercel deploy --token ${{ secrets.VERCEL_TOKEN }})
echo "url=$url" >> "$GITHUB_OUTPUT"
- name: Comment PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '🚀 Preview: ${{ steps.deploy.outputs.url }}'
})Теперь каждый PR получает комментарий со ссылкой на preview — ревьюер может проверить изменения вживую.
Деплой — это не финальный шаг. После выкатки нужно следить за приложением.
- name: Health check
run: |
sleep 30
response=$(curl -s -o /dev/null -w "%{http_code}" https://my-app.com/api/health)
if [ "$response" != "200" ]; then
echo "Health check failed with status $response"
exit 1
fi
echo "Health check passed"- name: Smoke test
id: smoke
continue-on-error: true
run: |
curl -f https://my-app.com || exit 1
- name: Rollback on failure
if: steps.smoke.outcome == 'failure'
run: |
echo "Smoke test failed, rolling back..."
vercel rollback --token ${{ secrets.VERCEL_TOKEN }}1. ✅ Линтинг (ESLint, Prettier) на каждый PR
2. ✅ TypeScript проверка (tsc --noEmit) на каждый PR
3. ✅ Тесты на каждый PR и push в main
4. ✅ Сборка проекта (npm run build)
5. ✅ Preview deploy для PR
6. ✅ Автодеплой в staging при мерже в develop
7. ✅ Автодеплой в production при мерже в main
8. ✅ Health check после деплоя
9. ✅ Мониторинг ошибок (Sentry)
10. ✅ Branch protection rules — CI обязателен для мержа
Деплой в production только после успешного CI
name: Deploy
on:
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
deploy:
runs-on: ubuntu-latest
needs: verify
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy script
run: ./deploy.sh productionДвухэтапный Dockerfile для frontend-приложения
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Изучи материал выше и задай вопросы AI если что-то непонятно
Этот урок содержит теоретическую информацию. Изучи материал, затем отметь урок как пройденный.