Docker for Developers: Images, Containers, and Compose
You've probably heard about Docker and containers, but maybe you're not sure how they fit into your daily development workflow. Or perhaps you've tried Docker, but the concepts of images, containers, and Compose feel confusing. This guide will walk you through the essentials with practical examples, so you can start using Docker effectively in your projects.
What Are Docker Images and Containers?
Think of a Docker image as a blueprint for your application. It contains everything needed to run your code: the operating system, runtime, libraries, and your application files. Images are immutable and built from a Dockerfile.
A container is a running instance of an image. When you start a container, Docker creates an isolated environment from the image. You can run multiple containers from the same image, each with its own state.
Key Differences
| Image | Container |
|---|---|
| Read-only template | Runnable instance |
| Built from Dockerfile | Created from image |
| Stored in registry | Runs on host |
| Immutable | Ephemeral (can be stopped, started, deleted) |
Building Your First Docker Image
Let's create a simple Node.js app and containerize it. Start with a Dockerfile in your project root:
# Use an official Node.js runtime as a parent image
FROM node:18-alpine
# Set the working directory
WORKDIR /app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy the rest of the application code
COPY . .
# Expose the port the app runs on
EXPOSE 3000
# Define the command to run the app
CMD ["node", "server.js"]
Build the image with:
docker build -t my-node-app .
Run a container from the image:
docker run -p 3000:3000 -d my-node-app
Your app is now accessible at http://localhost:3000.
Managing Containers
Here are essential commands to manage containers:
docker ps– list running containersdocker ps -a– list all containers (including stopped)docker stop <container_id>– stop a running containerdocker rm <container_id>– remove a stopped containerdocker logs <container_id>– view container logsdocker exec -it <container_id> sh– open a shell inside a running container
Simplifying Multi-Container Apps with Docker Compose
Real applications often need multiple services: a web server, a database, a cache, etc. Managing these with individual docker run commands is tedious. Docker Compose lets you define and run multi-container applications using a YAML file.
Create a docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Start all services with:
docker compose up -d
Stop and remove them with:
docker compose down
Best Practices for Development
- Use .dockerignore to exclude unnecessary files (node_modules, .git) from the build context.
- Leverage layer caching: order Dockerfile instructions so that dependencies are installed before copying source code.
- Use multi-stage builds to keep production images small.
- Store data in volumes for databases and other stateful services.
- Use Compose for local development to replicate production-like environments.
FAQ
What is the difference between an image and a container?
An image is a read-only template that defines the application and its dependencies. A container is a running instance of an image, with a writable layer on top.
Can I use Docker Compose in production?
Docker Compose is primarily designed for development and testing. For production, consider orchestration tools like Kubernetes or Docker Swarm.
How do I persist data in Docker?
Use volumes or bind mounts. Volumes are managed by Docker and are the preferred way to persist data generated by containers.
Ready to containerize your app? If you need to convert documentation or guides to PDF for your team, try our Word to PDF converter to share polished docs.