5.3Docker for Node.js
The essentials in 30 seconds
- The end of “it works on my machine”: the container ships the app with its environment and runs identically everywhere.
- Image → container: the Dockerfile describes the recipe, docker build freezes the image, docker run launches the container.
- Compose for the stack: app + database + cache described in one file and launched together — onboarding in one command.
Running case — Salim containerises in Algiers
Salim's API runs perfectly on his machine in Algiers — but crashes on his colleague's (different Node version, missing variable). He writes a Dockerfile: base Node image, dependencies installed in the image, start command. Then a Compose file with the database: a single launch brings up the whole stack. Continuation of cases 5.1-5.2 — Salim makes his app reproducible everywhere.
Continuation of cases 5.1-5.2 — Salim moves from “it works on my machine” to “the same everywhere”.
1. Containerising: image and container
Docker solves “it works on my machine” by packaging the application with its whole environment (Node version, dependencies, configuration) in an isolated, portable container that runs identically everywhere: workstation, colleague, server, cloud. Concepts: the image (frozen model of the app + environment, defined by a Dockerfile — the recipe: base Node image, copy the code, install dependencies, start command) and the container (a running instance of an image). You build (docker build), you run (docker run). .dockerignore excludes the needless from the image (node_modules — dependencies are installed INSIDE the image). Salim no longer debates versions: the environment travels with the code.
Reflex: anything specific to your machine and missing from the image is a future crash elsewhere — the image must contain everything.
2. Docker Compose and benefits
For a realistic stack (app + database + cache), Docker Compose (docker-compose.yml) defines several containers and their relationships, launched together with one command (docker compose up). A single file describes the whole stack, reproducible identically — and onboarding becomes trivial: a new developer runs one command and gets the whole environment. Benefits: reproducibility (identical everywhere), isolation (no conflicts between apps and versions), portability (any Docker host), easy deployment (deploying = launching the container — see 5.4). Salim adds the database to Compose: his colleague starts in minutes.
Docker is a standard of modern development and a cross-cutting skill (DevOps): the basics are enough to start, advanced orchestration will come as needed.
3. The right dosage for a developer
No need to become an infrastructure expert: aim for the useful basics — writing a simple Dockerfile, building and running, orchestrating app + database with Compose, excluding the needless via .dockerignore. Master Node first (your core craft), add Docker when you work as a team, prepare a deployment, or manage several services. To avoid: including node_modules in the image, aiming for advanced orchestration before the basics, or containerising a tiny learning script with no real need. Salim keeps his Dockerfile readable: six understood instructions beat a copied recipe.
The right profile: a developer who knows the basics of operations — autonomous, able not only to code but to deliver.
Did you know?
Same image, same behaviour — everywhere.
🔎 Concrete example — Salim's Dockerfile
The image recipe, readable in six lines.
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "app.js"]
# .dockerignore : node_modules
# docker compose up → app + database together
Reading: each instruction has a role — base, dependencies, code, start.
Lesson: an understood Dockerfile beats a copied recipe.
Section vocabulary
- Docker
- Tool that packages the app with its environment in a portable container.
Simple example: Salim's API runs the same in Algiers and on his colleague's machine.
What it is not: a simple Node installer on each machine.
Reflex: does my app still depend on my machine?
- Image
- Frozen model of the app + environment, built from the Dockerfile.
Simple example: Salim builds a versioned image of each release.
What it is not: the running container itself.
Reflex: can I rebuild this image identically?
- Dockerfile
- Build recipe of the image (base, code, dependencies, start).
Simple example: Six readable instructions for Salim's API.
What it is not: a script that installs Node by hand on a server.
Reflex: is each instruction understood, not copied?
- Container
- A running instance of an image, isolated and portable.
Simple example: Salim launches an identical container in dev and in staging.
What it is not: the frozen image itself.
Reflex: do dev and prod launch the same image?
- Docker Compose
- File describing several containers launched together.
Simple example: Salim's app + database started with a single command.
What it is not: advanced Kubernetes-style orchestration.
Reflex: does a new dev start with one command?
In practice — Containerise a Node application
- Write a Dockerfile: start from a Node image, copy the code, install dependencies (npm install), define the start command. Add a .dockerignore (node_modules…).
- Build the image (`docker build`) and launch a container (`docker run`); check that the application runs in the container.
- Orchestrate with Docker Compose: a docker-compose.yml defining the Node app AND its database, launched together (`docker compose up`).
- Enjoy the benefits: reproducibility (identical everywhere), isolation, and onboarding (one `docker compose up` is enough for the whole environment).
Ready-to-say script — proposing Docker to the team
“Our API works on my machine but nowhere else: it is an environment problem, not a code problem. I suggest a simple Dockerfile — six instructions — plus a Compose with the database. Everyone will run the same image, and a newcomer will start with one command. We keep it readable and skip advanced orchestration for now.”
To say in a team meeting to get containerisation adopted without aiming for DevOps expertise.
Copy-paste template — generic Node Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
# .dockerignore :
# node_modules
# npm-debug.log
# .git
Solo / small budget
Salim alone: a simple Dockerfile with no Compose is enough — the image already freezes the environment.
Small business / small team
Compose app + database: each colleague starts the full stack with no manual installation.
SME in Algiers
Salim shares the image with the team in Algiers: everyone tests the same version, no more machine gaps.
Team starting out
Pair: one writes the Dockerfile, the other re-reads it line by line; build tested on two machines before adoption.
✓ Best practices
- Master Node first, then learn the Docker basics.
- Add a .dockerignore (exclude node_modules).
- Use Docker Compose to orchestrate app + database (fast onboarding).
✗ Common pitfalls
- Including node_modules in the image (install it in the image via npm install).
- Wanting to master advanced orchestration before the basics.
- Containerising a tiny learning script with no real need.
Key takeaways
- DOCKER packages the application WITH its environment in an isolated, portable CONTAINER that runs IDENTICALLY everywhere — the end of “it works on my machine”.
- IMAGE (frozen model, defined by a DOCKERFILE) → CONTAINER (instance). `docker build` / `docker run`. .dockerignore excludes node_modules.
- DOCKER COMPOSE defines SEVERAL containers (app + database + cache) launched together (`docker compose up`) — describes the whole stack, reproducible.
- Benefits: REPRODUCIBILITY, isolation, portability, easy deployment, fast onboarding. Modern standard (cross-cutting DevOps).
48h challenge — apply tomorrow
Write your app's Dockerfile (template above) and run it in a container: does it respond the same as on your machine?
- I can explain image vs container in one sentence.
- My Dockerfile builds an image that runs.
- I know why node_modules is not in it.
Frequently asked questions
What does Docker concretely bring, and is it necessary for a Node developer?
Docker mainly brings reproducibility: the end of “it works on my machine” (the container ships everything, so it runs identically everywhere). Also: isolation (several apps/versions with no conflicts), portability (any Docker host), easy deployment (deploying = launching the container), fast onboarding (one docker compose up brings up the whole stack). For learning Node or small solo projects, not strictly. For professional development, in a team or with deployment, it has become almost unavoidable — and cross-cutting. Master Node first, then the Docker basics.
Docker, deployment, CI/CD... must I become a DevOps expert on top of being a developer?
No, not an expert — but knowing the basics helps enormously: autonomy (putting your work into production), employability (job ads asking for Docker/deployment/CI-CD), better collaboration (apps that are easy to deploy), full picture of the cycle. Aim for the basics: containerising and Compose (not advanced orchestration), deploying on a simple platform, a simple CI/CD pipeline, secrets and config in environment variables, notions of logs/monitoring/HTTPS. The right profile: a developer who knows the basics of operations — able not only to code but to deliver.
What problem does Docker mainly solve?