Docker on VPS: What It Is and How to Get Started

If you just got a new VPS or are looking for a cleaner, more manageable way to run multiple applications on a single server, Docker is the tool you need to know. This guide takes you from understanding what Docker is all the way to installing it on Ubuntu and running your first real application.

What Is Docker?

Docker is a platform for developing, shipping, and running applications inside containers — self-contained units that package everything an application needs: code, runtime, libraries, and configuration. Containers run consistently regardless of the underlying server environment.

Containers vs. Virtual Machines (VMs)

The two are often confused, but they work in fundamentally different ways.

A useful analogy: if a VM is a standalone house with its own plumbing and wiring, a container is a flat in an apartment building — it has its own private space, but shares the building's infrastructure (the kernel).

Key takeaway: Docker containers use 5–10x fewer resources than VMs, start faster, and are far easier to deploy. They are ideal for VPS environments where RAM is at a premium.

Why Docker Is Popular on VPS

Docker has become a go-to tool for VPS users for several compelling reasons.

Requirements Before Installing Docker

Make sure your VPS meets these requirements before proceeding.

Connect to your VPS via SSH first. If you need help with that, see the SSH Connection Guide.

Installing Docker on Ubuntu

The recommended approach is to install from Docker's official repository, which always provides the latest stable version.

Step 1: Update the system and install dependencies

apt update && apt upgrade -y
apt install -y ca-certificates curl gnupg lsb-release

Step 2: Add Docker's GPG key and repository

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update

Step 3: Install Docker Engine

apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Step 4: Verify the installation

docker --version
# Expected: Docker version 26.x.x, build xxxxxxx

docker run hello-world
# Expected: Hello from Docker!

Step 5 (optional): Run Docker without sudo

If you work as a non-root user, add that user to the docker group.

usermod -aG docker $USER
# Log out and back in for the change to take effect

Essential Docker Commands

With Docker installed, here are the commands you will reach for most often.

docker pull — download an image

docker pull nginx          # Latest Nginx image
docker pull nginx:1.25     # Specific version
docker pull ubuntu:22.04   # Ubuntu 22.04 base image

docker run — start a container

docker run nginx                          # Run Nginx (foreground)
docker run -d nginx                       # Run in background (detached)
docker run -d -p 80:80 --name web nginx   # Map port 80, name the container "web"
docker run -d -p 8080:80 nginx            # Map host port 8080 to container port 80

docker ps — list running containers

docker ps        # Show running containers
docker ps -a     # Show all containers including stopped ones

docker stop and docker rm — stop and remove

docker stop web     # Stop the container named "web"
docker stop abc123  # Stop by container ID
docker rm web       # Remove a stopped container
docker rm -f web    # Force-remove even if running

Other useful commands

docker images             # List all local images
docker rmi nginx          # Remove an image
docker logs web           # View container logs
docker exec -it web bash  # Open a shell inside a running container

What Is Docker Compose and How to Install It

Docker Compose lets you define and run multi-container applications using a single docker-compose.yml file. Instead of typing long docker run commands for each service, you describe the entire stack in one file and bring it up with one command.

If you installed Docker using the steps above (including docker-compose-plugin), Compose is already available.

docker compose version
# Docker Compose version v2.x.x

Note: Docker Compose v2 uses docker compose (with a space). The older v1 used docker-compose (with a hyphen). This guide uses v2.

Example: Running WordPress + MySQL with Docker Compose

Here is a working example that launches a full WordPress site backed by MySQL — no manual Apache or PHP installation required.

Create a project directory and compose file

mkdir ~/wordpress && cd ~/wordpress
nano docker-compose.yml

Contents of docker-compose.yml

services:
  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: your_wp_password
    volumes:
      - db_data:/var/lib/mysql

  wordpress:
    image: wordpress:latest
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: your_wp_password
    volumes:
      - wp_data:/var/www/html
    depends_on:
      - db

volumes:
  db_data:
  wp_data:

Start the WordPress stack

docker compose up -d
# Docker pulls the images and creates both containers automatically

docker compose ps
# Verify both services are running

# Open your browser to http://YOUR_VPS_IP:8080
# You will see the WordPress setup wizard

Common Docker Compose commands

docker compose up -d        # Start all services in the background
docker compose down         # Stop and remove all containers
docker compose down -v      # Stop + delete volumes (data will be lost!)
docker compose logs -f      # Tail logs in real time
docker compose restart      # Restart all services
docker compose ps           # Show service status

Docker Networking and Volumes: Fundamentals You Must Understand

Once you start running multiple containers on a VPS, two concepts become critical: Docker networking (how containers talk to each other) and Docker volumes (how data persists). By default, containers are stateless — all data inside a container disappears the moment it is removed.

Docker Networks

