Docker has fundamentally transformed the way developers build, test, and deploy applications by introducing a consistent, lightweight, and portable runtime environment. With its ability to package applications and their dependencies into isolated containers, Docker has eliminated the age-old challenge of “it works on my machine” while enabling seamless deployment across various environments. The part of “It’s working for me” used to be funny or sad depends on the day and the hour…
Whether you’re developing locally, testing in a CI/CD pipeline, or deploying to production, Docker provides the flexibility and scalability to streamline these processes. In this guide, we’ll explore the foundational concepts of Docker, dive into its practical uses, and demonstrate how you can harness its power to simplify workflows and achieve greater efficiency in your development and operations pipelines. Whether you’re a beginner or looking to refine your Docker skills, this walkthrough will equip you with the knowledge you need to use Docker effectively.
What is Docker?
Docker is a platform that packages applications and their dependencies into lightweight, portable containers. These containers can run consistently across any environment that has Docker installed.
Basic Docker Concepts
Images and Containers
- Image: A blueprint that contains everything needed to run an application
- Container: A running instance of an image
- Dockerfile: A script containing instructions to build an image
Key Commands
# Pull an image
docker pull nginx
# Run a container
docker run nginx
# List running containers
docker ps
# Stop a container
docker stop container_id
### How to get 'clean' quickly
# Remove all containers first (force stop and remove)
docker container stop $(docker container ls -aq)
docker container prune -f
# Remove all images (including those in use)
docker rmi -f $(docker images -q)
Development Environment Setup
Let’s create a simple Node.js application and containerize it.
- Create a
Dockerfile:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
- Create a
.dockerignore:
node_modules
npm-debug.log
- Use Docker Compose for local development. Create
docker-compose.yml:
version: '3'
services:
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
Development Best Practices
- Use volumes to mount source code for hot reloading
- Keep development dependencies separate
- Use environment variables for configuration
Testing Environment
Create a separate Docker configuration for testing:
# Dockerfile.test
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "test"]
Run tests in a containerized environment:
docker build -f Dockerfile.test -t myapp-test .
docker run myapp-test
Testing Best Practices
- Use multi-stage builds to keep test dependencies separate
- Run tests in isolation
- Set up CI/CD pipelines with Docker
Production Environment
Create an optimized production build:
# Dockerfile.prod
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm install --only=production
EXPOSE 3000
CMD ["npm", "start"]
Production Best Practices
- Security:
- Use specific image versions
- Run containers as non-root
- Scan images for vulnerabilities
docker scan myapp:latest
- Performance:
- Use multi-stage builds
- Minimize image layers
- Only install production dependencies
- Monitoring:
# Check container resource usage
docker stats
# View container logs
docker logs container_id
Deployment Example
Deploy to production using Docker Compose:
version: '3'
services:
app:
image: myapp:latest
restart: always
ports:
- "80:3000"
environment:
- NODE_ENV=production
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
Deployment Best Practices
- Use container orchestration (Kubernetes/Swarm)
- Implement health checks
- Set up proper logging
- Use secrets management
- Configure automatic restarts
Common Docker Commands Reference
# Build an image
docker build -t my-fe-app .
# Run container in detached mode
docker run -d my-fe-app
# View logs
docker logs -f container_id
# Execute command in running container
docker exec -it container_id sh
# Remove unused resources
docker system prune
Cheat Sheet
Conclusion
Docker provides a consistent environment across development, testing, and production. By following these best practices and examples, you can create a robust containerization strategy for your applications.
Remember to:
- Keep development and production configurations separate
- Optimize for security and performance in production
- Use Docker Compose for managing multi-container applications
- Implement proper monitoring and logging
- Regular security scanning and updates
- Have fun
Start small with a single container and gradually expand your Docker usage… Or walk before you run.
Be strong.
Discover more from Ido Green
Subscribe to get the latest posts sent to your email.