From 9466d33afe4d04ac5e8b85a3541784085357a3fa Mon Sep 17 00:00:00 2001 From: "kristiyan.velkov" Date: Mon, 8 Dec 2025 16:04:19 +0200 Subject: [PATCH] [feat] added dhi example for vue.js sample guide --- content/guides/vuejs/containerize.md | 98 ++++++++++++++++++++++++---- content/guides/vuejs/develop.md | 2 +- 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/content/guides/vuejs/containerize.md b/content/guides/vuejs/containerize.md index cc60262495c7..aa9d39838e6a 100644 --- a/content/guides/vuejs/containerize.md +++ b/content/guides/vuejs/containerize.md @@ -29,7 +29,7 @@ By the end of this guide, you will: - Containerize an Vue.js application using Docker. - Create and optimize a Dockerfile for production builds. - Use multi-stage builds to minimize image size. -- Serve the application efficiently with a custom NGINX configuration. +- Serve the application efficiently with a custom Nginx configuration. - Build secure and maintainable Docker images by following best practices. --- @@ -78,7 +78,7 @@ For consistency, please use the same responses shown in the example below when p | Question | Answer | |------------------------------------------------------------|-----------------| | What application platform does your project use? | Node | -| What version of Node do you want to use? | 23.11.0-alpine | +| What version of Node do you want to use? | 24.11.1-alpine | | Which package manager do you want to use? | npm | | Do you want to run "npm run build" before starting server? | yes | | What directory is your build output to? | dist | @@ -106,7 +106,7 @@ The default Dockerfile generated by `docker init` provides a solid foundation fo In this step, you’ll improve the Dockerfile and configuration files by following best practices: - Use multi-stage builds to keep the final image clean and small -- Serve the app using NGINX, a fast and secure web server +- Serve the app using Nginx, a fast and secure web server - Improve performance and security by only including what’s needed These updates help ensure your app is easy to deploy, fast to load, and production-ready. @@ -118,13 +118,77 @@ These updates help ensure your app is easy to deploy, fast to load, and producti ### Step 2: Configure the Dockerfile +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). + +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/). + +> [!IMPORTANT] +> 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. +> +> Official Node.js Docker Images: https://hub.docker.com/_/node + +{{< tabs >}} +{{< tab name="Using Docker Hardened Images" >}} +Docker Hardened Images (DHIs) are available for Node.js on [Docker Hub](https://hub.docker.com/hardened-images/catalog/dhi/node). Unlike using the Docker Official Image, you must first mirror the Node.js image into your organization and then use it as your base image. Follow the instructions in the [DHI quickstart](/dhi/get-started/) to create a mirrored repository for Node.js. + +Mirrored repositories must start with `dhi-`, for example: `FROM /dhi-node:`. In the following Dockerfile, the `FROM` instruction uses `/dhi-node:24-alpine3.22-dev` as the base image. + +```dockerfile +# ========================================= +# Stage 1: Build the Vue.js Application +# ========================================= +# Use a lightweight DHI Node.js image for building +FROM /dhi-node:24-alpine3.22-dev AS builder + +# Set the working directory inside the container +WORKDIR /app + +# Copy package-related files first to leverage Docker's caching mechanism +COPY package.json package-lock.json ./ + +# Install project dependencies using npm ci (ensures a clean, reproducible install) +RUN --mount=type=cache,target=/root/.npm npm ci + +# Copy the rest of the application source code into the container +COPY . . + +# Build the Vue.js application +RUN npm run build + +# ========================================= +# Stage 2: Prepare Nginx to Serve Static Files +# ========================================= + +FROM /dhi-nginx:1.28.0-alpine3.21-dev AS runner + +# Copy custom Nginx config +COPY nginx.conf /etc/nginx/nginx.conf + +# Copy the static build output from the build stage to Nginx's default HTML serving directory +COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html + +# Use a built-in non-root user for security best practices +USER nginx + +# Expose port 8080 to allow HTTP traffic +# Note: The default Nginx container now listens on port 8080 instead of 80 +EXPOSE 8080 + +# Start Nginx directly with custom config +ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"] +CMD ["-g", "daemon off;"] +``` + +{{< /tab >}} +{{< tab name="Using the Docker Official Image" >}} + 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. ```dockerfile # ========================================= # Stage 1: Build the Vue.js Application # ========================================= -ARG NODE_VERSION=23.11.0-alpine +ARG NODE_VERSION=24.11.1-alpine ARG NGINX_VERSION=alpine3.22 # Use a lightweight Node.js image for building (customizable via ARG) @@ -151,26 +215,34 @@ RUN npm run build FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS runner -# Use a built-in non-root user for security best practices -USER nginx - # Copy custom Nginx config COPY nginx.conf /etc/nginx/nginx.conf - # Copy the static build output from the build stage to Nginx's default HTML serving directory COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html +# Use a built-in non-root user for security best practices +USER nginx + # Expose port 8080 to allow HTTP traffic -# Note: The default NGINX container now listens on port 8080 instead of 80 +# Note: The default Nginx container now listens on port 8080 instead of 80 EXPOSE 8080 # Start Nginx directly with custom config ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"] CMD ["-g", "daemon off;"] - ``` +> [!NOTE] +> We are using nginx-unprivileged instead of the standard Nginx image to follow security best practices. +> Running as a non-root user in the final image: +>- Reduces the attack surface +>- Aligns with Docker’s recommendations for container hardening +>- Helps comply with stricter security policies in production environments + +{{< /tab >}} +{{< /tabs >}} + ### Step 3: Configure the .dockerignore file 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 +340,12 @@ docker-compose.override.yml ### Step 4: Create the `nginx.conf` file -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. +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. Create a file named `nginx.conf` in the root of your project directory, and add the following content: > [!NOTE] -> To learn more about configuring NGINX, see the [official NGINX documentation](https://nginx.org/en/docs/). +> To learn more about configuring Nginx, see the [official Nginx documentation](https://nginx.org/en/docs/). ```nginx worker_processes auto; @@ -339,7 +411,7 @@ With your custom configuration in place, you're now ready to build the Docker im The updated setup includes: -- The updated setup includes a clean, production-ready NGINX configuration tailored specifically for Vue.js. +- The updated setup includes a clean, production-ready Nginx configuration tailored specifically for Vue.js. - Efficient multi-stage Docker build, ensuring a small and secure final image. After completing the previous steps, your project directory should now contain the following files: diff --git a/content/guides/vuejs/develop.md b/content/guides/vuejs/develop.md index 2c96424be0a6..a038e2f010dd 100644 --- a/content/guides/vuejs/develop.md +++ b/content/guides/vuejs/develop.md @@ -38,7 +38,7 @@ Create a file named `Dockerfile.dev` in your project root with the following con # ========================================= # Stage 1: Develop the Vue.js Application # ========================================= -ARG NODE_VERSION=23.11.0-alpine +ARG NODE_VERSION=24.11.1-alpine # Use a lightweight Node.js image for development FROM node:${NODE_VERSION} AS dev