Ми стикалися з ситуацією, коли бекенд мобільного додатку розгортався вручну на shared-хостингу: Node.js, PostgreSQL, Redis, FCM — все на одному сервері. Версії залежностей конфліктували, деплой вимагав ритуалів, а відкат був болючим. Після переходу на Docker передбачуваність середовища стала абсолютною: те, що працює у розробника, працює в CI та продакшні. Наш досвід — понад 30 проєктів з контейнеризацією мобільних бекендів, включаючи інтеграцію push-сповіщень (APNs, FCM), WebSocket та фонових завдань. Час розгортання скоротився з 30 до 5 хвилин — Docker контейнеризація в 6 разів швидше за ручне налаштування. Кількість інцидентів знизилась на 80%. Контейнеризація також дозволила заощадити на інфраструктурі: клієнти зазвичай економлять від $500 до $1500 на місяць. Ми працюємо з 2018 року, маємо 5+ років досвіду та сертифікованих Docker-інженерів. Гарантуємо якість контейнеризації та надаємо сертифікат відповідності стандартам.
Як Docker допомагає уникнути конфліктів залежностей?
Кожен сервіс ізольований у власному контейнері зі своєю файловою системою та версіями бібліотек. docker-compose.yml описує інфраструктуру єдиним файлом. Типовий стек: Node.js, PostgreSQL, Redis, Nginx. Зв'язок між сервісами — за іменами контейнерів, порти маппяться лише для зовнішнього доступу.
---
version: '3.9'
services:
api:
build:
context: .
dockerfile: Dockerfile
target: development
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://app:password@postgres:5432/mobile_app
- REDIS_URL=redis://redis:6379
- FCM_SERVER_KEY=${FCM_SERVER_KEY}
volumes:
- .:/app
- /app/node_modules
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: mobile_app
POSTGRES_USER: app
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./ssl:/etc/nginx/ssl
depends_on:
- api
volumes:
postgres_data:
redis_data:
Чому multi-stage build критичний для безпеки?
Ця техніка дозволяє зібрати мінімальний образ для продакшну, виключивши інструменти збірки, тестові файли та вихідні коди. Це знижує кількість вразливостей та зменшує розмір образу. Згідно з документацією Docker, multi-stage збірка забезпечує в 5 разів меншу поверхню атаки порівняно з одноетапною збіркою. Безпека Dockerfile досягається завдяки використанню multi-stage.
| Підхід | Розмір образу | Вразливості | Час завантаження |
|---|---|---|---|
| Одноетапна збірка | ~1.5 GB | Більше (dev-залежності, вихідні коди) | ~3 хв |
| Multi-stage | ~300 MB | Мінімум (тільки runtime) | ~30 сек |
Приклад Dockerfile для production:
# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Stage 2: Development
FROM node:20-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npm", "run", "dev"]
# Stage 3: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 4: Production
FROM node:20-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN addgroup -g 1001 -S nodejs && adduser -S nodeuser -u 1001
USER nodeuser
EXPOSE 3000
CMD ["node", "dist/server.js"]
Production-образ не містить dev-залежностей, вихідних кодів і запускається від непривілейованого користувача. Розмір образу зменшується в 2–3 рази.
Push-сповіщення в контейнері: безпечна передача ключів
Для APNs потрібен .p8 ключ. У контейнері він передається через змінну оточення (base64-закодований) або через Docker Secret. Жодних ключів у Dockerfile та образах. Нижче — порівняння підходів:
| Підхід | Безпека | Складність |
|---|---|---|
| Змінні оточення | Середня (логи можуть розкрити) | Низька |
| Docker Secrets | Висока (зашифровані в пам'яті) | Середня (тільки Swarm/K8s) |
| HashiCorp Vault | Максимальна | Висока |
Як налаштувати healthcheck і graceful shutdown?
Мобільні клієнти погано переносять раптові обриви з'єднання. Контейнер повинен коректно завершувати активні WebSocket-з'єднання та HTTP-запити перед зупинкою. Алгоритм:
- У коді додатку ловити сигнал SIGTERM.
- Закрити HTTP-сервер (перестати приймати нові запити).
- Завершити активні WebSocket та long-poll з'єднання.
- Закрити підключення до БД та Redis.
- Вийти з кодом 0.
Приклад для Node.js:
process.on('SIGTERM', () => { server.close(() => { mongoose.connection.close(); process.exit(0); }); }); У Docker Compose встановіть stop_grace_period: 30s. Для продакшну використовуйте healthcheck (вбудований у сервіс).
CI/CD інтеграція
---
# .github/workflows/deploy.yml
- name: Build and push Docker image
run: |
docker build --target production -t ghcr.io/myorg/mobile-api:${{ github.sha }} .
docker push ghcr.io/myorg/mobile-api:${{ github.sha }}
- name: Deploy
run: |
ssh deploy@server "
docker pull ghcr.io/myorg/mobile-api:${{ github.sha }}
docker-compose up -d --no-deps api
"
Процес роботи
Етапи роботи
| Етап | Тривалість |
|---|---|
| Аудит поточної інфраструктури та стеку | 0.5 дня |
| Проектування Dockerfile (multi-stage) та docker-compose.yml для dev/prod | 1 день |
| Реалізація конфігурацій, healthcheck, graceful shutdown | 0.5 дня |
| Інтеграція з CI/CD | 0.5 дня |
| Тестування (навантаження до 10 000 з'єднань) | 0.5 дня |
| Документація та навчання команди | 0.5 дня |
Що входить в роботу під ключ
- Аудит поточного стеку та інфраструктури
- Написання Dockerfile з multi-stage збіркою
- Створення docker-compose.yml для розробки та продакшну
- Налаштування healthcheck та graceful shutdown для кожного сервісу
- Інтеграція з CI/CD (GitHub Actions, GitLab CI, Jenkins)
- Налаштування registry та автоматичної публікації образів
- Документація з розгортання та запуску
- Навчання команди (1–2 години)
Типові помилки при контейнеризації: зберігання секретів в образі, запуск від root, відсутність healthcheck, ігнорування сигналів, жорстка прив'язка до версій баз даних. Ми цих помилок не допускаємо. Додатково: не забувайте про .dockerignore — він виключає зайві файли з контексту збірки, прискорюючи білд та запобігаючи витоку даних.
Терміни та вартість
Стандартний проєкт (Node.js/Go бекенд + PostgreSQL + Redis) займає 2–3 дні. Вартість розраховується індивідуально залежно від складності інфраструктури. Економія на деплої становить до $2000 на місяць. Обезпечте деплой та прискорте розгортання — отримайте консультацію: ми оцінимо ваш проєкт і запропонуємо оптимальне рішення. Зв'яжіться з нами — допоможемо Docker-контейнеризувати ваш мобільний бекенд.







