Docker for Beginners: Install, Run & Deploy Your First Container
A complete beginner's guide to Docker — from installation to running containers, building images, Docker Compose, and deploying real applications. No prior container experience needed.
What Is Docker?
Docker packages your application and all its dependencies into a container — a lightweight, portable unit that runs the same way everywhere. No more "it works on my machine" problems.
Think of it like this:
- A virtual machine emulates an entire OS (heavy, slow to start)
- A container shares the host OS kernel but isolates the application (lightweight, starts in seconds)
Traditional: App → OS → Hardware
Virtual Machine: App → Guest OS → Hypervisor → Host OS → Hardware
Docker: App → Container Runtime → Host OS → Hardware
Why developers use Docker:
- Consistent environments across dev, staging, and production
- Instant setup —
docker runinstead of installing 20 dependencies - Easy scaling — run 10 copies of your app with one command
- Clean system — remove a container and everything is gone
Step 1: Install Docker
Ubuntu / Debian
CentOS / RHEL / Fedora
Windows / macOS
Download Docker Desktop from docker.com. It includes Docker Engine, CLI, and Docker Compose.
Post-Install: Run Docker Without sudo
Verify Installation
You should see "Hello from Docker!" — your first container just ran.
Step 2: Core Concepts
Images vs Containers
| Concept | Analogy | Description | |---------|---------|-------------| | Image | Blueprint / Recipe | Read-only template with OS, dependencies, and app code | | Container | Running instance | A live process created from an image | | Registry | App Store | Where images are stored (Docker Hub, GitHub Container Registry) |
One image can spawn multiple containers:
Docker Hub
Docker Hub is the default public registry. Thousands of pre-built images are available:
Step 3: Essential Docker Commands
Run a Container
-d— run in background (detached)-p 8080:80— map host port 8080 to container port 80--name my-web— give it a friendly name
Open http://localhost:8080 — you'll see the Nginx welcome page.
Manage Containers
View Logs
Execute Commands Inside a Container
Manage Images
Clean Up Everything
Step 4: Build Your Own Image
Create a Simple Node.js App
Create a project folder:
Create app.js:
Create package.json:
Write a Dockerfile
Create Dockerfile:
Build the Image
-t my-app:1.0— tag it with name and version.— build context (current directory)
Run Your Custom Image
Test it:
Dockerfile Best Practices
Step 5: Volumes — Persistent Data
Containers are ephemeral — when removed, their data is lost. Use volumes to persist data:
Even if you remove and recreate the container, the database data persists.
Bind Mounts (map host folder)
Edit files on your host, changes appear instantly in the container. Great for development.
Volume Commands
Step 6: Docker Compose — Multi-Container Apps
Most real applications need multiple services (app + database + cache). Docker Compose defines everything in one YAML file.
Example: Node.js + PostgreSQL + Redis
Create docker-compose.yml:
Compose Commands
Example: Monitoring Stack (Grafana + Prometheus)
One command and you have a full monitoring stack:
Step 7: Networking
Default Bridge Network
Containers on the same Docker Compose file can reach each other by service name:
Custom Networks
Network Commands
Step 8: Environment Variables & Secrets
Pass Environment Variables
.env File
DATABASE_URL=postgres://postgres:secretpass@db:5432/myapp
REDIS_URL=redis://cache:6379
NODE_ENV=production
API_KEY=your-api-key-here
Security tip: Never bake secrets into your Docker image. Always pass them at runtime via environment variables or Docker secrets.
Step 9: Deploy to Production
Push to Docker Hub
Deploy on a Remote Server
Deploy with Docker Compose
Copy your docker-compose.yml to the server and run:
Restart Policies
| Policy | Behavior |
|--------|----------|
| no | Never restart (default) |
| always | Always restart, including on boot |
| unless-stopped | Restart unless manually stopped |
| on-failure:3 | Restart up to 3 times on failure |
Common Mistakes to Avoid
1. Using :latest tag in production
2. Running as root
3. Not using .dockerignore
Create .dockerignore:
node_modules
.git
.env
*.log
Dockerfile
docker-compose.yml
This prevents copying unnecessary files into the image, making builds faster and images smaller.
4. Too many layers