TL;DR
- Image = blueprint (immutable). Container = running instance.
- Dockerfile →
docker build → Image → docker run → Container.
- Layers are cached. Order Dockerfile commands from least→most changing.
Essential Commands
# Images
docker build -t myapp . # Build from Dockerfile
docker images # List images
docker rmi myapp # Remove image
# Containers
docker run -d -p 3000:3000 myapp # Run detached, map port
docker ps # List running containers
docker ps -a # Include stopped
docker stop <id> # Stop gracefully
docker rm <id> # Remove container
docker logs <id> # View logs
docker exec -it <id> sh # Shell into container
Dockerfile (Node.js)
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "dist/main.js"]
Docker Compose
# docker-compose.yml
services:
app:
build: .
ports: ["3000:3000"]
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on: [db]
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes: [pgdata:/var/lib/postgresql/data]
volumes:
pgdata:
Quick Reference
| Command |
Purpose |
docker compose up -d |
Start all services |
docker compose down |
Stop + remove |
docker compose logs -f |
Follow logs |
docker system prune |
Clean unused data |
docker volume ls |
List volumes |