How to Install Docker on Ubuntu Server (and Run Your First Container)

Docker is the reason home servers took off. Instead of installing a database, a web server and a dozen libraries by hand — and having them fight each other — each app runs in its own tidy box called a container, with everything it needs inside. Installing Nextcloud, Pi-hole or a Minecraft server becomes one command.
Quick reference
| Task | Command |
|---|---|
| Run a container | docker run -d --name web -p 8080:80 nginx |
| See what's running | docker ps |
| Logs | docker logs -f web |
| Stop / start / remove | docker stop web / docker start web / docker rm web |
| Clean up unused stuff | docker system prune |
| Go inside a container | docker exec -it web bash |
1. Install Docker
Use Docker's own repository rather than Ubuntu's older package. Docker provides a script that does the setup:
curl -fsSL https://get.docker.com | sudo sh
That adds the repository, installs Docker Engine and Docker Compose, and starts the service. Check it:
docker --version
sudo systemctl status docker
2. Run it without sudo
sudo usermod -aG docker $USER
Log out and back in, then docker ps should work without sudo. (Members of the docker group effectively have root access, so only add people you'd give sudo to.)
3. Your first container
docker run -d --name web -p 8080:80 nginx
- -d runs it in the background
- --name web gives it a name
- -p 8080:80 connects port 8080 on the server to port 80 inside the container
- nginx is the image, downloaded automatically from Docker Hub
Open http://your-server-ip:8080 in a browser. That's Nginx, running, with nothing installed on the server itself.
4. Everyday commands
docker ps # running containers
docker ps -a # including stopped ones
docker logs -f web # watch its output (Ctrl + C to stop watching)
docker stop web
docker start web
docker rm web # delete it (must be stopped)
docker images # downloaded images
5. Keeping data
Containers are disposable: delete one and anything written inside it is gone. For data you want to keep, map a folder on the server into the container with -v:
docker run -d --name web -p 8080:80 -v /home/john/site:/usr/share/nginx/html nginx
Now the website files live in /home/john/site on the server, and the container just reads them.
6. Restart after reboot
Add --restart unless-stopped to docker run and the container comes back whenever the server does.
Clean up
Images pile up. Every few weeks:
docker system prune
It removes stopped containers, unused networks and dangling images. -a also removes images no container is using.
Troubleshooting
"permission denied while trying to connect to the Docker daemon socket." You haven't logged out and in since adding yourself to the docker group.
"port is already allocated." Something else is using that port on the server. sudo ss -tlnp | grep :8080 to find it, or pick a different host port (-p 8081:80).
Container starts then immediately stops. docker logs name shows why — usually a missing environment variable or config file.
Docker bypasses UFW. Published ports are reachable even if UFW blocks them. Bind to localhost (-p 127.0.0.1:8080:80) for things that should only be reached through a reverse proxy.
Wrapping up
One install script, add yourself to the group, docker run. Use -v for data you want to keep and --restart unless-stopped for things that should always be up. Next: Docker Compose, which turns those long docker run commands into a file you can keep.
