FROM is the first instruction of every Dockerfile. It names the image your build starts from: its filesystem, its tools and its configuration.
FROM node:20-alpinedocker.io/library/node:20-alpine
└─ registry ─┘└ namespace ┘└repo┘└─ tag ─┘Short names expand: node:20-alpine means docker.io/library/node:20-alpine. With no tag, Docker uses latest.
Variants of the same runtime
Official images publish several variants per version. For Node.js 20:
node:20 | node:20-alpine | |
|---|---|---|
| OS | Debian 12 (bookworm) | Alpine Linux 3.20 |
Size (docker images) | 1.1GB | 135MB |
| Shell | bash, sh | sh only |
| Package manager | apt-get | apk |
| C library | glibc | musl |
| Extra tools | curl, wget, ps, compilers | wget |
learner@pier:~$ docker images node
REPOSITORY TAG IMAGE ID CREATED SIZE
node 20 7aff5c847dd8 12 days ago 1.1GB
node 20-alpine 1647895d9ed3 12 days ago 135MBA smaller base means faster pulls, less disk and fewer packages to patch. Choose the full image when you need its tools, for example to compile native npm modules that expect glibc.
Pin the tag
| FROM | Changes when |
|---|---|
node / node:latest | Any new Node.js release, including major versions |
node:20-alpine | Node.js 20 patch releases and Alpine updates |
node:20-alpine@sha256:487e… | Never; the digest names one exact image |
Use at least a major version and a variant. A digest gives byte-for-byte repeatable builds; you then update it on purpose.
What the image inherits
Your image starts with everything the base image set:
learner@pier:~/status-page$ docker image inspect status-page:0.2 --format '{{json .Config.Entrypoint}}'
["docker-entrypoint.sh"]
learner@pier:~/status-page$ docker run --rm status-page:0.2 node --version
v20.18.0ENV NODE_VERSION, ENTRYPOINT and CMD all come from node:20-alpine. Any instruction you write later overrides the inherited value.
A tag that does not exist
The build stops at FROM when the tag cannot be resolved:
learner@pier:~/status-page$ docker build -t status-page:0.2 .
[+] Building 0.9s (3/3) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 116B 0.0s
=> ERROR [internal] load metadata for docker.io/library/node:20-alpne 0.8s
Dockerfile:1
--------------------
1 | >>> FROM node:20-alpne
2 | WORKDIR /app
--------------------
ERROR: failed to solve: docker.io/library/node:20-alpne: failed to resolve source metadata for docker.io/library/node:20-alpne: docker.io/library/node:20-alpne: not foundnot found on the FROM line means a typo in the repository or tag. Check the tag with docker pull before you edit the Dockerfile.