Lets start by creating a Dockerfile in the root of the project
Dockerfile
# use node 16 alpine image
FROM node:16-alpine
# create work directory in app folder
WORKDIR /app
# install required packages for node image
RUN apk --no-cache add openssh g++ make python3 git
# copy over package.json files
COPY package.json /app/
COPY package-lock.json /app/
# install all depencies
RUN npm ci && npm cache clean --force
# copy over all files to the work directory
ADD . /app
# build the project
RUN npm run build
# expose the host and port 3000 to the server
ENV HOST 0.0.0.0
EXPOSE 3000
# run the build project with node
ENTRYPOINT ["node", ".output/server/index.mjs"]
now lets make a docker-compose file
docker-compose.yml
version: "3"
services:
nuxt-docker-example:
container_name: nuxt-docker-example
build:
context: .
dockerfile: DockerFile
ports:
- "3000:3000"
build the docker image
docker compose up --build
you can add -d
at the end to run it in the background
if everything went alright, open localhost:3000
and we can see the project running.
Docker image size
If we look over at the docker desktop and see the image size its over 850MB
We can reduce the size of the image by adjusting the Dockerfile
using multi-stage builds
Docker multi stage
Multistage builds make use of one Dockerfile with multiple FROM instructions. Each of these FROM instructions is a new build stage that can COPY artifacts from the previous stages. By going and copying the build artifact from the build stage, you get rid of all the unnecessary packages and files. All these steps create additional layers, and you want to eliminate them from the final image. thus reducing the size of the final image
lets adjust the dockerfile
# use node 16 alpine image as build image
FROM node:16-alpine as builder
# create work directory in app folder
WORKDIR /app
# install required packages for node image
RUN apk --no-cache add openssh g++ make python3 git
# copy over package.json files
COPY package.json /app/
COPY package-lock.json /app/
# install all depencies
RUN npm ci && npm cache clean --force
# copy over all files to the work directory
ADD . /app
# build the project
RUN npm run build
# start final image
FROM node:16-alpine
WORKDIR /app
# copy over build files from builder step
COPY --from=builder /app/.output app/.output
COPY --from=builder /app/.nuxt app/.nuxt
# expose the host and port 3000 to the server
ENV HOST 0.0.0.0
EXPOSE 3000
# run the build project with node
ENTRYPOINT ["node", ".output/server/index.mjs"]
the first line of code in the file changed to
FROM node:16-alpine as builder
this tells docker that this stage is just for building our application
after npm run build
command we added another FROM command
FROM node:16-alpine
because this is a new stage we specified a WORKDIR
again, then we copied over the files from the build stage to the final stage.
And that's it, the image size is now 364MB! A big difference from the previous 886MB
Top comments (5)
just want to notice. you don't need copy all files of project from first stage. it is enough to copy only .output directory. so then your image will be much smaller)
nice one, thank you
I will update the article with these changes
Is that what you're saying?
...
ADD ./output /app
build the project
RUN npm run build
...
Sorry, I'm new to this, I don't quite understand what you mean, could you explain it in detail
Thanks!
I've changed the Dockerfile:
COPY --from=builder /app/.output /app/.output
very helpful and insightful