Deploy a Laravel 13 Application: From Shared Hosting to Docker (2026)

Deploy a Laravel 13 Application: From Shared Hosting to Docker (2026)

When your Laravel app works locally, deployment is the next real milestone. In this guide, you will deploy Laravel 13 with MySQL 8 using three practical options: shared hosting, VPS with Docker, and Laravel Forge.

You will also get a production checklist so you avoid common mistakes like broken permissions, leaked debug pages, and queue workers not running.

Deployment options at a glance

OptionBest forTradeoff
Shared hostingLowest cost MVPsLess control, limited performance tuning
VPS + DockerFull control and portabilityMore DevOps responsibility
Laravel ForgeFastest managed VPS setupAdded platform cost

If you are new to Laravel setup, read Create a New Laravel 13 Project in 2026 first. For config hardening, pair this with Laravel .env Explained.

Pre-deploy production checklist

Before any deployment method, confirm these baseline settings:

APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
LOG_CHANNEL=stack
QUEUE_CONNECTION=database
CACHE_STORE=redis
SESSION_DRIVER=redis

And run:

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan migrate --force

Key checks:

  • .env is not in git.
  • storage and bootstrap/cache are writable by the web user.
  • Queue workers and scheduler are configured.
  • HTTPS is enabled.

Path 1: Deploy on shared hosting

Shared hosting can run Laravel if you structure files correctly.

Typical flow:

  1. Upload project files outside public_html.
  2. Point web root to Laravel public/.
  3. Set production .env values.
  4. Run composer install via SSH (if available).
  5. Run migrations and cache commands.

Recommended command set:

composer install --no-dev --optimize-autoloader
php artisan key:generate --force
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache

If your host does not provide CLI access, shared hosting becomes painful quickly. In that case, move to Forge or a VPS.

Path 2: Deploy on VPS with Docker

This is ideal when you want predictable environments and full control.

1) Minimal docker-compose.yml

services:
  app:
    image: ghcr.io/your-org/laravel-app:latest
    env_file:
      - .env
    depends_on:
      - mysql
      - redis
    networks:
      - app-net

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - app
    networks:
      - app-net

  mysql:
    image: mysql:8
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: root-secret
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - app-net

  redis:
    image: redis:7-alpine
    networks:
      - app-net

networks:
  app-net:

volumes:
  mysql-data:

2) Build and release pipeline

Use CI to build image, then pull on server.

docker compose pull
docker compose up -d --remove-orphans
docker compose exec app php artisan migrate --force
docker compose exec app php artisan config:cache

3) Queue workers and scheduler

Run queue workers using Supervisor or an extra container.

Scheduler example (cron on host):

* * * * * cd /var/www/laravel && docker compose exec -T app php artisan schedule:run >> /dev/null 2>&1

Path 3: Deploy with Laravel Forge

Forge is the fastest way to run Laravel on managed VPS infrastructure.

Core setup:

  1. Provision server in Forge.
  2. Create a site and connect your Git repo.
  3. Add environment variables in Forge dashboard.
  4. Configure deployment script.
  5. Enable queue worker and scheduler.

Sample Forge deploy script:

cd /home/forge/yourdomain.com

git pull origin main
composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart

For many teams, Forge gives the best speed-to-production balance.

Zero-downtime deployment basics

Even simple apps should avoid visible downtime during deploy.

Good practices:

  • Build assets before switch-over.
  • Run migrations that are backward-compatible first.
  • Restart workers after code deploy.
  • Avoid destructive schema changes in a single release step.

If using symlink-based release directories, switch symlink only after health checks pass.

Security and reliability hardening

Minimum production hardening:

  • Enable firewall (ufw) and only allow required ports.
  • Disable password SSH login, use SSH keys.
  • Enforce TLS certificates (LetsEncrypt).
  • Back up MySQL daily and test restore.
  • Use separate DB users per environment.

Monitor these metrics:

  • 5xx error rate
  • Queue lag
  • DB CPU and slow queries
  • Disk usage and backup success

Common deployment mistakes

MistakeSymptomFix
APP_DEBUG=true in prodStack traces visible publiclySet false and clear config cache
Missing write permissionsLogs/sessions failFix owner/group and permissions
Not restarting workersOld jobs run stale codephp artisan queue:restart
Running unsafe migrationsApp errors during deployUse backward-compatible migrations
No health check routeHard to verify releaseAdd /health endpoint

Post-deploy verification checklist

After each deploy:

  1. Open /health and main app routes.
  2. Confirm migrations succeeded.
  3. Confirm queue jobs process successfully.
  4. Check logs for exceptions in first 10 minutes.
  5. Confirm scheduler runs at least one cycle.

A quick smoke test after each release catches most production incidents early.

FAQ

Which deployment path should I pick in 2026?

If you want speed and less infrastructure overhead, pick Forge. If you need full control and portability, pick VPS + Docker. Use shared hosting only for small low-risk projects.

Do I need Docker for Laravel deployment?

No, but Docker improves consistency across environments and teams.

Should I run php artisan migrate --force on every deploy?

Usually yes, as part of your deployment script, as long as your migrations are safe and reviewed.

How do I avoid downtime during schema changes?

Use additive, backward-compatible migrations first, deploy code that supports both old and new schema, then clean up in a later release.

Final takeaway

Laravel deployment is easiest when you standardize your process. Pick one path, automate it, and verify every release with a checklist. In Laravel 13, consistent environment handling and safe migrations are what separate stable deployments from stressful ones.

Next in this series: How to Run Raw SQL Queries in Laravel with DB::raw and the upcoming Laravel Project Lifecycle pillar.