DEV Community

Orbit Websites
Orbit Websites

Posted on

Getting Started with Docker: Building Containerized Apps From Scratch

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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}`);
});
Enter fullscreen mode Exit fullscreen mode

Test it:

node app.js
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

A few things to note:

  • We’re using node:18-alpine—a lightweight Linux image with Node 18.
  • WORKDIR sets where your app lives inside the container.
  • We copy package.json first, 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.
  • CMD is the default command when the container starts.

Step 4: Build the Image

Now build your Docker image:

docker build -t my-node-app .
Enter fullscreen mode Exit fullscreen mode
  • -t my-node-app tags 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
Enter fullscreen mode Exit fullscreen mode

You should see my-node-app in the list.


Step 5: Run the Container

Run it:

docker run -p 3000:3000 my-node-app
Enter fullscreen mode Exit fullscreen mode
  • -p 3000:3000 maps 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
Enter fullscreen mode Exit fullscreen mode

-d detaches it (runs in background). List running containers:

docker ps
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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**
Enter fullscreen mode Exit fullscreen mode

Top comments (0)