Getting Started with Docker: Building Containerized Apps From Scratch
You’ve heard the hype: “Everything runs in containers now.” But if you’ve never built one yourself, Docker can feel like magic—or voodoo. The truth? It’s neither. Docker is just a tool that packages your app and its environment so it runs the same everywhere. No more “but it works on my machine.” Let’s cut through the noise and build a real containerized app from scratch.
Why Bother With Docker?
Because consistency matters. Whether you're deploying to staging, production, or handing off to a teammate, Docker ensures your app runs in a predictable environment. It’s not just for ops teams—every developer should know how to containerize their app. And the learning curve? Not as steep as you think.
Step 1: Install Docker (Yes, Really)
Before anything, get Docker installed. Go to docker.com and grab Docker Desktop (macOS/Windows) or use your package manager on Linux.
Verify it works:
docker --version
docker run hello-world
If you see a “Hello from Docker!” message, you’re good.
Step 2: Write a Simple App
Let’s build a minimal Node.js app. You don’t need to be a Node expert—this is just an example. The concepts apply to Python, Go, Ruby, whatever.
Create a project:
mkdir my-docker-app
cd my-docker-app
npm init -y
npm install express
Create app.js:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from Docker!');
});
app.listen(PORT, () => {
console.log(`App running on http://localhost:${PORT}`);
});
Test it:
node app.js
Hit localhost:3000 in your browser. You should see the message. Good. Now let’s containerize it.
Step 3: Write a Dockerfile
This is where the magic happens. A Dockerfile defines how your container is built.
Create Dockerfile (no extension):
# Use an official Node runtime as the base image
FROM node:18-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy package.json and package-lock.json (if available)
COPY package*.json ./
# Install dependencies
RUN npm install
# 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", "app.js"]
A few things to note:
- We’re using
node:18-alpine—a lightweight Linux image with Node 18. -
WORKDIRsets where your app lives inside the container. - We copy
package.jsonfirst, install deps, then copy the rest. This leverages Docker’s layer caching—so if only your code changes, you don’t reinstall deps every time. -
CMDis the default command when the container starts.
Step 4: Build the Image
Now build your Docker image:
docker build -t my-node-app .
-
-t my-node-apptags the image with a name. - The
.tells Docker to build from the current directory.
You’ll see Docker step through each line in the Dockerfile. When it’s done, list your images:
docker images
You should see my-node-app in the list.
Step 5: Run the Container
Run it:
docker run -p 3000:3000 my-node-app
-
-p 3000:3000maps host port 3000 to container port 3000.
Now go to localhost:3000. Same message? Great. Your app is running in a container.
Try killing it with Ctrl+C. The container stops.
Want it to run in the background?
docker run -d -p 3000:3000 my-node-app
-d detaches it (runs in background). List running containers:
docker ps
Step 6: Clean Up (Because You Will Forget)
Containers keep piling up. Clean them like a pro:
# Stop all running containers
docker stop $(docker ps -q)
# Remove all containers
docker rm $(docker ps -aq)
# Remove all images
docker rmi $(docker images -q)
Or just use Docker Desktop’s UI if you prefer.
Step 7: Add a .dockerignore
Just like .gitignore, you can ignore files in your Docker build context.
Create .dockerignore:
node_modules
npm-debug.log
.git
.env
This keeps your build lean and avoids copying unnecessary or sensitive files.
Bonus: Multi-Stage Builds (For Real Apps)
When you build apps with compiled code (like React or Go), you don’t want build tools in your final image. Multi-stage builds fix that.
Example: a React app build:
Dockerfile
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Runtime stage
FROM nginx:alpine
COPY --from
---
☕ **Community-Focused**
Top comments (0)