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.