"It works on my machine" is the phrase that ended countless production deployments. A developer builds a Node.js app on Ubuntu 22.04 with Node 20. The CI server runs Amazon Linux 2 with Node 16. The staging environment has a different npm version. The production environment has conflicting system library versions. Nothing matches. Nothing is reproducible. Containers solve this by packaging the application and everything it needs - runtime, libraries, dependencies, environment variables, configuration - into a single portable unit. That unit runs identically on a developer's laptop, a CI runner, and a production EC2 instance. The environment is part of the artifact.
```bash ## Install Docker on Ubuntu (the official way) curl -fsSL https://get.docker.com | sh ## Add your user to the docker group (avoids needing sudo) sudo usermod -aG docker ubuntu newgrp docker ## apply group change without logging out ## Verify installation docker --version ## Docker version 27.x.x, build abc123 ## Run your first container docker run hello-world ``` > **Note:** `docker run hello-world` pulls the `hello-world` image from Docker Hub if it is not cached locally, starts a container, prints a message, and exits. This confirms Docker is installed and can reach Docker Hub.
Before you can run a container, you need an **image** - the immutable blueprint that defines the container's filesystem. Images are built in layers. Each instruction in a Dockerfile creates a new layer. Layers are cached and shared across images, which is why pulling a second Node.js image is much faster than the first - you already have the base layers.
Most engineers write Dockerfiles that work but are large, slow to build, or insecure. A production Dockerfile needs to be: small (less attack surface, faster deploys), reproducible (pinned versions), and built efficiently (layer caching maximized).
Containers are ephemeral - when a container is removed, everything written to its filesystem is gone. For databases, logs, uploaded files, and any other persistent data, you need **volumes**.
By default, containers are isolated from each other. For a web server to reach a database in another container, they need to be on the same Docker network. Docker's built-in DNS resolves container names to IPs automatically within a network. ```bash ## Create a user-defined bridge network docker network create razorpay-network ## Run Redis on the network docker run -d \ --name redis-cache \ --network razorpay-network \ redis:7-alpine ## Run the app on the same network - it can reach Redis by name docker run -d \ --name api-server \ --network razorpay-network \ -e REDIS_URL=redis://redis-cache:6379 \ -p 3000:3000 \ razorpay-api:v1.4.2 ## Verify the app can reach Redis by DNS name docker exec api-server ping -c 3 redis-cache ``` > **Note:** `redis://redis-cache:6379` works because Docker's built-in DNS resolver maps container names to their IP addresses on the same user-defined network. This only works on user-defined networks - NOT on the default bridge network. Always create a named network for multi-container apps. ---
"It works on my machine" is the phrase that ended countless production deployments. A developer builds a Node.js app on ...
> Note: docker run hello-world pulls the hello-world image from Docker Hub if it is not cached locally, starts a contain...
Before you can run a container, you need an image - the immutable blueprint that defines the container's filesystem. Ima...
Most engineers write Dockerfiles that work but are large, slow to build, or insecure. A production Dockerfile needs to b...
Containers are ephemeral - when a container is removed, everything written to its filesystem is gone. For databases, log...
By default, containers are isolated from each other. For a web server to reach a database in another container, they nee...
Running five docker run commands to start a local development environment is fragile and hard to share. Docker Compose d...
Containerize a real API server with a database backend, from scratch to running with Docker Compose. Create the project ...
Command Purpose docker ps List running containers docker ps -a List all containers docker logs -f <name> Follow containe...
Aligns directly with DevOps, Site Reliability (SRE), and Platform Engineering job descriptions.