As always, if you are just here to copy and paste, here is the final Dockerfile that will produce a 4.21MB image for your Vite app:
FROM node:21-alpine3.20 AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
FROM busybox:1.30 AS runner
WORKDIR /app
COPY --from=builder /app/dist .
CMD ["busybox", "httpd", "-f", "-v", "-p", "8080"]
and the .dockerignore file:
node_modules
dist
and the command to build and run the image:
docker build -t vite-app .
docker run -p 8080:8080 vite-app
Not just here to copy and paste? Let's go over what is happening in the Dockerfile!
The Setup
For this tutorial, I assume that you have some sort of Vite project setup. I based this Dockerfile on this starter template. It is a fairly simple npm
based project with a build command that outputs the files to a dist
folder. If you have a different setup, you might need to adjust the Dockerfile accordingly.
Usually, you would simply run npm install
and then npm run dev
to work locally. If you actually want to deploy your app somewhere, you generally dont want to use a dev server, but instead build your app and serve the files from a static file server. So instead, you would run npm run build
to create the files and then serve them with a different server.
Let's go into the details of the Dockerfile.
The Dockerfile
FROM node:21-alpine3.20 AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
FROM busybox:1.30 AS runner
WORKDIR /app
COPY --from=builder /app/dist .
CMD ["busybox", "httpd", "-f", "-v", "-p", "8080"]
So what is happening here?
- Builder stage:
- Uses Node.js 21 on Alpine 3.20, always tag the specific versions you are using to avoid unexpected errors!
- Installs dependencies, then copies and builds the app.
- Leverages Docker's layer caching for faster builds, first node_modules, then the rest of the app.
- Runner stage:
- Uses Busybox 1.30 for a minimal runtime. Again, always tag the specific versions you are using to avoid unexpected errors!
- Copies built files from the builder stage.
- Runs a simple HTTP server on port 8080. Pick any port you want, I just chose 8080 for this example.
This multi-stage approach keeps the final image small (4.21MB) by ditching build tools and only using busybox, which is a collection of common Unix utilities.
Make sure that you also add a .dockerignore file to ignore the node_modules and dist folder. This will speed up the build process and reduce the image size.
Deployment
I run a cloud hosting platform that makes it super easy to deploy Docker containers, so that is what I will show you here. The great thing about Docker is that you can easily deploy it anywhere, so don't think that Sliplane is the only option. You can use any cloud provider that supports Docker containers.
Anyway, if you have your changes committed and pushed to a git repository, you can deploy them to Sliplane by signing up and then creating a new service:
You won't have to change anything, so just click "Deploy" and Sliplane will take care of everything else.
After roughly 2 minutes everything should be up and running and you can access your app via the provided link. You can see the progress in the logs:
That's it! You have now successfully deployed a Vite app to the cloud. Awesome, isn't it?
Next Steps
Is there anything else you want to know? Do you need help dockerizing your Vite app? Do you need help deploying it to Sliplane? Feel free to reach out to me!
You can find me on X @JonasScholz19 or just comment here on this blog
Cheers,
Jonas