10. AWS: EC2 и S3

AWS — крупнейший облачный провайдер. EC2 — виртуальные серверы, S3 — хранилище файлов. Базовые сервисы для любого бекенда.
Основные сервисы AWS для разработчика
Заголовок раздела «Основные сервисы AWS для разработчика»EC2 — виртуальные серверы (VPS)S3 — хранение файлов (объектное хранилище)RDS — managed БД (PostgreSQL, MySQL)Lambda — serverless функцииECS/EKS — контейнерыCloudFront — CDNRoute53 — DNSIAM — управление доступомEC2: виртуальный сервер
Заголовок раздела «EC2: виртуальный сервер»Запуск EC2 инстанса
Заголовок раздела «Запуск EC2 инстанса»# AWS CLIaws ec2 run-instances \ --image-id ami-0c55b159cbfafe1f0 \ # Ubuntu 22.04 --instance-type t3.micro \ --key-name my-keypair \ --security-group-ids sg-xxxxxxxx \ --subnet-id subnet-xxxxxxxx \ --count 1 \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=myapp}]'Подключение по SSH
Заголовок раздела «Подключение по SSH»# Скачать key pair (.pem файл) при созданииchmod 400 my-keypair.pem
# Подключение
# Или через Instance Connect (в браузере)# EC2 Console → выбрать instance → Connect → EC2 Instance ConnectНастройка сервера (Ubuntu 22.04)
Заголовок раздела «Настройка сервера (Ubuntu 22.04)»# Обновление системыsudo apt update && sudo apt upgrade -y
# Установка Node.js (через nvm)curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bashsource ~/.bashrcnvm install 20nvm use 20
# Установка PM2npm install -g pm2
# Установка Nginxsudo apt install nginx -ysudo systemctl enable nginxsudo systemctl start nginx
# Firewallsudo ufw allow OpenSSHsudo ufw allow 'Nginx Full'sudo ufw enableSecurity Groups — firewall EC2
Заголовок раздела «Security Groups — firewall EC2»# Создание группы безопасностиaws ec2 create-security-group \ --group-name myapp-sg \ --description "MyApp Security Group"
# Разрешить SSH (22)aws ec2 authorize-security-group-ingress \ --group-id sg-xxxxxxxx \ --protocol tcp \ --port 22 \ --cidr 0.0.0.0/0 # лучше только твой IP: $(curl -s ifconfig.me)/32
# Разрешить HTTP (80) и HTTPS (443)aws ec2 authorize-security-group-ingress \ --group-id sg-xxxxxxxx \ --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \ --group-id sg-xxxxxxxx \ --protocol tcp \ --port 443 \ --cidr 0.0.0.0/0Elastic IP — статический IP
Заголовок раздела «Elastic IP — статический IP»# Выделить Elastic IPaws ec2 allocate-address --domain vpc
# Привязать к инстансуaws ec2 associate-address \ --instance-id i-xxxxxxxxxxxxxxxxx \ --allocation-id eipalloc-xxxxxxxxxxxxxxxxxS3: хранилище файлов
Заголовок раздела «S3: хранилище файлов»Базовые операции
Заголовок раздела «Базовые операции»# Создание bucketaws s3 mb s3://my-bucket-name --region eu-west-1
# Загрузка файловaws s3 cp file.jpg s3://my-bucket-name/aws s3 cp ./dist/ s3://my-bucket-name/static/ --recursive
# Скачиваниеaws s3 cp s3://my-bucket-name/file.jpg ./file.jpgaws s3 sync s3://my-bucket-name/backup/ ./backup/
# Список файловaws s3 ls s3://my-bucket-name/
# Удалениеaws s3 rm s3://my-bucket-name/file.jpgaws s3 rm s3://my-bucket-name/ --recursiveS3 в Node.js приложении
Заголовок раздела «S3 в Node.js приложении»npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presignerimport { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const s3 = new S3Client({ region: process.env.AWS_REGION || 'eu-west-1', credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, },});
// Загрузка файлаasync function uploadFile(key: string, body: Buffer, contentType: string) { await s3.send(new PutObjectCommand({ Bucket: process.env.S3_BUCKET!, Key: key, Body: body, ContentType: contentType, }));
return `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${key}`;}
// Presigned URL для прямой загрузки с клиентаasync function getPresignedUploadUrl(key: string, contentType: string) { const command = new PutObjectCommand({ Bucket: process.env.S3_BUCKET!, Key: key, ContentType: contentType, });
return getSignedUrl(s3, command, { expiresIn: 3600 }); // 1 час}
// Presigned URL для чтения приватного файлаasync function getPresignedDownloadUrl(key: string) { const command = new GetObjectCommand({ Bucket: process.env.S3_BUCKET!, Key: key, });
return getSignedUrl(s3, command, { expiresIn: 300 }); // 5 минут}
// Удалениеasync function deleteFile(key: string) { await s3.send(new DeleteObjectCommand({ Bucket: process.env.S3_BUCKET!, Key: key, }));}S3 для статического сайта
Заголовок раздела «S3 для статического сайта»# 1. Включить static website hostingaws s3 website s3://my-static-site/ \ --index-document index.html \ --error-document 404.html
# 2. Сделать bucket публичным (bucket policy)aws s3api put-bucket-policy \ --bucket my-static-site \ --policy '{ "Version": "2012-10-17", "Statement": [{ "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::my-static-site/*" }] }'
# 3. Деплой сайтаnpm run buildaws s3 sync ./dist s3://my-static-site/ --delete
# URL: http://my-static-site.s3-website-eu-west-1.amazonaws.comIAM: управление доступом
Заголовок раздела «IAM: управление доступом»# Создать пользователя для CI/CDaws iam create-user --user-name github-actions-deploy
# Создать ключи доступаaws iam create-access-key --user-name github-actions-deploy# Сохрани AccessKeyId и SecretAccessKey → в GitHub Secrets
# Минимальные права для S3 деплояaws iam put-user-policy \ --user-name github-actions-deploy \ --policy-name s3-deploy \ --policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:PutObject", "s3:DeleteObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ] }] }'GitHub Actions + S3 деплой
Заголовок раздела «GitHub Actions + S3 деплой»name: Deploy to S3
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: node-version: '20'
- run: npm ci && npm run build
- name: Deploy to S3 uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: eu-west-1
- run: aws s3 sync ./dist s3://${{ secrets.S3_BUCKET }} --deleteКлючевые моменты
Заголовок раздела «Ключевые моменты»- EC2 — виртуальный сервер, полный контроль
- Security Groups — firewall для EC2, разрешай только нужные порты
- Elastic IP — статический IP для EC2
- S3 — объектное хранилище, идеально для файлов и статики
- Presigned URLs — безопасная загрузка/скачивание без прямого доступа к AWS
- IAM — минимальные права (principle of least privilege)
- AWS SDK v3 — модульный, тряски дерева, рекомендуется
Интерактивный пример
Заголовок раздела «Интерактивный пример»Основные сервисы AWS и их связи: