# Local Docker Deployment

> Step-by-step guide to run the full Temp-Number App locally with Docker Compose for development, testing, and learning the stack.


Run a complete Temp-Number App stack locally using Docker Compose. Perfect for development, testing, and learning how the system works.

## Overview

Docker Compose provides:

- ✅ **Quick Setup**: Get running in minutes with automated configuration
- ✅ **No Local Dependencies**: Everything runs in containers
- ✅ **Automatic Migrations**: Database setup handled automatically
- ✅ **Hot Reload**: Development mode with live code changes (optional)
- ✅ **Easy Cleanup**: Remove everything with one command
- ✅ **Isolated Environment**: Doesn't interfere with other projects

## Architecture



## Prerequisites

- **Web Frontend**: Vue.js app served by Nginx on port 8080
- **Backend API**: AdonisJS API server on port 3333
- **MySQL Database**: MySQL 8.0 on port 3336 with persistent volume

### Required Software

Install the following before proceeding:

- **Docker Desktop**: [Installation guide](https://docs.docker.com/get-docker/)

  - Windows: Docker Desktop for Windows
  - Mac: Docker Desktop for Mac
  - Linux: Docker Engine + Docker Compose
- **Git**: For cloning repositories ([Download](https://git-scm.com/downloads)
)

Verify installation:

```bash
# Check Docker
docker --version
# Output: Docker version 24.0.0 or higher

# Check Docker Compose
docker compose version
# Output: Docker Compose version 2.0.0 or higher
```

### Required Accounts

- **Firebase**: [Create project](https://console.firebase.google.com)
 for user authentication
- **Platfone**: For SMS activation API ([Get access](https://platfone.com)
)
- **Stripe** (optional): For payment processing ([Sign up](https://stripe.com)
)

## Deployment

### ⚡ Automated Deployment (Recommended)

You can use the provided deployment scripts for automated deployment to your local machine. These scripts handle the entire deployment process, including building Docker images, starting containers, and configuring the necessary services.

```bash
git clone https://github.com/platfone-com/temp-number-deploy.git
cd temp-number-deploy
./docker-start.sh
```

Script will prompt for necessary configuration values.

For automated assistance with Firebase setup, consider using the [Setup Wizard](/docs/temp-number/deployment/setup-wizard/) instead.

**Watch the video tutorial:**

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/SXoU-PhTg5U?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>


</br>

- [Setup Wizard](https://platfone.com/docs/temp-number/deployment/setup-wizard.md): Interactive setup wizard that handles all prerequisites and configuration


### 🐢 Manual Deployment Steps

#### Step 1: Clone the Deployment Repository

```bash
git clone https://github.com/platfone-com/temp-number-deploy.git
cd temp-number-deploy
```

#### Step 2: Clone Application Repositories

```bash
# Clone backend repository
git clone https://github.com/platfone-com/temp-number-backend.git
# Clone frontend repository
git clone https://github.com/platfone-com/temp-number-web.git
```

#### Step 3: Prepare environment

```bash
# Prepare environment variables
cp config/env/backend.env.example config/env/backend.env
cp config/env/web.env.example config/env/web.env
# Prepare secrets
cp config/secrets/backend.secrets.example config/secrets/backend.secrets
echo "Fill in the configuration files with your values"
```

#### Step 4: Prepare Firebase

##### Step 4.1 : Create Firebase Project

1. Go to [Firebase Console](https://console.firebase.google.com)

2. Create a new Firebase project or select an existing one

##### Step 4.2: Configure Firebase Authentication

Configure Firebase Authentication (Email/Password, Google, etc.)

 1. Go to [Firebase Console](https://console.firebase.google.com)

 2. Select your project
 3. Go to **Authentication** → **Sign-in method**
 4. Choose and enable desired sign-in providers (e.g., Email/Password, Google, Apple, Facebook)
 5. Save changes

##### Step 4.3: Set Email Templates

1. Go to **Authentication** → **Templates**
2. Click on pencil icon to edit templates
3. Click on "Customize action URL"
4. Set the URL to `http://localhost:8080/app/deeplink` for local development

This ensures that email links redirect to your local frontend application.

#### Step 5: Download Firebase Service Account Key

1. Go to **Project Settings** → **Service Accounts**
2. Click **Generate New Private Key**
3. Save as `config/secrets/firebase-service-account.json`

Set correct permissions:

```bash
chmod 644 config/secrets/firebase-service-account.json
```

Run the interactive script:

```bash
./docker-start.sh
```

Select option **1** or **2** to start services:

```bash
What would you like to do?
  1) Start services (build and run)
  2) Start services in background
  3) Run migrations only
  4) View logs
  5) Stop services
  6) Clean up (remove containers and volumes)

Enter choice [1-6]: 2
```

#### Step 6: Verify Services

Check that all services are running:

```bash
docker compose ps
```

Expected output:

```bash
NAME                    IMAGE               STATUS              PORTS
temp-number-backend     docker-backend      Up 30 seconds       0.0.0.0:3333->3333/tcp
temp-number-mysql       mysql:8.0           Up 30 seconds       0.0.0.0:3336->3336/tcp
temp-number-web         docker-web          Up 30 seconds       0.0.0.0:8080->80/tcp
```

Check logs:

```bash
cd scripts/docker
docker compose --profile full logs -f
```

## Understanding the Services

### MySQL Database

**Container**: `temp-number-mysql`

```yaml
Environment:
  MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root_password}
  MYSQL_DATABASE: ${DB_DATABASE:-temp_number}
  MYSQL_USER: ${DB_USER:-temp_number_user}
  MYSQL_PASSWORD: ${DB_PASSWORD:-temp_number_password}

Volume:
  mysql_data:/var/lib/mysql  # Persists data

Health Check:
  mysqladmin ping every 10s
```

**Access database**:

```bash
# Using Docker
cd scripts/docker
echo "Use user and password from backend.env and backend.secrets file"
docker exec -it temp-number-mysql mysql -u YOUR_DB_USER -pYOUR_DB_PASSWORD

# From host (if port 3336 is exposed)
mysql -h 127.0.0.1 -P 3336 -u YOUR_DB_USER -pYOUR_DB_PASSWORD
```

### Backend API

**Container**: `temp-number-backend`

```yaml
Build Context: ../../temp-number-backend
Entry Point: /app/init-backend.sh (runs migrations)
Command: node bin/server.js

Environment Overrides:
  # Override specific values for Docker environment
  DB_HOST: mysql
  DB_PORT: 3306
  DB_PASSWORD: ${DB_PASSWORD:-temp_number_password}
  NODE_ENV: development
  HOST: 0.0.0.0

  # Use local Firebase credentials path
  GOOGLE_APPLICATION_CREDENTIALS: /app/config/secrets/firebase-service-account.json

  # Override CORS for local development
  ALLOWED_ORIGINS: http://localhost:${DOCKER_WEB_PORT:-8080}

Mounts:
  - Firebase credentials (read-only)
  - Initialization script
```

**Automatic Initialization**:

The backend automatically runs on startup:

1. Waits for MySQL to be ready (30 retries, 2s interval)
2. Runs database migrations: `node ace migration:run --force`
3. Starts the API server

**View backend logs**:

```bash
docker compose --profile full logs backend -f
```

**Access backend shell**:

```bash
docker exec -it temp-number-backend bash
```

### Web Frontend

**Container**: `temp-number-web`

```yaml
Build Context: ../../temp-number-web
Build Args: All VITE_* environment variables
Server: Nginx on port 80 (mapped to 8080)

Health Check:
  curl -f http://localhost:80/app/ every 30s
```

**Build process**:

1. Installs npm dependencies
2. Builds Vue.js app with environment variables
3. Serves static files via Nginx

**View web logs**:

```bash
docker compose --profile full logs web -f
```

## Development Mode (Hot Reload)

For active development of Backend or Web components with hot reload use `scripts/docker/docker-compose.dev.yml` as additional compose file:

```bash
cd scripts/docker
docker compose --profile full -f docker-compose.yml -f docker-compose.dev.yml up
```

Now code changes will automatically reload!

- **Backend**: Reloads on TypeScript changes
- **Frontend**: Hot module replacement (HMR) on port 5173

To run migrations please, refer to [running database migrations](/docs/temp-number/deployment/local-docker-deployment/#run-database-migrations).

## Common Operations

### View Logs

```bash
# All services
docker compose --profile full logs -f

# Specific service
docker compose --profile full logs backend -f
docker compose --profile full logs web -f
docker compose --profile full logs mysql -f

# Last 100 lines
docker compose --profile full logs --tail=100 backend
```

### Restart Services

```bash
# Restart all
docker compose --profile full restart

# Restart specific service
docker compose --profile full restart backend
docker compose --profile full restart web
```

### Run Database Migrations

Migrations run automatically on startup, but you can run manually:

```bash
# Run pending migrations
docker exec -it temp-number-backend node ace migration:run

# Rollback last batch
docker exec -it temp-number-backend node ace migration:rollback

# Check migration status
docker exec -it temp-number-backend node ace migration:status
```

### Access Service Shells

```bash
# Backend shell
docker exec -it temp-number-backend bash

# MySQL shell
docker exec -it temp-number-mysql mysql -u YOUR_DB_USER -pYOUR_DB_PASSWORD

# Web container shell
docker exec -it temp-number-web sh
```

### Stop Services

```bash
# Stop services (keeps containers)
docker compose --profile full stop

# Stop and remove containers
docker compose --profile full down

# Stop, remove containers and volumes (deletes database!)
docker compose --profile full down -v
```

### Rebuild After Code Changes

```bash
# Rebuild and restart
docker compose --profile full up --build -d

# Rebuild specific service
docker compose --profile full build backend
docker compose --profile full up -d backend
```

### Reset Database

```bash
# Method 1: Drop and recreate via migrations
docker exec -it temp-number-backend node ace migration:rollback --batch=0
docker exec -it temp-number-backend node ace migration:run

# Method 2: Destroy volume and restart
docker compose --profile full down -v
docker compose --profile full up -d
```

## Troubleshooting

⚠️ All `docker compose ...` commands should be run from `scripts/docker` directory.

### Services Won't Start

**Check Docker is running**:

```bash
docker info
```

If Docker is not running, start Docker Desktop.

**Check port conflicts**:

```bash
# Check if ports are already in use
lsof -i :8080  # Web frontend
lsof -i :3333  # Backend API
lsof -i :3336  # MySQL

# Or on Linux
netstat -tulpn | grep -E ':(8080|3333|3336)'
```

Change ports if needed in `scripts/docker/docker-compose.env.sh`.

### MySQL Connection Errors

**Symptom**: Backend fails to connect to database

**Check MySQL is healthy**:

```bash
docker compose ps mysql
# Should show "healthy" status

docker compose --profile full logs mysql
```

**Test connection manually**:

```bash
docker exec -it temp-number-mysql mysqladmin ping -h localhost -u root -proot_password
```

**Reset database**:

```bash
docker compose --profile full down -v
docker compose --profile full up -d
```

### Migration Failures

**Symptom**: Backend logs show migration errors

**Check migration status**:

```bash
docker exec -it temp-number-backend node ace migration:status
```

**Rollback and retry**:

```bash
docker exec -it temp-number-backend node ace migration:rollback
docker exec -it temp-number-backend node ace migration:run
```

**Reset migrations**:

```bash
docker exec -it temp-number-backend node ace migration:rollback --batch=0
docker exec -it temp-number-backend node ace migration:run --force
```

### Firebase Authentication Issues

**Symptom**: Login fails or "Firebase not configured" errors

**Verify credentials file**:

```bash
# Check file exists and has correct permissions
ls -la config/secrets/firebase-service-account.json

# Should show: -rw-r--r-- (644)
```

**Verify environment variable**:

```bash
docker exec -it temp-number-backend printenv | grep GOOGLE_APPLICATION_CREDENTIALS
# Should show: GOOGLE_APPLICATION_CREDENTIALS=/app/config/secrets/firebase-service-account.json

# Check file is mounted
docker exec -it temp-number-backend ls -la /app/config/secrets/
```

**Test Firebase connection**:

```bash
docker compose --profile full logs backend | grep -i firebase
```

### Frontend Build Errors

**Symptom**: Web container fails to build

**Check environment variables**:

```bash
cat scripts/docker/.env | grep VITE_
```

**Build with verbose output**:

```bash
docker compose --profile full build --no-cache --progress=plain web
```

**Check Node.js version**:

The frontend requires Node.js 18+. Check Dockerfile in `temp-number-web`.

### Port Already in Use

**Change ports**:

Edit `scripts/docker/docker-compose.env.sh`:

```bash
export DOCKER_WEB_PORT=8081        # Changed from 8080
export DOCKER_BACKEND_PORT=3334    # Changed from 3333
export DOCKER_MYSQL_PORT=3307      # Changed from 3336
```

Restart:

```bash
docker compose --profile full down
./docker-start.sh
```

### Container Disk Space

**Check Docker disk usage**:

```bash
docker system df
```

**Clean up**:

```bash
# Remove unused images
docker image prune -a

# Remove unused volumes
docker volume prune

# Full cleanup (WARNING: removes everything)
docker system prune -a --volumes
```

### Logs Show EADDRINUSE

**Symptom**: `Error: listen EADDRINUSE: address already in use`

This means another process is using the port. Kill the process or change ports.

**Find and kill process**:

```bash
# Find process on port 3333
lsof -ti:3333

# Kill it
kill -9 $(lsof -ti:3333)
```

## Performance Optimization

### Resource Limits

Set resource limits in `docker-compose.yml`:

```yaml
services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G
```

### Volume Performance

Use delegated or cached volume mounts for better performance:

```yaml
volumes:
  - ../../temp-number-backend:/usr/src/app:delegated
```

### Build Cache

Speed up rebuilds with build cache:

```bash
# Use BuildKit
export DOCKER_BUILDKIT=1

# Build with cache
docker compose build --build-arg BUILDKIT_INLINE_CACHE=1
```

## Security Best Practices

### Protect Secrets

Never commit secrets to version control:

```bash
# .gitignore should include:
config/secrets/
scripts/docker/.env
*.pem
*.key
*-key.json
```

### Generate Strong APP_KEY

```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```

### Use Strong Database Password

```bash
openssl rand -base64 32
```

### Restrict Firebase Permissions

Set minimal file permissions:

```bash
chmod 600 config/secrets/firebase-service-account.json
```

## Backup and Restore

### Backup Database

```bash
# Create backup
docker exec temp-number-mysql mysqldump -u YOUR_DB_USER -pYOUR_DB_PASSWORD temp_number > backup-$(date +%Y%m%d).sql

# Or with Docker
docker exec temp-number-mysql mysqldump -u YOUR_DB_USER -pYOUR_DB_PASSWORD temp_number > backup.sql
```

### Restore Database

```bash
# Restore from backup
docker exec -i temp-number-mysql mysql -u YOUR_DB_USER -pYOUR_DB_PASSWORD temp_number < backup.sql
```

### Backup Entire Volume

```bash
# Stop services
docker compose --profile full stop backend web

# Create volume backup
docker run --rm \
  -v docker_mysql_data:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/mysql-data-backup.tar.gz -C /source .

# Restart services
docker compose --profile full start
```

### Restore Volume

```bash
# Stop and remove containers
docker compose --profile full down

# Remove old volume
docker volume rm docker_mysql_data

# Create new volume
docker volume create docker_mysql_data

# Restore data
docker run --rm \
  -v docker_mysql_data:/target \
  -v $(pwd):/backup \
  alpine sh -c "cd /target && tar xzf /backup/mysql-data-backup.tar.gz"

# Start services
docker compose --profile full up -d
```

## Advanced Topics

### Custom Docker Network

Use a custom network for integration with other services:

```yaml
networks:
  temp-number-network:
    external: true
    name: my-custom-network
```

### Health Checks

Monitor service health:

```bash
# Check health status
docker compose ps

# Detailed health info
docker inspect temp-number-backend --format='{{json .State.Health}}'
```

### Logging to File

Redirect logs to files:

```bash
# Log all services
docker compose --profile full logs -f > docker-compose.log 2>&1 &

# Log specific service
docker compose --profile full logs -f backend > backend.log 2>&1 &
```

## Next Steps


  - [Configuration](https://platfone.com/docs/temp-number/configuration/): Configure authentication and payments

  - [Development Guide](https://platfone.com/docs/temp-number/development.md): Customize and extend the application




