RUN
FROM ubuntu
RUN apt-get update && apt-get install vim
Copy the code
RUN
FROM ubuntu
RUN apt-get update
RUN apt-get install vim
Copy the code
COPY
ADD
RUN
The layer is similar to Git commits.
RUN
Merge layers into one using Docker multi-phase builds
index.js
const express = require('express') const app = express() app.get('/', (req, res) => res.send('Hello World! ')) app.listen(3000, () => { console.log(`Example app listening on port 3000! `)})Copy the code
package.json
{" name ":" hello, world ", "version" : "1.0.0", "main" : "index. Js", "dependencies" : {" express ":" ^ 4.16.2 "}, "scripts" : { "start": "node index.js" } }Copy the code
Dockerfile
FROM node:8
EXPOSE 3000
WORKDIR /app
COPY package.json index.js ./
RUN npm install
CMD ["npm", "start"]
Copy the code
$ docker build -t node-vanilla .
Copy the code
$ docker run -p 3000:3000 -ti --rm --init node-vanilla
Copy the code
http://localhost:3000
Dockerfile
COPY
RUN
$ docker history node-vanilla IMAGE CREATED BY SIZE 075d229d3f48 /bin/sh -c #(nop) CMD ["npm" "start"] 0B bc8c3cc813ae /bin/sh -c NPM install 2.91MB bac31AFb6f42 /bin/sh -c #(nop) COPY multi: 3071DDd474429E1 /bin/sh -c #(nop) COPY multi: 3071DDd474429E1... 364B 500a9fbef90e /bin/sh -c #(nop) WORKDIR /app 0B 78b28027dfbf /bin/sh -c #(nop) EXPOSE 3000 0B b87c2ad8344d /bin/sh -c #(nop) CMD ["node"] 0B <missing> /bin/sh -c set -ex && for key in 6A010... 4.17MB <missing> /bin/sh -c #(nop) ENV YARN_VERSION= 1.3.20b <missing> /bin/sh -c ARCH= &&dpkgarch ="$(DPKG --print... 569 MB <missing> /bin/sh -c #(nop) ENV NODE_VERSION= 8.9.4b <missing> /bin/sh -c set -ex && for key in 94AE3... 129kB <missing> /bin/sh -c groupadd --gid 1000 node && use... 335kB <missing> /bin/sh -c set -ex; apt-get update; Apt - ge... 324MB <missing> /bin/sh -c apt-get update && apt-get install... 324MB <missing> /bin/sh -c apt-get update && apt-get install... 123MB <missing> /bin/sh -c set -ex; if ! Command -v GPG > /... 0B <missing> /bin/sh -c apt-get update && apt-get install... 446 MB <missing> /bin/sh -c #(nop) CMD ["bash"] 0B <missing> /bin/sh -c #(nop) ADD file: 1DD78a123212328bd... 123MBCopy the code
Dockerfile
Dockerfile
FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM node:8
COPY --from=build /app /
EXPOSE 3000
CMD ["index.js"]
Copy the code
Dockerfile
$ docker build -t node-multi-stage .
Copy the code
$ docker history node-multi-stage IMAGE CREATED BY SIZE 331b81a245b1 /bin/sh -c #(nop) CMD ["index.js"] 0B bdfc932314af /bin/sh -c #(nop) EXPOSE 3000 0B f8992f6c62a6 /bin/sh -c #(nop) COPY dir:e2b57dff89be62f77... 1.62MB b87c2AD8344D /bin/sh -c #(nop) CMD ["node"] 0B <missing> /bin/sh -c set -ex && for key in 6A010... 4.17MB <missing> /bin/sh -c #(nop) ENV YARN_VERSION= 1.3.20b <missing> /bin/sh -c ARCH= &&dpkgarch ="$(DPKG --print... 569 MB <missing> /bin/sh -c #(nop) ENV NODE_VERSION= 8.9.4b <missing> /bin/sh -c set -ex && for key in 94AE3... 129kB <missing> /bin/sh -c groupadd --gid 1000 node && use... 335kB <missing> /bin/sh -c set -ex; apt-get update; Apt - ge... 324MB <missing> /bin/sh -c apt-get update && apt-get install... 324MB <missing> /bin/sh -c apt-get update && apt-get install... 123MB <missing> /bin/sh -c set -ex; if ! Command -v GPG > /... 0B <missing> /bin/sh -c apt-get update && apt-get install... 446 MB <missing> /bin/sh -c #(nop) CMD ["bash"] 0B <missing> /bin/sh -c #(nop) ADD file: 1DD78a123212328bd... 123MBCopy the code
$ docker images | grep node-
node-multi-stage 331b81a245b1 678MB
node-vanilla 075d229d3f48 679MB
Copy the code
Use Distroless to remove all the baggage from the container
yarn
npm
bash
So how do you do that?
GoogleCloudPlatform/distroless
The “Distroless” image contains only the application and its runtime dependencies. Package managers, shells, and other programs found in standard Linux distributions are not included.
FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM gcr.io/distroless/nodejs
COPY --from=build /app /
EXPOSE 3000
CMD ["index.js"]
Copy the code
$ docker build -t node-distroless .
Copy the code
$ docker run -p 3000:3000 -ti --rm --init node-distroless
Copy the code
http://localhost:3000
$docker images | grep node - distroless node - distroless 7 b4db3b7f1e5 76.7 MBCopy the code
Only 76.76 MB.
$docker exec-ti < < _docker_id> bashCopy the code
bash
$docker exec-ti < < _docker_id> nodeCopy the code
It is important to note that we should not attach to containers for debugging in a production environment, but rather rely on proper logging and monitoring.
Use Alpine as a smaller base image
Alpine Linux
Based on a
musl libcand
busyboxA lightweight security-oriented Linux distribution.
Dockerfile
node:8-alpine
FROM node:8 as build
WORKDIR /app
COPY package.json index.js ./
RUN npm install
FROM node:8-alpine
COPY --from=build /app /
EXPOSE 3000
CMD ["npm", "start"]
Copy the code
$ docker build -t node-alpine .
Copy the code
$docker images | grep node - alpine node - alpine aa1f85f8e724 69.7 MBCopy the code
69.7 MB!
$ docker run -p 3000:3000 -ti --rm --init node-alpine
Example app listening on port 3000!
Copy the code
$ docker exec -ti 9d8e97e307d7 bash
OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown
Copy the code
sh
$ docker exec -ti 9d8e97e307d7 sh
/ #
Copy the code
- Glibc is the most commonly used and faster
- Muslc takes up less space and focuses on safety
How do I select the base image?
If you’re running in a production environment and you care about security,
Note:
Minimizing the attack surface is OWASP’s recommended practice.
If you’re more concerned with size, switch to Alpine Base mirroring.
this
this
Native base images are great for testing and development.
node:8
node:8
gcr.io/distroless/nodejs
node:8-alpine
Original link:3 simple tricks for smaller Docker images(translation:Liang Xiaoyong)