Docker ships with three main network types.

When you use Docker Compose, it automatically creates a custom bridge network for your project. Containers in the same Compose file can reach each other by service name — for example, the WordPress container can connect to MySQL simply using the hostname db.

# Create a custom network
docker network create mynetwork

# Run a container attached to that network
docker run -d --name app --network mynetwork nginx

# List all networks
docker network ls

# Inspect a network
docker network inspect mynetwork

Docker Volumes: Keeping Data Alive

A Docker volume is a storage area managed by Docker that lives outside the container filesystem. Data in a volume survives container removal and recreation — making volumes essential for databases, user-uploaded files, and critical configuration.

# Create a volume
docker volume create mydata

# List all volumes
docker volume ls

# Mount a volume when running a container
docker run -d -v mydata:/var/lib/mysql mysql:8.0

# Remove a volume (warning: data is permanently deleted)
docker volume rm mydata

# Remove all unused volumes
docker volume prune

Golden rule: Every piece of important data — databases, uploaded files, configuration — must live in a Docker volume. Never store it inside the container; the container is ephemeral and will be recreated during updates or restarts.

Managing a Multi-Container Stack on VPS with Docker Compose

In real VPS deployments, you will almost always run several containers together — a web server, database, cache, and reverse proxy at minimum. Below is a production-ready example stack.

Example: Nginx + PHP-FPM + MySQL + Redis

This stack suits modern PHP applications that need high performance and Redis-based caching.

services:
  nginx:
    image: nginx:1.25-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./app:/var/www/html
      - ./ssl:/etc/ssl/certs
    depends_on:
      - php

  php:
    image: php:8.3-fpm-alpine
    restart: always
    volumes:
      - ./app:/var/www/html
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: strong_root_pw_here
      MYSQL_DATABASE: appdb
      MYSQL_USER: appuser
      MYSQL_PASSWORD: strong_app_pw_here
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "127.0.0.1:3306:3306"

  redis:
    image: redis:7-alpine
    restart: always
    volumes:
      - redis_data:/data
    ports:
      - "127.0.0.1:6379:6379"

volumes:
  db_data:
  redis_data:

Note that MySQL and Redis bind their ports to 127.0.0.1 only — accessible from the VPS itself but not from the public internet. This is an important security best practice.

Starting and inspecting the stack

# Start all services
docker compose up -d

# Check the status of every service
docker compose ps

# Follow logs in real time
docker compose logs -f

# Restart a misbehaving service
docker compose restart php

# Pull the latest images and redeploy
docker compose pull && docker compose up -d

Backing Up and Restoring Docker Data on VPS

Docker volumes are far safer than storing data inside containers, but you still need a solid backup strategy. Volume data lives on the VPS disk — if the VPS itself fails, the data is gone too.

Backup a database from a running container

# Back up a specific MySQL database
docker exec mysql_container mysqldump -u root -p'strong_root_pw_here' appdb > backup_$(date +%Y%m%d).sql

# Back up all databases
docker exec mysql_container mysqldump -u root -p'strong_root_pw_here' --all-databases > all_backup.sql

# Restore a database
docker exec -i mysql_container mysql -u root -p'strong_root_pw_here' appdb < backup_20260608.sql

Backup an entire Docker volume

# Back up a volume using a temporary Alpine container
docker run --rm \
  -v db_data:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/db_data_backup.tar.gz -C /source .

# Restore a volume from a backup archive
docker run --rm \
  -v db_data:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/db_data_backup.tar.gz -C /target

Automated daily backup with cron

Add a cron job to the VPS to run database backups automatically every day.

# Run: crontab -e, then add this line
# Back up daily at 2 AM, keep 7 days of history
0 2 * * * docker exec mysql_container mysqldump -u root -p'PWD' appdb > /backups/db_$(date +\%Y\%m\%d).sql && find /backups -name "db_*.sql" -mtime +7 -delete

Best practice: A good backup strategy stores copies in multiple locations — on the VPS, downloaded to cloud storage (e.g., Google Drive), or on a separate server. A backup that only lives on the same machine as the data it is protecting is not true redundancy.

Docker vs. Direct Installation on VPS

Many people wonder whether to use Docker or simply install Apache, PHP, and MySQL directly. Here is an honest comparison.

Bare-metal installation

Using Docker

Recommendation: If you plan to run multiple applications on one VPS or deploy frequently, Docker pays off quickly. If you only need a single WordPress site, a traditional LAMP stack is still a perfectly valid choice.

Security Tips for Docker on VPS

Ready to Run Docker on a VPS?

AsiaGB Linux VPS starts from 500 THB/month — 1 GB RAM and up, full root access, Docker-ready out of the box. Data centers in Thailand and Singapore.

View VPS Plans