Start learning free

LESSON 151 OF 173 · BACKEND: SHIPPING IT

Install Before You Copy in JavaScript

Practice

The base image has Node.js, but nothing of the shop. COPY copies files from the shop's folder on your computer, where you run docker build, into the image: COPY source destination. A . as the destination is the image's current folder, /app thanks to WORKDIR; with more than one file to copy, you write it as a folder, with a slash at the end: ./. RUN runs a command inside the image while it is being built, and keeps what the command changed.

Each line of a Dockerfile makes a layer, a saved change to the image, and Docker keeps the layers in a cache. On the next build it reuses a layer, CACHED, as long as the line and the files it copies have not changed. From the first line that changed, every line runs again. So the order matters: what changes rarely goes at the top, what changes often at the bottom.

Here is the same idea for a program built on Python: its package list, requirements.txt, is copied and installed first, and the code last.

const dockerfile = [
  "FROM python:3.13-slim",
  "WORKDIR /srv",
  "COPY requirements.txt .",
  "RUN pip install -r requirements.txt",
  "COPY . .",
].join("\n");

Two files say which packages the shop needs: package.json, and package-lock.json, where npm wrote down the exact version of every package it installed on your computer. npm ci (a clean install) reads both and installs exactly the versions written in the lock file, into the folder node_modules.

The check builds your image, then changes app.js and builds again. When your lines are right, it prints:

$ docker build -t shop .
[1/6] FROM node:22-slim
[2/6] WORKDIR /app
[3/6] ENV NODE_ENV=production
[4/6] COPY package.json package-lock.json ./: copies package.json, package-lock.json into /app
[5/6] RUN npm ci: installs express 5.1.0 and the packages it needs, in the exact versions written in package-lock.json
[6/6] COPY . .: copies app.js, package.json, package-lock.json, Dockerfile into /app
In the image: /app/package.json, /app/package-lock.json, /app/app.js, /app/Dockerfile
You change app.js and build again:
[1/6] FROM node:22-slim: CACHED
[2/6] WORKDIR /app: CACHED
[3/6] ENV NODE_ENV=production: CACHED
[4/6] COPY package.json package-lock.json ./: CACHED
[5/6] RUN npm ci: CACHED
[6/6] COPY . .: runs again, app.js changed
npm ci was CACHED: a change to the code does not install the packages again

Your task: after the three lines of the base, add three lines to the string dockerfile: copy package.json and package-lock.json into the current folder, ./; install the packages with npm ci; then copy the whole shop folder into the current folder. A change to app.js must leave the install CACHED.


Assignment
Follow the Coding Tutorial to add the COPY, RUN and COPY lines to the shop's Dockerfile, in that order.


Hint
In COPY source destination, a dot as the source means everything in the shop's folder, and a dot as the destination means /app. npm can only read package.json and package-lock.json once a line above it has copied them in.


STEP 1 OF 3
    Ctrl + Enter to check

    Ship Dockerfile Install in JavaScript

    Keep going with JavaScript1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free