Агент пишет Dockerfile, оптимизирует образы и чинит контейнеры — Docker перестаёт быть загадкой
composer.json — посмотрю какие PHP-расширения нужны для Dockerfile.storage:link создаёт симлинк public/storage → storage/app/public. В Docker:# docker-compose.yml
services:
app:
volumes:
- storage:/var/www/storage # персистентный volume
# ...
volumes:
storage: # данные сохраняются между деплоями
# entrypoint.sh
#!/bin/sh
# Создать структуру storage если пустой volume
mkdir -p storage/app/public storage/framework/{cache,sessions,views} storage/logs
chmod -R 775 storage
chown -R www-data:www-data storage
# Симлинк — каждый раз при старте
php artisan storage:link --force
# Миграции
php artisan migrate --force
exec "$@"
storage:link --force в entrypoint — пересоздаёт симлинк при каждом старте. Это нормально и быстро.public/ как volume — там должны быть файлы из образа (CSS, JS). Только storage/ персистентный.USER appuser (uid 1000)node:20.11-alpine, не latest.dockerignore исключает .git, .env, node_modules--no-cache-dir (pip) / npm ci (не npm install)node:20 — 1.1 ГБ (Debian, 400+ пакетов)node:20-alpine — 180 МБ (Alpine, минимум)node:20 содержит 400+ пакетов, каждый — потенциальная CVE. В alpine — 15 пакетов. Trivy сканирование: 50 уязвимостей vs 3.node:20-slim (~200 МБ, Debian-based)project/
├── docker-compose.yml
├── docker-compose.override.yml # dev-специфичное (volumes, ports)
├── frontend/
│ ├── Dockerfile
│ └── Dockerfile.dev
├── backend/
│ ├── Dockerfile
│ └── Dockerfile.dev
└── .env.example # скопировать в .env
services:
frontend:
build: { context: ./frontend, dockerfile: Dockerfile.dev }
volumes: [./frontend:/app, /app/node_modules, /app/.next]
ports: ["3000:3000"]
environment: { NEXT_PUBLIC_API_URL: http://localhost:8000 }
backend:
build: { context: ./backend, dockerfile: Dockerfile.dev }
volumes: [./backend:/app]
ports: ["8000:8000"]
environment:
DATABASE_URL: postgresql://postgres:localdev@db:5432/myapp
REDIS_URL: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/1
depends_on:
db: { condition: service_healthy }
command: python manage.py runserver 0.0.0.0:8000
celery:
build: { context: ./backend, dockerfile: Dockerfile.dev }
volumes: [./backend:/app]
command: celery -A config worker -l info --autoreload
environment:
DATABASE_URL: postgresql://postgres:localdev@db:5432/myapp
REDIS_URL: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/1
depends_on: [redis, db]
db:
image: postgres:16-alpine
environment: { POSTGRES_DB: myapp, POSTGRES_PASSWORD: localdev }
volumes: [pgdata:/var/lib/postgresql/data]
ports: ["5432:5432"]
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 3s
retries: 5
redis:
image: redis:7-alpine
volumes:
pgdata:
/app/node_modules — анонимный volume, чтобы Mac/Windows node_modules не попали в Linux-контейнерWATCHPACK_POLLING=true для Next.js, --reload для Django.env.example → .env в README# docker-compose.override.yml (только для Mac)
services:
frontend:
environment:
WATCHPACK_POLLING: "true" # Next.js
CHOKIDAR_USEPOLLING: "true" # CRA/Vite
VirtioFS (вместо gRPC FUSE) — быстрее в 2-3 разаVirtioFS уже по умолчаниюservices:
frontend:
develop:
watch:
- action: sync
path: ./frontend/src
target: /app/src
docker compose watch вместо docker compose up7 дней без ограничений. Настройка за 3 минуты — бот уже ждёт в Telegram.
Попробовать за 490 ₽ — 7 дней ← Нейросеть для DevOps