Optimize docker NodeJS deployments

@patrick I optimized the Dockerfile for NodeJS deployments, check the end of this post

Until Wappler releases an update to fix this, yes

Here’s your optimized Dockerfile: (edit: fixed the issue on the following post)

FROM node:16-bullseye-slim

ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV

ARG PORT=3000
ENV PORT $PORT
EXPOSE $PORT

RUN mkdir /opt/node_app
ENV PATH /opt/node_app/node_modules/.bin:$PATH

WORKDIR /opt/node_app

COPY package.json ./
RUN npm install --no-optional --production --no-package-lock

COPY . .
CMD [ "nodemon", "./index.js" ]

After saving the file, switch the target to your local environment (if not already), and then switch it back to Live, only then you can attempt to deploy. The first deployment will still take an eternity, but subsequent deploys will skip the slow npm install step, and therefore deploy within a few seconds

1 Like

That is a huge optimization that I was looking for a long time!

Using this cuts deployment time significantly as the large npm install command is ran just once or only when the package.json is changed.

So well done @Apple - we will implement this in the next update.

Some additional info:

1 Like

Also changed the:

RUN npm install --no-optional --production --no-package-lock

to:

RUN npm install --no-package-lock

as the --no-optional and --production are no longer required and default on production environments as well their syntax is changed to --omit=dev which is default

That would be great @George

Can you make updating existing docker files opt in when you push that stuff with the next update? I customized mine quite heavily for CI/CD and E2E testing. If not no worries because I can do a git revert but an opt in option for existing Dockerfiles would be great.

Could you provide a sample of what are you changing to the Dockerfile ?

Currently we regenerate it fully indeed. It is kind of difficult to track down what to change and what not otherwise.

In docker-compose.yml file, we do partial updates only of the stuff we need.

My bad. No need to not overwrite the Dockerfile in my case. I forgot that you store the Wappler Dockerfile under targets while I have mine somewhere else, and I deploy from GitLab CI/CD, so not via Wappler.

I adjusted a few things, including the suggestions from apple.

using Alpine:

FROM node:18-alpine

Updating the system

RUN apk update && apk upgrade && \
    apk add --no-cache git

Hardcoded the port:

ENV PORT 80
EXPOSE 80

Getting rid of nodemon

CMD [ "./index.js" ]

And more, but the other things don’t make sense without showing the complete .gitlab-ci.yml. I’m basically running E2E tests first, then building the image with a dedi runner server, pushing the image to our repository, running knex migrations, and then deploying the image to the cluster.

1 Like

@karh wants to know your CI stuff :slight_smile:

1 Like

I’ll need to clean it up a little and remove things that are very specific to my use case like pausing bull queues on the target server and my specific knex settings. Does @karh have a thread for that? I don’t want to pollute that one even more with my own use cases. :sweat_smile: I also thought about making a tutorial series about CI/CD with Wappler.

1 Like

We are also considering offering more options about which process manager to use. Nodemon, pm2 or none

1 Like

Yeah nodemon is great for development but not for production imo. The new watch mode added in Node 19 will most likely make nodemon obsolete for development as well.

1 Like

Here is how my dockerfile looks to have it deploy on Caprover while still in dev tartget. I usually just set usage = development not production, then set different target folders in the same dev usage versus creating new usage for production. My workaround is that I build the image then push it docker hub then pull it from Docker hub on to the deployed server then I use env values to target my resources external databases etc. So the cmd ./index.js is very important on my since I am always copying the entire folders to the server and using the package.json for all dependencies, etc.

Swap lines 16 and 17 for faster image build :rocket:

2 Likes

I can get rid of line 17 for sure but not line 16

you don’t need to get rid of them but just swap them for proper caching

I see.

Implemented in Wappler 5.4.3