Skip to content

Commit 548e6cd

Browse files
[feat] update vue.js sample guide to use dhi example (#23822)
## Description This PR adds a DHI-based Dockerfile example demonstrating how to build an Vue.js application using the dhi-node image and serve it through the dhi-nginx image. ## Reviews - [x] Technical review
1 parent 2edaefd commit 548e6cd

2 files changed

Lines changed: 103 additions & 16 deletions

File tree

content/guides/vuejs/containerize.md

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ By the end of this guide, you will:
2929
- Containerize an Vue.js application using Docker.
3030
- Create and optimize a Dockerfile for production builds.
3131
- Use multi-stage builds to minimize image size.
32-
- Serve the application efficiently with a custom NGINX configuration.
32+
- Serve the application efficiently with a custom Nginx configuration.
3333
- Build secure and maintainable Docker images by following best practices.
3434

3535
---
@@ -78,7 +78,7 @@ For consistency, please use the same responses shown in the example below when p
7878
| Question | Answer |
7979
|------------------------------------------------------------|-----------------|
8080
| What application platform does your project use? | Node |
81-
| What version of Node do you want to use? | 23.11.0-alpine |
81+
| What version of Node do you want to use? | 24.12.0-alpine |
8282
| Which package manager do you want to use? | npm |
8383
| Do you want to run "npm run build" before starting server? | yes |
8484
| What directory is your build output to? | dist |
@@ -106,7 +106,7 @@ The default Dockerfile generated by `docker init` provides a solid foundation fo
106106
In this step, you’ll improve the Dockerfile and configuration files by following best practices:
107107

108108
- Use multi-stage builds to keep the final image clean and small
109-
- Serve the app using NGINX, a fast and secure web server
109+
- Serve the app using Nginx, a fast and secure web server
110110
- Improve performance and security by only including what’s needed
111111

112112
These updates help ensure your app is easy to deploy, fast to load, and production-ready.
@@ -118,13 +118,92 @@ These updates help ensure your app is easy to deploy, fast to load, and producti
118118

119119
### Step 2: Configure the Dockerfile
120120

121+
Before creating a Dockerfile, you need to choose a base image. You can either use the [Node.js Official Image](https://hub.docker.com/_/node) or a Docker Hardened Image (DHI) from the [Hardened Image catalog](https://hub.docker.com/hardened-images/catalog).
122+
123+
Choosing DHI offers the advantage of a production-ready image that is lightweight and secure. For more information, see [Docker Hardened Images](https://docs.docker.com/dhi/).
124+
125+
> [!IMPORTANT]
126+
> This guide uses a stable Node.js LTS image tag that is considered secure when the guide is written. Because new releases and security patches are published regularly, the tag shown here may no longer be the safest option when you follow the guide. Always review the latest available image tags and select a secure, up-to-date version before building or deploying your application.
127+
>
128+
> Official Node.js Docker Images: https://hub.docker.com/_/node
129+
130+
{{< tabs >}}
131+
{{< tab name="Using Docker Hardened Images" >}}
132+
Docker Hardened Images (DHIs) are available for Node.js in the [Docker Hardened Images catalog](https://hub.docker.com/hardened-images/catalog/dhi/node). Docker Hardened Images are freely available to everyone with no subscription required. You can pull and use them like any other Docker image after signing in to the DHI registry. For more information, see the [DHI quickstart](/dhi/get-started/) guide.
133+
134+
1. Sign in to the DHI registry:
135+
```console
136+
$ docker login dhi.io
137+
```
138+
139+
2. Pull the Node.js DHI (check the catalog for available versions):
140+
```console
141+
$ docker pull dhi.io/node:24-alpine3.22-dev
142+
```
143+
144+
3. Pull the Nginx DHI (check the catalog for available versions):
145+
```console
146+
$ docker pull dhi.io/nginx:1.28.0-alpine3.21-dev
147+
```
148+
149+
In the following Dockerfile, the `FROM` instructions use `dhi.io/node:24-alpine3.22-dev` and `dhi.io/nginx:1.28.0-alpine3.21-dev` as the base images.
150+
151+
```dockerfile
152+
# =========================================
153+
# Stage 1: Build the Vue.js Application
154+
# =========================================
155+
# Use a lightweight DHI Node.js image for building
156+
FROM dhi.io/node:24-alpine3.22-dev AS builder
157+
158+
# Set the working directory inside the container
159+
WORKDIR /app
160+
161+
# Copy package-related files first to leverage Docker's caching mechanism
162+
COPY package.json package-lock.json* ./
163+
164+
# Install project dependencies using npm ci (ensures a clean, reproducible install)
165+
RUN --mount=type=cache,target=/root/.npm npm ci
166+
167+
# Copy the rest of the application source code into the container
168+
COPY . .
169+
170+
# Build the Vue.js application
171+
RUN npm run build
172+
173+
# =========================================
174+
# Stage 2: Prepare Nginx to Serve Static Files
175+
# =========================================
176+
177+
FROM dhi.io/nginx:1.28.0-alpine3.21-dev AS runner
178+
179+
# Copy custom Nginx config
180+
COPY nginx.conf /etc/nginx/nginx.conf
181+
182+
# Copy the static build output from the build stage to Nginx's default HTML serving directory
183+
COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html
184+
185+
# Use a built-in non-root user for security best practices
186+
USER nginx
187+
188+
# Expose port 8080 to allow HTTP traffic
189+
# Note: The default Nginx container now listens on port 8080 instead of 80
190+
EXPOSE 8080
191+
192+
# Start Nginx directly with custom config
193+
ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"]
194+
CMD ["-g", "daemon off;"]
195+
```
196+
197+
{{< /tab >}}
198+
{{< tab name="Using the Docker Official Image" >}}
199+
121200
Replace the contents of your current `Dockerfile` with the optimized configuration below. This setup is tailored specifically for building and serving Vue.js applications in a clean, efficient, and production-ready environment.
122201

123202
```dockerfile
124203
# =========================================
125204
# Stage 1: Build the Vue.js Application
126205
# =========================================
127-
ARG NODE_VERSION=23.11.0-alpine
206+
ARG NODE_VERSION=24.12.0-alpine
128207
ARG NGINX_VERSION=alpine3.22
129208

130209
# Use a lightweight Node.js image for building (customizable via ARG)
@@ -134,7 +213,7 @@ FROM node:${NODE_VERSION} AS builder
134213
WORKDIR /app
135214

136215
# Copy package-related files first to leverage Docker's caching mechanism
137-
COPY package.json package-lock.json ./
216+
COPY package.json package-lock.json* ./
138217

139218
# Install project dependencies using npm ci (ensures a clean, reproducible install)
140219
RUN --mount=type=cache,target=/root/.npm npm ci
@@ -151,26 +230,34 @@ RUN npm run build
151230

152231
FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS runner
153232

154-
# Use a built-in non-root user for security best practices
155-
USER nginx
156-
157233
# Copy custom Nginx config
158234
COPY nginx.conf /etc/nginx/nginx.conf
159235

160-
161236
# Copy the static build output from the build stage to Nginx's default HTML serving directory
162237
COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html
163238

239+
# Use a built-in non-root user for security best practices
240+
USER nginx
241+
164242
# Expose port 8080 to allow HTTP traffic
165-
# Note: The default NGINX container now listens on port 8080 instead of 80
243+
# Note: The default Nginx container now listens on port 8080 instead of 80
166244
EXPOSE 8080
167245

168246
# Start Nginx directly with custom config
169247
ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"]
170248
CMD ["-g", "daemon off;"]
171-
172249
```
173250

251+
> [!NOTE]
252+
> We are using nginx-unprivileged instead of the standard Nginx image to follow security best practices.
253+
> Running as a non-root user in the final image:
254+
>- Reduces the attack surface
255+
>- Aligns with Docker’s recommendations for container hardening
256+
>- Helps comply with stricter security policies in production environments
257+
258+
{{< /tab >}}
259+
{{< /tabs >}}
260+
174261
### Step 3: Configure the .dockerignore file
175262

176263
The `.dockerignore` file plays a crucial role in optimizing your Docker image by specifying which files and directories should be excluded from the build context.
@@ -268,12 +355,12 @@ docker-compose.override.yml
268355

269356
### Step 4: Create the `nginx.conf` file
270357

271-
To serve your Vue.js application efficiently inside the container, you’ll configure NGINX with a custom setup. This configuration is optimized for performance, browser caching, gzip compression, and support for client-side routing.
358+
To serve your Vue.js application efficiently inside the container, you’ll configure Nginx with a custom setup. This configuration is optimized for performance, browser caching, gzip compression, and support for client-side routing.
272359

273360
Create a file named `nginx.conf` in the root of your project directory, and add the following content:
274361

275362
> [!NOTE]
276-
> To learn more about configuring NGINX, see the [official NGINX documentation](https://nginx.org/en/docs/).
363+
> To learn more about configuring Nginx, see the [official Nginx documentation](https://nginx.org/en/docs/).
277364
278365
```nginx
279366
worker_processes auto;
@@ -339,7 +426,7 @@ With your custom configuration in place, you're now ready to build the Docker im
339426

340427
The updated setup includes:
341428

342-
- The updated setup includes a clean, production-ready NGINX configuration tailored specifically for Vue.js.
429+
- The updated setup includes a clean, production-ready Nginx configuration tailored specifically for Vue.js.
343430
- Efficient multi-stage Docker build, ensuring a small and secure final image.
344431

345432
After completing the previous steps, your project directory should now contain the following files:

content/guides/vuejs/develop.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Create a file named `Dockerfile.dev` in your project root with the following con
3838
# =========================================
3939
# Stage 1: Develop the Vue.js Application
4040
# =========================================
41-
ARG NODE_VERSION=23.11.0-alpine
41+
ARG NODE_VERSION=24.12.0-alpine
4242

4343
# Use a lightweight Node.js image for development
4444
FROM node:${NODE_VERSION} AS dev
@@ -50,7 +50,7 @@ ENV NODE_ENV=development
5050
WORKDIR /app
5151

5252
# Copy package-related files first to leverage Docker's caching mechanism
53-
COPY package.json package-lock.json ./
53+
COPY package.json package-lock.json* ./
5454

5555
# Install project dependencies
5656
RUN --mount=type=cache,target=/root/.npm npm install

0 commit comments

Comments
 (0)