Recently I've created a NuxtJS application that will run in SSR mode, this is deployed to Cloud Run on GCP via a docker image.
In order to allow the autoscaling to work quicker and to allow quicker start ups I wanted to reduce the docker size of the application to as small as possible.
When you're first starting with NuxtJS they recommend a dockerfile
you can use for your application, but it isn't optimized work size.
Below is the typical dockerfile
for Nuxt applications.
FROM node:16
WORKDIR /usr/src/app
COPY . ./
RUN yarn
EXPOSE 8080
ENV HOST=0.0.0.0
ENV PORT=8080
RUN yarn build
CMD [ "yarn", "start" ]
On a standard application, this will create an image size around 500MB.
What can we do to reduce the docker image size?
Dependencies
The node module folder is one of the largest folders in the application. This is because the dockerfile
above will install all the dependencies needed for both development and production.
But if you're deploying the application from this dockerfile
you don't need development dependencies such as jest
.
Use the --production
option in the yarn install
command.
yarn install --production
This will install all packages in the dependencies
property and ignore all in devDependencies
within your package.json
.
Nuxt Build Standalone
When you run nuxt build
it will create the client and server files the applications needs to run the application.
These are stored in the .nuxt/dist
folder, but the server.js
file will still depend on files stored in the node_modules
folders.
Therefore you will need to install all the dependencies rather than just the dependencies needs to run the Nuxt application.
There is an option on the build command called Standalone. This will move the dependencies used from node_modules
into the .nuxt/dist/server.js
file, so we don't need the node_modules anymore.
If after the build is successful you get errors about modules missing from node_modules
folder then you might have modules loaded in your nuxt.config.js
modules
property. For standalone to work correctly you need to move these over to buildModules
.
Nuxt Start
The only package you would need to run nuxt is nuxt
package itself, but you don't need the entire nuxt
package you can use nuxt start
to run your application.
There's a separate package that you can use which is optimized for running SSR bundles.
yarn add nuxt-start
Final Dockerfile
FROM node:16 as builder
WORKDIR /usr/src/builder
ADD . ./
RUN yarn install --production
RUN yarn build --standalone
FROM node:16-alpine as starter
WORKDIR /usr/src/app
RUN yarn add "[email protected]"
COPY --from=builder /usr/src/builder/.nuxt /usr/src/app/.nuxt
COPY --from=builder /usr/src/builder/nuxt.config.js /usr/src/app/
COPY --from=builder /usr/src/builder/static /usr/src/app/
ENV HOST=0.0.0.0
ENV PORT=8080
ENTRYPOINT ["npx", "nuxt-start"]
EXPOSE 8080