Quick Start Tutorial
This tutorial walks you through building, running, and managing your first Docker container. By the end, you will have hands-on experience with the most common Docker workflows.
Prerequisites
Before starting, ensure you have Docker installed on your system. Verify by running:
docker --version
docker compose versionIf Docker is not installed, follow the Installation Guide.
Step 1: Run Your First Container
The simplest way to start with Docker is to run an existing image from Docker Hub:
# Run the official hello-world image
docker run hello-worldYou should see output like:
Hello from Docker!
This message shows that your installation appears to be working correctly.
...What Happened?
- Docker checked for the
hello-worldimage locally. - The image was not found locally, so Docker pulled it from Docker Hub.
- Docker created a container from the image.
- The container ran, printed the message, and exited.
Step 2: Explore an Interactive Container
Run an interactive Ubuntu container:
# Run Ubuntu interactively
docker run -it ubuntu:22.04 /bin/bashInside the container, try some commands:
# Check the OS version
cat /etc/os-release
# Update packages and install a tool
apt-get update && apt-get install -y curl
# Check the hostname
hostname
# Exit the container
exitUnderstanding the Flags
| Flag | Description |
|---|---|
-i | Keep STDIN open (interactive) |
-t | Allocate a pseudo-TTY (terminal) |
-d | Run in detached mode (background) |
-p | Publish container ports to host |
-v | Bind mount a volume |
--name | Assign a name to the container |
--rm | Automatically remove container when it exits |
-e | Set environment variables |
Step 3: Run a Web Server
Start an Nginx web server:
# Run Nginx in the background, mapping port 8080 to container port 80
docker run -d --name my-nginx -p 8080:80 nginx:latestVerify it is running:
# List running containers
docker ps
# Access the web server
curl http://localhost:8080You should see the default Nginx welcome page HTML.
Manage the Container
# View container logs
docker logs my-nginx
# Follow logs in real-time
docker logs -f my-nginx
# Execute a command inside the running container
docker exec -it my-nginx /bin/bash
# Stop the container
docker stop my-nginx
# Start it again
docker start my-nginx
# Remove the container (must be stopped first)
docker stop my-nginx && docker rm my-nginxStep 4: Build Your First Image
Create a simple Node.js application and containerize it.
Create the Application
Create a project directory with the following files:
app.js:
const http = require('http');
const hostname = '0.0.0.0';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: 'Hello from Docker!',
timestamp: new Date().toISOString(),
hostname: require('os').hostname()
}));
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});package.json:
{
"name": "docker-quickstart",
"version": "1.0.0",
"description": "A simple Docker quick start app",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {}
}Dockerfile:
# Use the official Node.js 20 Alpine image
FROM node:20-alpine
# Set the working directory
WORKDIR /app
# Copy package files
COPY package.json ./
# Install dependencies
RUN npm install --production
# Copy the application code
COPY app.js ./
# Expose the port
EXPOSE 3000
# Define the startup command
CMD ["npm", "start"].dockerignore:
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignoreBuild the Image
# Build the image with a tag
docker build -t my-node-app:1.0 .
# Verify the image was created
docker images | grep my-node-appExpected output:
REPOSITORY TAG IMAGE ID CREATED SIZE
my-node-app 1.0 a1b2c3d4e5f6 10 seconds ago 130MBRun Your Custom Image
# Run the container
docker run -d --name my-app -p 3000:3000 my-node-app:1.0
# Test the application
curl http://localhost:3000Expected response:
{
"message": "Hello from Docker!",
"timestamp": "2025-01-15T10:30:00.000Z",
"hostname": "a1b2c3d4e5f6"
}Step 5: Use Docker Compose
Docker Compose allows you to define and run multi-container applications.
Create a Compose File
docker-compose.yml:
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
volumes:
- ./app.js:/app/app.js
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:Run with Compose
# Start all services
docker compose up -d
# View running services
docker compose ps
# View logs for all services
docker compose logs
# View logs for a specific service
docker compose logs web
# Stop all services
docker compose down
# Stop and remove volumes
docker compose down -vCompose Commands Reference
| Command | Description |
|---|---|
docker compose up | Create and start containers |
docker compose up -d | Start in detached mode |
docker compose down | Stop and remove containers |
docker compose ps | List containers |
docker compose logs | View output from containers |
docker compose build | Build or rebuild services |
docker compose pull | Pull service images |
docker compose restart | Restart services |
docker compose exec <svc> <cmd> | Execute command in running service |
Step 6: Work with Volumes
Volumes allow you to persist data and share data between containers.
# Create a named volume
docker volume create my-data
# Run a container with a volume
docker run -d \
--name db \
-v my-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=mysecret \
postgres:16
# List volumes
docker volume ls
# Inspect a volume
docker volume inspect my-data
# Remove a volume
docker volume rm my-dataBind Mounts for Development
# Mount current directory into container (great for development)
docker run -d \
--name dev-app \
-p 3000:3000 \
-v $(pwd):/app \
-w /app \
node:20-alpine \
npm startStep 7: Docker Networking Basics
Containers can communicate with each other through Docker networks:
# Create a custom network
docker network create my-network
# Run containers on the same network
docker run -d --name api --network my-network my-node-app:1.0
docker run -d --name cache --network my-network redis:7-alpine
# Containers can reach each other by name
docker exec api ping cache
# List networks
docker network ls
# Inspect a network
docker network inspect my-network
# Remove a network
docker network rm my-networkStep 8: Clean Up
After completing this tutorial, clean up your Docker environment:
# Stop all running containers
docker stop $(docker ps -q)
# Remove all stopped containers
docker container prune
# Remove unused images
docker image prune
# Remove unused volumes
docker volume prune
# Remove unused networks
docker network prune
# Nuclear option: remove everything unused
docker system prune -a --volumesSystem Cleanup Summary
| Command | What It Removes |
|---|---|
docker container prune | All stopped containers |
docker image prune | Dangling images |
docker image prune -a | All unused images |
docker volume prune | All unused volumes |
docker network prune | All unused networks |
docker system prune | Containers, networks, dangling images |
docker system prune -a | All unused objects including images |
Quick Reference Card
# Images
docker build -t name:tag . # Build an image
docker images # List images
docker pull image:tag # Pull an image
docker rmi image:tag # Remove an image
# Containers
docker run -d -p 80:80 image # Run a container
docker ps # List running containers
docker stop <name> # Stop a container
docker rm <name> # Remove a container
docker logs <name> # View logs
docker exec -it <name> sh # Shell into container
# Compose
docker compose up -d # Start services
docker compose down # Stop services
docker compose logs # View logs
# Cleanup
docker system prune -a # Remove all unused dataNext Steps
- Image Building Best Practices — Optimize your Docker images
- Docker Networking Guide — Deep dive into container networking
- Storage Management — Advanced volume and storage strategies
- Docker Compose Quick Start — Learn more about multi-container applications
- Multi-stage Builds — Reduce image size with multi-stage builds