Well, there's this Node.js app that I built using Typescript + ExpressJS, and now I'm trying to setup docker to have both a working development container and a production one.
I'd like to have only one Dockerfile in order to use the multi-stage building process.
My project consists of the root folder, inside of it there are all these dockerfile and compose files, and also my package.json, src/ folder, yarn.lock and etc.
For now I have this:
Dockerfile
FROM node:14.18.1-alpine3.14 as base
ENV APP=/app
WORKDIR $APP
COPY . $APP/
RUN yarn install --frozen-lockfile &&\
rm -rf "$(yarn cache dir)"
RUN yarn build
FROM base as prod
ENV APP=/home/node/app
WORKDIR $APP
RUN chown node:node $APP
USER node
COPY --chown=node:node --from=base ./app/dist/ $APP/dist/
COPY --chown=node:node package.json yarn.lock $APP/
RUN NODE_ENV=production yarn install --frozen-lockfile &&\
rm -rf "$(yarn cache dir)"
If I build the base stage only, this is the image I get:
355.65 MB of image size.
Now if I check how big the node_modules
inside the image is, this is:
That's ok for a dev node_modules.
Checking the layers with
dive
, I get these:
You can see that 237 MB of those 355 is the node_modules folder.
Now, the production part.
If I build to the prod
target of the dockerfile, that's my image size:
That's even bigger than the dev one.
Checking the node_modules size inside of that image:
Wen from 237 to only 36 MB, really good
But now if I check the layers from that image, that's the result:
The 237 MB node_modules is still there, that's almost the entire image size. How can I avoid having that thresh in my production image? Without that, the result image should be something like 80 MB only, really better than 391.
Please, help me with that!!!
just fixed the problem by replacing FROM base as prod
by FROM node:14.18.1-alpine3.14 as prod
. The first method was caching all the base layers in the final build.