Docker for Beginners: How to Build, Run, and Deploy Containers on a VPS/Cloud
Docker has become one of the most practical tools in modern software development because it solves a common problem: “It works on my laptop, but it doesn’t work on the server.” With Docker, you package your application and its dependencies into a container so it can run consistently across environments—local machine, VPS, or cloud.
This beginner-friendly guide will walk you through Docker from the ground up: what it is, how it works, how to create and run containers, and how to deploy them safely on a VPS or cloud instance.
This beginner-friendly guide will walk you through Docker from the ground up: what it is, how it works, how to create and run containers, and how to deploy them safely on a VPS or cloud instance.
1) What Is Docker (and What Is a Container)?
Docker in one sentence
Docker is a platform for building, shipping, and running applications inside containers.
Docker is a platform for building, shipping, and running applications inside containers.
Container vs Virtual Machine (VM)
A container is not a full virtual machine. Instead:A VM includes a full guest OS (heavier, more resources).A container shares the host OS kernel but isolates the app and its dependencies (lighter, faster startup).Containers are ideal for deploying web apps, APIs, background workers, and services because they are:Portable (same behavior anywhere)Reproducible (same build, same result)Isolated (dependencies won’t conflict with other apps)Easy to roll back (deploy by version/tag)
A container is not a full virtual machine. Instead:
A VM includes a full guest OS (heavier, more resources).
A container shares the host OS kernel but isolates the app and its dependencies (lighter, faster startup).
Containers are ideal for deploying web apps, APIs, background workers, and services because they are:
Portable (same behavior anywhere)
Reproducible (same build, same result)
Isolated (dependencies won’t conflict with other apps)
Easy to roll back (deploy by version/tag)
2) Key Docker Terms You Must Know
Image
An image is a blueprint (read-only template) for a container. It includes:your app code (optional)runtime (Node, Python, PHP, etc.)OS librariesdependenciesImages are usually built from a Dockerfile.
An image is a blueprint (read-only template) for a container. It includes:
your app code (optional)
runtime (Node, Python, PHP, etc.)
OS libraries
dependencies
Images are usually built from a Dockerfile.
Container
A container is a running instance of an image. You can start/stop/restart containers without reinstalling everything.
A container is a running instance of an image.
You can start/stop/restart containers without reinstalling everything.
Dockerfile
A Dockerfile is a set of instructions that tells Docker how to build an image.
A Dockerfile is a set of instructions that tells Docker how to build an image.
Registry (Docker Hub, GHCR, etc.)
A registry is where images are stored so servers can pull them:Docker HubGitHub Container Registry (GHCR)GitLab RegistryAWS ECR, GCP Artifact Registry, etc.
A registry is where images are stored so servers can pull them:
Docker Hub
GitHub Container Registry (GHCR)
GitLab Registry
AWS ECR, GCP Artifact Registry, etc.
Volumes
Volumes store persistent data outside the container lifecycle, useful for:databasesuploaded filesapplication state that must survive restarts
Volumes store persistent data outside the container lifecycle, useful for:
databases
uploaded files
application state that must survive restarts
3) Installing Docker (High-Level Guidance)
On a VPS/cloud instance, Docker is typically installed via official repositories. Since different Linux distros vary (Ubuntu, Debian, AlmaLinux, etc.), follow Docker’s official documentation for your OS. After installing, validate with:docker --versiondocker run hello-worldIf you’re deploying professionally, also install Docker Compose (now commonly docker compose).
On a VPS/cloud instance, Docker is typically installed via official repositories. Since different Linux distros vary (Ubuntu, Debian, AlmaLinux, etc.), follow Docker’s official documentation for your OS. After installing, validate with:
docker --version
docker run hello-world
If you’re deploying professionally, also install Docker Compose (now commonly
docker compose
).4) Basic Docker Commands (Beginner Toolkit)
Here are the commands you’ll use constantly:
Here are the commands you’ll use constantly:
Pull an image
docker pull nginx:latest
docker pull nginx:latest
Run a container
docker run -d --name web -p 8080:80 nginx:latest
-d runs in background (detached)--name gives it a readable name-p 8080:80 maps host port 8080 → container port 80
docker run -d --name web -p 8080:80 nginx:latest
-d
runs in background (detached)--name
gives it a readable name-p 8080:80
maps host port 8080 → container port 80List containers
docker ps
docker ps -a
docker ps
docker ps -a
View logs
docker logs web
docker logs -f web
docker logs web
docker logs -f web
Stop and remove
docker stop web
docker rm web
docker stop web
docker rm web
Remove images
docker rmi nginx:latest
docker rmi nginx:latest
5) Creating Your First Dockerfile (Example: Node.js Web App)
Let’s assume a simple Node.js app:package.jsonserver.js listening on port 3000
Let’s assume a simple Node.js app:
package.json
server.js
listening on port 3000
Example Dockerfile
Create a file named Dockerfile:FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "server.js"]
What this does:Uses a lightweight Node base imageCopies dependencies first (better caching)Installs production dependenciesCopies your app codeExposes port 3000Runs the app
Create a file named
Dockerfile
:FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "server.js"]
What this does:
Uses a lightweight Node base image
Copies dependencies first (better caching)
Installs production dependencies
Copies your app code
Exposes port 3000
Runs the app
Build the image
docker build -t myapp:1.0 .
docker build -t myapp:1.0 .
Run it
docker run -d --name myapp -p 3000:3000 myapp:1.0
Then test:http://YOUR_SERVER_IP:3000
docker run -d --name myapp -p 3000:3000 myapp:1.0
Then test:
http://YOUR_SERVER_IP:3000
6) A Better Way: Multi-Container Apps with Docker Compose
Real production apps often have multiple services:web appdatabase (PostgreSQL/MySQL)cache (Redis)Docker Compose lets you manage them as one “stack.”
Real production apps often have multiple services:
web app
database (PostgreSQL/MySQL)
cache (Redis)
Docker Compose lets you manage them as one “stack.”
Example: App + Postgres (docker-compose.yml)
services:
app:
build: .
container_name: myapp
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/mydb
depends_on:
- db
db:
image: postgres:16
container_name: mydb
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=mydb
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
services:
app:
build: .
container_name: myapp
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/mydb
depends_on:
- db
db:
image: postgres:16
container_name: mydb
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=mydb
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Start the stack
docker compose up -d --build
docker compose up -d --build
Stop the stack
docker compose down
docker compose down
Stop and remove (including volumes)
Be careful—this deletes database data:docker compose down -v
Be careful—this deletes database data:
docker compose down -v
7) Docker Networking: How Containers Talk to Each Other
In Docker Compose, services share a network by default. That means:The app container can reach the database at hostname dbYou don’t need to expose DB ports publiclyOnly expose ports that must be accessed from the internet (usually 80/443 via reverse proxy)This is a big security win compared to running everything directly on the host.
In Docker Compose, services share a network by default. That means:
The
app
container can reach the database at hostname db
You don’t need to expose DB ports publicly
Only expose ports that must be accessed from the internet (usually 80/443 via reverse proxy)
This is a big security win compared to running everything directly on the host.
8) Deploying Containers to a VPS/Cloud (Step-by-Step)
Here’s a clean and practical deployment flow used by many teams.
Here’s a clean and practical deployment flow used by many teams.
Step 1: Provision your VPS / cloud VM
Choose a server near your users. Make sure you have:SSH accessfirewall rulesenough RAM/CPU for your workload
Choose a server near your users. Make sure you have:
SSH access
firewall rules
enough RAM/CPU for your workload
Step 2: Install Docker + Docker Compose
After installation, ensure:Docker daemon is runningyour user can run Docker (or you use sudo)
After installation, ensure:
Docker daemon is running
your user can run Docker (or you use sudo)
Step 3: Upload your project (Git-based workflow)
On the server:git clone https://github.com/yourname/yourrepo.git
cd yourrepo
On the server:
git clone https://github.com/yourname/yourrepo.git
cd yourrepo
Step 4: Create production environment variables
Do not hardcode secrets in Compose. Common approaches:.env file on the server (not committed to Git)secret manager tools (more advanced)platform environment variable systems (PaaS)Example .env:DATABASE_URL=...
JWT_SECRET=...
Compose will auto-load .env by default in the project directory.
Do not hardcode secrets in Compose. Common approaches:
.env
file on the server (not committed to Git)secret manager tools (more advanced)
platform environment variable systems (PaaS)
Example
.env
:DATABASE_URL=...
JWT_SECRET=...
Compose will auto-load
.env
by default in the project directory.Step 5: Build and run
docker compose up -d --build
docker compose up -d --build
Step 6: Verify logs and health
docker compose ps
docker compose logs -f
docker compose ps
docker compose logs -f
9) Making It Production-Ready: Reverse Proxy + HTTPS
Running your app on port 3000 is fine for testing, but production should use:HTTPSstandard ports 80 and 443a reverse proxy (often Nginx, Traefik, or Caddy)
Running your app on port 3000 is fine for testing, but production should use:
HTTPS
standard ports 80 and 443
a reverse proxy (often Nginx, Traefik, or Caddy)
Common production pattern
Reverse proxy listens on 80/443Routes traffic to internal container portsTerminates SSL (Let’s Encrypt)If you’re a beginner, two approachable options:Caddy (simple auto-HTTPS, minimal config)Nginx + Certbot (classic, more manual)You can run the reverse proxy as a container too, but keep configuration clean and avoid exposing internal services directly.
Reverse proxy listens on 80/443
Routes traffic to internal container ports
Terminates SSL (Let’s Encrypt)
If you’re a beginner, two approachable options:
Caddy (simple auto-HTTPS, minimal config)
Nginx + Certbot (classic, more manual)
You can run the reverse proxy as a container too, but keep configuration clean and avoid exposing internal services directly.
10) Deploy Strategy: Updating Your App Without Downtime
At minimum, you want a repeatable update process.
At minimum, you want a repeatable update process.
Simple redeploy (basic)
On the server:git pull
docker compose up -d --build
This rebuilds the image if code changed and restarts containers as needed.
On the server:
git pull
docker compose up -d --build
This rebuilds the image if code changed and restarts containers as needed.
Better: Tag and push images to a registry
Instead of building on the server, you can:Build image in CI (GitHub Actions)Push to registry (GHCR/Docker Hub)Pull on server and restartThis is more professional because:server doesn’t need build toolchainsdeployment is faster and consistentyou can roll back by image tag
Instead of building on the server, you can:
Build image in CI (GitHub Actions)
Push to registry (GHCR/Docker Hub)
Pull on server and restart
This is more professional because:
server doesn’t need build toolchains
deployment is faster and consistent
you can roll back by image tag
11) Docker Volumes and Backups (Critical for Databases)
If you run Postgres/MySQL in Docker, the data must persist in a volume.
If you run Postgres/MySQL in Docker, the data must persist in a volume.
Backup mindset
A container is disposable; data is not.Good backup practices:Scheduled database dumps (daily)Store backups off-server (S3, another storage provider)Test restores regularlyIf you can afford it, consider managed databases (easier backups, monitoring, scaling).
A container is disposable; data is not.
Good backup practices:
Scheduled database dumps (daily)
Store backups off-server (S3, another storage provider)
Test restores regularly
If you can afford it, consider managed databases (easier backups, monitoring, scaling).
12) Security Basics for Docker on a VPS
Docker simplifies deployment, but you still must secure the host.Minimum best practices:Keep OS packages updatedUse SSH keys, disable password auth if possibleConfigure firewall: expose only 80/443 (and maybe SSH)Do not publish database ports publicly (avoid -p 5432:5432 unless necessary)Use strong secrets (not “admin123”)Limit container privileges (avoid --privileged unless required)Monitor logs and disk usage (containers can fill disk with logs)Also: never expose the Docker daemon port to the internet.
Docker simplifies deployment, but you still must secure the host.
Minimum best practices:
Keep OS packages updated
Use SSH keys, disable password auth if possible
Configure firewall: expose only 80/443 (and maybe SSH)
Do not publish database ports publicly (avoid
-p 5432:5432
unless necessary)Use strong secrets (not “admin123”)
Limit container privileges (avoid
--privileged
unless required)Monitor logs and disk usage (containers can fill disk with logs)
Also: never expose the Docker daemon port to the internet.
13) Common Beginner Mistakes (and How to Avoid Them)
Putting secrets in the Dockerfile Docker images can be shared. Keep secrets in env vars, not inside images.Not using volumes for databases If the container is removed, your data disappears unless stored in a volume.Publishing every service port Only publish what must be publicly accessible.Using latest everywherePin versions for reliability:postgres:16node:20-alpinenginx:1.26Ignoring logs and monitoringAt least set up basic log review and uptime checks.
Putting secrets in the Dockerfile
Docker images can be shared. Keep secrets in env vars, not inside images.
Not using volumes for databases
If the container is removed, your data disappears unless stored in a volume.
Publishing every service port
Only publish what must be publicly accessible.
Using
latest
everywherePin versions for reliability:
postgres:16
node:20-alpine
nginx:1.26
Ignoring logs and monitoring
At least set up basic log review and uptime checks.
Conclusion
Docker is one of the best technologies a beginner can learn for modern deployment. It helps you package apps reliably, run them consistently, and deploy them to VPS/cloud environments with fewer “it broke in production” surprises.To get started confidently:learn the core concepts (image, container, Dockerfile, volume)build and run locallyuse Docker Compose for multi-service appsdeploy to a VPS with a secure configurationadd HTTPS and a reverse proxy for real production useWith these fundamentals, you’ll be able to deploy everything from a simple website to a full production API stack in a clean, repeatable way.
Docker is one of the best technologies a beginner can learn for modern deployment. It helps you package apps reliably, run them consistently, and deploy them to VPS/cloud environments with fewer “it broke in production” surprises.
To get started confidently:
learn the core concepts (image, container, Dockerfile, volume)
build and run locally
use Docker Compose for multi-service apps
deploy to a VPS with a secure configuration
add HTTPS and a reverse proxy for real production use
With these fundamentals, you’ll be able to deploy everything from a simple website to a full production API stack in a clean, repeatable way.

Komentar
Posting Komentar