Node v21.6.2 (npm v10.2.4)
Create project
Let’s use the command line to create our project my-vite-vue-ssr
.
npm create vite-extra@latest my-vite-vue-ssr -- --template ssr-vue
Scaffolding project in /Users/harianto/Projects/my-vite-vue-ssr...
Done. Now run:
cd my-vite-vue-ssr
npm install
npm run dev
Follow other commands then continue.
Save your current Node & NPM version (for NVM).
node -v > .nvmrc
nvm use
.Initiate git with git init
. And save the Initial state.
git init
Initialized empty Git repository in ~/git/my-vite-vue-ssr/.git/
# Stage all files
git add .
# Commit and Message it
git commit -avm "INIT my-vite-vue-ssr Node `node -v`"
Docker things
Add .dockerignore
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
# .nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# Mac OSX
.DS_Store
# Vim swap files
*.swp
# VSCode Settings
.vscode
# APP IGNORES
package-lock.json
.git
.docker-mount
Create Docker Node Image
Before we create Dockerfile
we need to edit the package.json
. In scripts
we add more handy command lines.
I’m using Docker Hub User as dockeruser
and project name as my-vite-vue-ssr
. Use your own preferences and change the code accordingly.
"scripts": {
"docker": "cross-env NODE_ENV=production npm run dev",
"docker:build": "npm run build && docker build -t dockeruser/my-vite-vue-ssr .",
"docker:run": "docker run --rm -p 3000:3000 dockeruser/my-vite-vue-ssr",
"docker:push": "npm run docker:build && docker push dockeruser/my-vite-vue-ssr"
},
package.json
file.See we’re using port 3000 instead of 5173
And move all devDependencies
lines to dependencies
.
During Docker build the script will only check dependencies
.
See below the result.
{
"name": "my-vite-vue-ssr",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --ssrManifest --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.js --outDir dist/server",
"preview": "cross-env NODE_ENV=production node server",
"docker": "cross-env NODE_ENV=production npm run dev",
"docker:build": "npm run build && docker build -t dockeruser/my-vite-vue-ssr .",
"docker:run": "docker run --rm -p 3000:3000 dockeruser/my-vite-vue-ssr",
"docker:push": "npm run docker:build && docker push dockeruser/my-vite-vue-ssr"
},
"dependencies": {
"compression": "^1.7.4",
"express": "^4.18.2",
"sirv": "^2.0.4",
"vue": "^3.3.13",
"@vitejs/plugin-vue": "^4.5.2",
"cross-env": "^7.0.3",
"vite": "^5.0.10"
},
"devDependencies": {}
}
package.json
. Resulting linesCreate Dockerfile
Since my node version is v21.6.2
. I’m looking which Alpine version from https://hub.docker.com/_/node/ and look for available version number -alpine
.

node:21.6.2-alpine
FROM node:21.6.2-alpine
EXPOSE 3000
ENV NODE_ENV=production
ENV PORT=3000
ENV NODE_WORKDIR=/app
WORKDIR $NODE_WORKDIR
COPY package.json $NODE_WORKDIR/
RUN npm shrinkwrap
RUN npm i
COPY . $NODE_WORKDIR
RUN npm run build
CMD ["npm", "run", "docker"]
Dockerfile
. In Docker environment the files are being copied to /app
directory. And exposes port 3000Build Docker Image
Create Docker Image: dockeruser/my-vite-vue-ssr
.
Since we made special commands in package.json
we can build from it, without knowing long strings of commands. Just peek it in.
npm run docker:build
npm run build && docker build -t dockeruser/my-vite-vue-ssr .
Hopefully everything goes well, and we can look up with in command: docker images
.
REPOSITORY TAG IMAGE ID CREATED SIZE
dockeruser/my-vite-vue-ssr latest 323b18f70290 About a minute ago 211MB
Test Docker Image
Let’s use the command and check the web: http://localhost:3000/
npm run docker:run
Kill Running Image
To kill the image, first we need to see what’s running again on port 3000. With this command below we can see what’s going on.
docker ps | grep 3000
7d32fd2396d8 dockeruser/my-vite-vue-ssr "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 0.0.0.0:3000->3000/tcp stupefied_cohen
7d32fd2396d8
Use this info 7d32fd2396d8
to kill the process.
docker rm -f 7d32fd2396d8
7d32fd2396d8
Other useful docker commands
# see docker images
docker images
# remove IMAGE ID ex. baabdd69cf7a
docker rmi -f baabdd69cf7a
# see dangling images
docker images -q --filter "dangling=true"
# remove untagged images
docker rmi -f `docker images -q --filter "dangling=true"` > /dev/null 2>&1 || echo "Nothing to remove"
Conclusion
This is the way to build your own docker image. Every time you have new changes you can run again: npm run docker-build
.
And if you have Docker Hub you can push it with: npm run docker:push
.
Also don’t forget to commit your git.
Let me know what you think of this article?