From Shared Hosting to Docker on DigitalOcean: A Calm Server Migration Plan

How to move a Laravel or PHP app from shared hosting or an old VPS to Docker on DigitalOcean or AWS, with backups, DNS, SSL and almost no downtime.

A wall of stacked shipping containers
Photo by Richard Williams on Unsplash
Short answerContainerize the app, build the new server alongside the old one, copy the data, test on a temporary domain, lower DNS TTL in advance, then switch DNS during a quiet hour. Keep the old server until the new one has run cleanly for a week.

Shared hosting is a fine place to start. Then the app grows: queues, scheduled jobs, more traffic, a mobile app hitting the API. Shared hosting starts saying no, and every deployment becomes a nervous FTP upload.

When I deployed the TWG Platform to production, I containerized the whole stack with Docker. It's now how I set up most new projects, and how I move older ones. Here's the plan I follow.

Why Docker

  • The same setup everywhere. What runs on my laptop runs on staging and production.
  • Easier upgrades. Changing PHP or Node versions becomes a one-line change you can test, not a server-wide gamble.
  • Clear pieces. Web app, queue workers, scheduler, database and cache each run as their own service.

Docker isn't required for a good server. But for teams that will keep changing the app, it removes a lot of "works on my machine" pain.

Step 1: Containerize and run it locally

I write a Dockerfile for the app and a docker-compose.yml for the services around it: Nginx, PHP-FPM or Node, queue workers, a scheduler, Redis and the database for local use. The goal of this step is simple: the app runs locally exactly as it will in production.

Step 2: Build the new server next to the old one

On DigitalOcean (or AWS), I create a fresh Ubuntu server, harden it (SSH keys only, firewall, automatic security updates), install Docker and deploy the app. For production databases I usually prefer a managed database, so backups and updates aren't my client's problem.

Nothing changes for users yet. The old server keeps serving everyone.

Step 3: Copy the data and test

  • Copy the database and uploaded files to the new server.
  • Point a temporary subdomain at it and test every main flow.
  • Check emails, scheduled jobs, payment webhooks and file uploads. These are the things most often forgotten.

Step 4: Plan the DNS switch

A day or two before the move, I lower the DNS TTL to a few minutes so the switch spreads quickly. On the day:

  1. Put the old site in maintenance mode for a few minutes.
  2. Take a final database copy and load it on the new server.
  3. Switch the DNS records.
  4. Issue the SSL certificate and confirm HTTPS works.
  5. Turn maintenance mode off.

For most apps, users see a few minutes of maintenance at most.

Step 5: Keep the old server for a week

Don't cancel the old hosting on day one. Keep it for a week, untouched, as a fallback. Once the new server has run cleanly through a week of real traffic, backups and scheduled jobs, it's safe to retire.

After the move

  • Automated daily database backups stored off the server, with a restore you've actually tested.
  • Uptime monitoring and error alerts.
  • A deployment pipeline, so releases are a button or a git push, not an FTP upload.

Server and hosting moves are part of my migration and modernization service. If your app has outgrown its hosting, let's plan the move.