Old school hosting is a nightmare known as "Dependency Hell." You install PHP 8.1 for one app, but your second app requires PHP 7.4. Suddenly, your server is broken, and you are spending your weekend fixing config files.

Enter Docker. Docker packages your app and everything it needs into a "Container." It runs the same on your laptop as it does on a Joy Services VPS. No conflicts, no mess.


Step 1: Clean the Slate

Ubuntu repositories often contain outdated, unofficial versions of Docker. We need to rip those out before we begin.

Bash
root@joy:~# sudo apt-get remove docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc

(It is normal if it says "Package 'docker.io' is not installed, so not removed.")


Step 2: Add the Official Repository

We want the latest features, so we will tell Ubuntu to ignore its own library and use Docker's official source instead.

1. Install Prerequisites & Keyrings:

Bash
root@joy:~# sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg

2. Add the Repo to Source List:

Bash
root@joy:~# echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update

Step 3: Install the Engine

Now that the groundwork is laid, the installation is a single command.

Bash
root@joy:~# sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Verify it works:

root@joy:~# sudo systemctl status docker

If you see a green active (running) light, press Q to exit the screen.


Step 4: Launch Your First App

We will launch a tiny web server (Nginx) inside a container. We will map it to port 8080 so it doesn't conflict with any websites you already have running on port 80.

Bash
root@joy:~# sudo docker run -d -p 8080:80 --name my-web-server nginx
The Anatomy of that Command:
-d: Detached (Runs in the background so it doesn't freeze your terminal).
-p 8080:80: Traffic hitting your VPS on port 8080 is magically teleported to port 80 inside the container.
nginx: The image name to download from Docker Hub.

Test it now: Open your browser and go to http://your_server_ip:8080. You will see the "Welcome to Nginx" page.


Step 5: Cleanup

You can't leave containers running forever if you aren't using them. Here is how to kill it.

Bash
root@joy:~# sudo docker stop my-web-server sudo docker rm my-web-server

You have now successfully installed the engine and mastered the basic lifecycle of a container. You are ready to deploy complex stacks without the headache.