简体   繁体   中英

How to minimize properly a nestjs / nodejs application with docker slim or other alternatives?

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?

As mentioned by the previous comments I took into consideration the Dockerfile of this template https://github.com/jmcdo29/nest-docker-template Some of the key points on it were the order of the stages + the node prune created by TJ.

Last but not least for making docker slim to work I needed to add a flag to the line of docker slim that mentions in their documentation to make it work:

docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock dslim/docker-slim build testing --expose 3000 --http-probe=false --continue-after=1 --include-path=/app

the last flat --include-path=/app did effectively add more size to the slim version of the docker image but made it work as expected, making a good gain on size overall.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM