1
头图

JavaScript 应用的 Dockerfile 可能千差万别——从两行代码到五十行不等。这种复杂性可能会让一些前端开发者望而却步,从而难以真正理解这个强大的工具。

今天,我想通过分析一个 JavaScript 应用的示例 Dockerfile,来揭开 Docker 的神秘面纱。无论你使用哪个 JS 框架(React 、Vue、servlte 或者是 Angular ),这篇文章都应该对你有所帮助。

前端的 Docker 基础知识

在使用 Docker 容器化前端项目时,理解一些核心概念和术语至关重要。这些基本概念不仅有助于理解 Docker 的工作方式,还能够帮助你在构建、优化和管理容器化应用时做出更明智的决策。

  • 镜像(Image)
    镜像是 Docker 的核心组件,它类似于一个模板,包含了运行前端应用所需的一切:代码、运行时环境、依赖项和系统库。对于前端项目,这意味着你的应用程序代码、Node.js 环境、npm 模块、以及构建工具(如 Webpack 或 Vite)都打包在一起,形成一个可重用的镜像。镜像是分层构建的,每一层对应 Dockerfile 中的一条指令,这些层叠加在一起形成最终的镜像。镜像本身是只读的,当你运行一个镜像时,Docker 会创建一个容器,并在这个容器上添加一个可写层,允许应用在其中运行。你可以通过 docker build 命令来创建镜像,从而保证在不同环境中部署应用时的一致性。
  • 容器(Container)

    容器是 Docker 中实际运行镜像的实例,它负责启动你的前端应用。在容器中,你可以定义环境变量、开放特定的端口(如前端开发时常用的 3000 或 8080 端口)、指定网络协议等。简单来说,容器将镜像中打包的所有内容启动并运行,使得你的应用程序能够在任何支持 Docker 的环境中顺利运行。

  • 指令(Instructions)

    在编写 Dockerfile 时,指令是必不可少的构建块。每一行指令都以大写字母开头,紧跟相关参数。这些指令用于定义如何从基础镜像构建出符合你需求的新镜像。例如,FROM 指令指定基础镜像,RUN 指令则用于在镜像内执行命令。理解这些指令的作用有助于优化你的 Dockerfile,从而提升构建效率。

  • 层(Layers)

    Dockerfile 中的每一条指令几乎都会转化为镜像中的一个层。对于前端项目来说,这些层可能包括安装依赖的层、构建应用的层、压缩静态资源的层等。层的顺序对最终镜像的优化至关重要,合理安排指令顺序不仅可以减少镜像大小,还能加快构建速度。例如,提前缓存不常改变的依赖,可以避免每次构建都重复安装依赖。

通过理解这些 Docker 基础概念,你可以更加自信地构建和优化前端项目的 Docker 镜像,从而实现更高效、更稳定的开发和部署流程。

编写高效的 Dockerfile

Dockerfile 是使用 Docker 构建容器化应用的关键步骤之一。 它其实是一个文本文件,其中包含了一组指令,用于定义如何构建 Docker 镜像。

通过 Dockerfile,你可以指定应用程序的基础镜像、安装依赖、设置工作目录、定义环境变量、暴露端口等。

一个Vue 前端项目的Dockfile

以下是一个用于部署 Vue 应用的完整 Dockerfile 示例:

让我们通过解析这个 Dockerfile,逐步了解相关的知识点和注意事项。

1. 多阶段构建

这个 Dockerfile 使用了多阶段构建,这是为了将构建和部署分离开来,优化最终的镜像体积。第一阶段定义了一个名为 builder 的构建阶段。

  • ARG 指令: 用于设置构建时的变量。这些变量在构建时可用(但在运行时不可用)。 如果想要运行时同样可用的话,需要使用 ENV 指令。
  • 标签: node:${NODE_VERSION}-slim 这个叫标签。 标签可能包含 bookworm, bullseye, or buster等名称。这些是 Debian 版本的套件代码名称,并指示该镜像基于哪个版本。
  • 注意点:多阶段构建能够有效地减少最终镜像的大小,因为它允许你在最终镜像中只保留运行应用所需的最小内容,而丢弃构建过程中使用的依赖和工具。

2. 工作目录与依赖安装

WORKDIR /app

COPY package*.json ./

RUN npm install
  • 工作目录WORKDIR /app 指令设置了容器内的工作目录为 /app,后续所有的操作都将在这个目录下进行。
  • 依赖安装COPY package*.json ./RUN npm install 这两行命令先将 package.jsonpackage-lock.json(或 yarn.lock)文件复制到容器中,然后安装依赖。这样做的好处是如果代码没有变化,Docker 可以利用缓存跳过重复的依赖安装步骤,从而加快构建速度。
  • 注意点:在复制依赖文件和安装依赖前,避免复制其他源代码,可以利用 Docker 的层缓存机制,避免不必要的依赖重新安装。

3. 复制代码并构建应用

COPY . .

RUN npm run build
  • 复制代码COPY . . 将项目的所有源代码复制到容器中的工作目录 /app
  • 构建应用RUN npm run build 执行 Vue 3 项目的构建过程,将应用打包到 dist/ 目录中。这一步生成的文件是部署到生产环境中的静态资源。
  • 注意点:确保构建脚本正确配置了生产环境的构建选项,以生成优化后的静态资源文件。

4. 部署应用

# Stage 2: Serve
FROM nginx:alpine

# COPY nginx.conf /etc/nginx/nginx.conf 

COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
  • 部署阶段:第二阶段使用了 nginx:alpine 镜像,这是一个轻量级的 Nginx 服务器镜像。它负责在生产环境中提供静态文件。
  • 文件复制COPY --from=builder /app/dist /usr/share/nginx/html 指令将第一阶段构建的 dist/ 目录中的静态文件复制到 Nginx 默认的静态文件目录 /usr/share/nginx/html 中。

    如果,你需要对nginx 做配置,也可以将 nginx.conf 放入项目代码中,通过构建流程复制到docker server中。

  • 端口暴露EXPOSE 80 指令告诉 Docker 容器将使用 80 端口来服务 HTTP 请求。这个端口将用于在生产环境中访问你的 Vue 应用。
  • 启动命令CMD ["nginx", "-g", "daemon off;"] 是容器启动时执行的默认命令,它启动 Nginx 服务器并保持在前台运行(daemon off 选项)。这确保了容器在启动后不会立即退出。
  • 注意点:通过使用多阶段构建,最终生成的镜像非常精简,仅包含 Nginx 服务器和前端应用的静态资源文件。这不仅优化了性能,还减少了潜在的安全风险。
  1. 构建和运行 Docker 镜像

    使用下面的命令构建 Docker 镜像并运行容器:

    docker build -t vue-nginx-app .

总结

这个 Dockerfile 示例通过多阶段构建,展示了如何高效地构建和部署 Vue 3 应用。通过解析每个部分,我们理解了如何选择基础镜像、设置工作目录、安装依赖、构建应用、以及最终在 Nginx 中部署应用。这些步骤结合在一起,帮助我们创建了一个轻量、高效且易于管理的 Docker 镜像。

当我们构建出Docker 镜像后,我们不仅可以,直接在服务器运行,还可以与K8s 进行联动。 当然,构建过程 和 部署过程还有很多个性化的设置。本文主要讲解如何构建基于docker的工作流程,细节方面每个公司不同,不去讨论。


Sean
26 声望2 粉丝

一个 有趣的老程序员