I am trying to improve my docker images by minimizing as much as possible their size. In order to do so I did the follow steps with a nestjs example as a use case:
nest new testing-docker-slim
and then inside of it I created the following docker file, with multistage and also some differences on npm installation of packages in between production and development:
FROM node:17-alpine as base
FROM base as development
WORKDIR /app
COPY . .
RUN npm i
CMD ["sh", "-c", "npm run start:dev"]
FROM base as staging
WORKDIR /app
COPY . .
RUN npm i
RUN npm run build
CMD ["sh", "-c", "npm run start:prod"]
FROM base as production
WORKDIR /app
COPY --from=staging /app/dist ./dist
COPY --from=staging /app/package.json /app/package-lock.json ./
RUN npm i --production
CMD ["sh", "-c", "npm run start:prod"]
Added a docker ignore file with the following entries:
node_modules
.git
.idea
Created a docker images with the following command:
docker build . --target production -t testing-docker-slim
And also with this command another images:
docker build . --target development -t testing-docker-slim-dev
The images have this size:
testing-docker-slim-dev latest 4408308966c3 22 minutes ago 471MB
testing-docker-slim latest c688ff1bedc2 22 minutes ago 185MB
So we already have a reasonable improvement on size of image from 471Mb to 185Mb... Still I did a bit more of research and found out about 2 tools, dive and docker slim.
dive in both images says that it is a 99% image efficiency score... so did not found out much with it that I could do with the image to improve.
then I saw docker slim which claims to have an extraordinary level of compression of images, and I run the following command:
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock dslim/docker-slim build testing-docker-slim --expose 3000 --http-probe=false --continue-after=1
creating a beautiful image of this size:
testing-docker-slim.slim latest 99a51a88a0f2 9 minutes ago 89.9MB
this size of image is a reasonable one but when I run the image to see if it is working as expected, it crashes with this error:
> testing-docker-slim@0.0.1 start:prod
> node dist/main
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module 'iterare'
Require stack:
- /app/node_modules/@nestjs/common/pipes/validation.pipe.js
- /app/node_modules/@nestjs/common/pipes/parse-array.pipe.js
- /app/node_modules/@nestjs/common/pipes/index.js
- /app/node_modules/@nestjs/common/index.js
- /app/node_modules/@nestjs/core/discovery/discovery-module.js
- /app/node_modules/@nestjs/core/discovery/index.js
- /app/node_modules/@nestjs/core/index.js
- /app/dist/main.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:999:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/app/node_modules/@nestjs/common/pipes/validation.pipe.js:5:19)
at Module._compile (node:internal/modules/cjs/loader:1097:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:999:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/app/node_modules/@nestjs/common/pipes/validation.pipe.js',
'/app/node_modules/@nestjs/common/pipes/parse-array.pipe.js',
'/app/node_modules/@nestjs/common/pipes/index.js',
'/app/node_modules/@nestjs/common/index.js',
'/app/node_modules/@nestjs/core/discovery/discovery-module.js',
'/app/node_modules/@nestjs/core/discovery/index.js',
'/app/node_modules/@nestjs/core/index.js',
'/app/dist/main.js'
]
}
Node.js v17.4.0
the same happens when I use docker slim on the multistage for development, but the docker multistage without using docker slim works perfectly fine.
Did you use docker multistage with docker slim for production stage with a nodejs if possible nestjs application? Do you have any further advice to improve image size of a docker nodejs / nestjs application?