Skip to content

🐳 Dockerizing a Node.js Express App

This guide walks you through packaging your Node.js Express app into a Docker container so it runs the same everywhere β€” your laptop, your teammate’s machine, or any cloud server. πŸš€


πŸ”₯ Key Terms (Quick Recap)

  • Image: A blueprint for your app β€” like a recipe.
  • Container: The actual running app built from that recipe.
  • Dockerfile: The file that tells Docker how to build your image.
  • Port Mapping: Connecting your machine’s port to the container’s port.

πŸš€ The Simple 3-Step Flow

1️⃣ Your Express App Files
πŸ‘‡ (You run: docker build)
2️⃣ A Docker Image (Your app, packed and ready) πŸ“¦
πŸ‘‡ (You run: docker run)
3️⃣ A Running Server β†’ Hit it at http://localhost:4000 πŸŽ‰


πŸ“ 1. Project File Structure

Here’s what your project folder should look like:

express/
β”œβ”€β”€ node_modules/ ← auto-generated, don't touch
β”œβ”€β”€ Dockerfile ← Docker instructions
β”œβ”€β”€ .dockerignore ← files to exclude from the image
β”œβ”€β”€ index.js ← your Express app
β”œβ”€β”€ package-lock.json ← auto-generated lockfile
└── package.json ← app metadata & dependencies

package.json

{
"name": "express",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"type": "commonjs",
"dependencies": {
"express": "^5.2.1"
}
}

πŸ“ 2. Create a .dockerignore

Keep the image lean. Create .dockerignore in your project root:

Terminal window
node_modules
.git
.gitignore
npm-debug.log

This stops Docker from copying your local node_modules into the image β€” it’ll install its own fresh copy instead.


🐳 3. Create the Dockerfile

Create a file named Dockerfile in your project root:

# Use the lightweight Node.js 22 image
FROM node:22-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy package files first (this helps Docker cache layers)
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of your app files
COPY . .
# Set a default port via environment variable
ENV PORT=3000
# Start the app
CMD ["node", "index.js"]

What does ENV PORT=3000 do? It sets a default environment variable inside the container. Your app reads it with process.env.PORT β€” just like a normal .env file, but baked into the image.

πŸ’‘ 3 Ways to Pass Environment Variables

β‘  Baked into the Dockerfile (default)

ENV PORT=3000

The container always uses 3000 unless you override it.


β‘‘ Using a .env file (recommended for real projects)

Create a .env file in your project root:

Terminal window
PORT=4000
DB_URL=mongodb://localhost:27017/mydb
SECRET_KEY=supersecret

Then pass it to docker run:

Terminal window
docker run -p 4000:4000 --env-file .env --rm express-app
  • --env-file .env β†’ Loads all variables from your .env file into the container.

⚠️ Add .env to your .dockerignore so it doesn’t get copied into the image itself β€” just pass it at runtime.


β‘’ Inline with -e (quick one-off overrides)

Terminal window
docker run -p 5000:5000 -e PORT=5000 --rm express-app

πŸ“ 4. Your index.js

Here’s the basic Express app that runs inside the container:

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello World from a Docker container! 🐳');
});
app.listen(port, () => {
console.log(`App listening on port ${port}!`);
});

The app reads PORT from the environment, so you can change it at runtime without touching the code.


πŸ› οΈ 4. Build the Docker Image

Run this in your project root:

Terminal window
docker build -t express-app .

What this means:

  • docker build β†’ Build an image from the Dockerfile
  • -t express-app β†’ Name (tag) the image express-app
  • . β†’ Use the current folder

πŸš€ 5. Run the Container

Terminal window
docker run -p 4000:3000 --rm express-app

What this means:

  • -p 4000:3000 β†’ Map your machine’s port 4000 to the container’s port 3000
  • --rm β†’ Auto-delete the container when it stops (keeps things tidy)
  • express-app β†’ The image to run

Now open: πŸ‘‰ http://localhost:4000 πŸŽ‰


βš™οΈ Override the Port at Runtime

Want to run on a different port? Pass the PORT environment variable:

Terminal window
docker run -p 5000:5000 -e PORT=5000 --rm express-app
  • -e PORT=5000 β†’ Sets the PORT env variable inside the container
  • -p 5000:5000 β†’ Maps your machine’s 5000 to the container’s 5000

βœ… Quick Summary

  1. Create .dockerignore
  2. Create Dockerfile
  3. Build image:
    Terminal window
    docker build -t express-app .
  4. Run container:
    Terminal window
    docker run -p 4000:3000 --rm express-app
  5. Open: http://localhost:4000 πŸš€

πŸ“ Notes

  • Change the -p flag ports anytime β€” just keep host:container format.
  • --rm is optional but great during development to avoid orphan containers piling up.
  • For production, consider running with -d (detached mode) so it runs in the background:
    Terminal window
    docker run -d -p 4000:3000 express-app