基于 docker/docker-compose 对极简项目的部署

251 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

兄弟们第二章来啦,本篇文章介绍如何使用 Docker 将一个极简前端页面进行部署,而极简资源内容如下。也就是上篇文章的 hello 版前端应用

  • [ 在本地启动并运行项目 ]
  • [ Dockerfile ]
  • [ 构建镜像 (Image) ]
  • [ 运行容器 ]
  • [ 更高效的方式: docker-compose]
  • [ 构建镜像 RUN 输出查看小技巧 ]
  • [ 小结 ]
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  hello, shanyue. 
</body>
</html>

你可以在本地安装 docker完成本篇文章的部署实践内容,部署内容与上篇文章一致。在本篇文章之前,你需要先做一些功课:

  1. 在本地安装 docker/docker-compose。通过 Docker Desktop (opens new window)下载 docker 后,双击安装即可。
  2. 了解 Dockerfile Reference (opens new window)。了解最常见的 FROM/ADD/CMD 即可。不需要全部过一遍,遇到没见过的指令及时查阅即可。
  3. 了解 Compose file Reference (opens new window)。不需要全部过一遍,遇到没见过的指令及时查阅即可。
  4. 了解 Docker Hub (opens new window)。在该网站,可查找适合于自己的诸多基础镜像,比如 node (opens new window)与 nginx (opens new window)

如果你在此之前没有学习过 Docker,可参照山月以前的文章 Docker 简易入门 (opens new window)进行学习

PS: 本项目以 simple-deploy (opens new window)仓库作为实践,配置文件位于 node.Dockerfile(opens new window)

在本地启动并运行项目

由上篇文章可知,我们主要是将该资源服务化,此时可借助于一个工具 serve 进行静态资源服务化。

# 将 serve 置于 dependencies 中
$ npm i

# 通过 serve 启动服务
# 可通过 npm scripts 命令封装成 start
$ npx serve .

通过 npm scripts,将启动服务命令封装成 npm start

{
  start: 'serve .'
}

Dockerfile

一般来说,根据以下三步,可以将脚本命令翻译成 Dockerfile。

  1. 选择一个基础镜像。可在 Docker Hub (opens new window)中进行查找镜像。由于前端项目依赖于 Node 环境,我们选择 node:14-alpine (opens new window)作为基础镜像,其中基于轻量操作系统 alpine,内置了 node14/npm/yarn 等运行环境。
  2. 将以上几个脚本命令放在 RUN 指令中。
  3. 启动服务命令放在 CMD 指令中。

翻译如下:

PS: 该 Dockerfile 配置位于 simple-deploy/node.Dockerfile(opens new window)

# 选择一个体积小的镜像 (~5MB)
FROM node:14-alpine

# 设置为工作目录,以下 RUN/CMD 命令都是在工作目录中进行执行
WORKDIR /code

# 把宿主机的代码添加到镜像中
ADD . /code

# 安装依赖
RUN yarn

EXPOSE 3000

# 启动 Node Server
CMD npm start

还差两步,就可以将该最简单示例运行起来:

  1. 通过 Dockfile 构建镜像 (Image)
  2. 通过镜像运行容器 (Container)

构建镜像 (Image)

使用 docker build 命令可基于 Dockerfile 构建镜像。

镜像构建成功后,我们可以将仓库上传至 Docker 仓库,如 Docker Hub (opens new window)。而对于业务项目而言,一般会上传至公司内部的私有镜像仓库,比如通过 harbor (opens new window)搭建的私有镜像仓库。

# 构建一个名为 simple-app 的镜像
# -t: "name:tag" 构建镜像名称
$ docker build -t simple-app .

# git rev-parse --short HEAD: 列出当前仓库的 CommitId
# 也可将当前 Commit 作为镜像的 Tag
# 如果该前端项目使用 git tag 以及 package.json 中的 version 进行版本维护,也可将 version 作为生产环境镜像的 Tag
$ docker build -t simple-app:$(git rev-parse --short HEAD)

# 构建成功后,可用该命令列出所有的镜像
# 发现该镜像占用体积 133MB
$ docker images
REPOSITORY           TAG         IMAGE ID       CREATED          SIZE
simple-app           latest      c1571917d2c2   17 seconds ago   133MB

此时构建镜像成功,通过 docker images 可知镜像体积为 133MB。记住这个数字,以后优化镜像体积时用得到。

运行容器

我们可以基于镜像运行 N 个容器,而本次启动的容器也是我们最终所要提供的静态服务。

# 根据该镜像运行容器
# 如果需要在后台运行则添加 -d 选项
# --rm: 当容器停止运行时,自动删除容器
# -p: 3000:3000,将容器中的 3000 端口映射到宿主机的 3000 端口,左侧端口为宿主机端口,右侧为容器端口
$ docker run --rm -p 3000:3000 simple-app

# 运行成功后可在另一个窗口查看所有容器
$ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                       NAMES
50784910f758   simple-app   "docker-entrypoint.s…"   20 seconds ago   Up 20 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   wizardly_solomon

此时在本地访问 http://localhost:3000 访问成功

然而,通过冗余繁琐的命令行构建镜像和容器,比如管理端口,存储、环境变量等,有其天然的劣势,不易维护。

更高效的方式: docker-compose

1.webp 将命令行的选项翻译成配置文件,是更为简单且更容易维护的方式。比如对于 webpack 而言,基本上基于 webpack.config.js 配置文件使用。

而 docker compose 即可将 docker cli 的选项翻译成配置文件,除此之外,它还有更强大的功能。

编辑 docker-compose.yaml 配置文件如下所示。当然,由于这是一个最简项目,因此配置文件也极其简单。

PS: 该 docker compose 配置位于 simple-deploy/docker-compose.yaml

version: "3"
services:
  app:
    # build: 从当前路径构建镜像
    build: .
    ports:
      - 3000:3000

配置结束之后,即可通过一行命令 docker-compose up 替代以前关于构建及运行容器的所有命令。

# up: 创建并启动容器
# --build: 每次启动容器前构建镜像
$ docker-compose up --build

此时在本地访问 http://localhost:3000 访问成功

此时,通过 docker/docker-compose 便部署成功了第一个前端应用。

以下,再介绍一个使用 Docker 的小技巧。

构建镜像 RUN 输出查看小技巧

在使用 docker build 进行构建时,通过 RUN 指令可以通过打印一些关键信息进行调试,

但是,在我们进行 docker build 时,无法查看其输出结果。

此时可以通过 --progress plain 来查看其输出结果。

FROM node:14-alpine

RUN echo shanyue

对以上镜像构建,可拿到 echo shanyue 的输出结果。

$ docker build --progress plain --no-cache .
4 [1/2] FROM docker.io/library/node:14-alpine
4 sha256:4641ddabdab058bf21b1550827533213f023ec21abf1ceb322993c137532f760
4 CACHED

5 [2/2] RUN echo shanyue
5 sha256:37883e3cbc36146a836ad89f3cf147723bcda1d2cf4e97655c9ed1afceb59517
5 0.237 shanyue
5 DONE 0.3s

小结

通过本篇文章,我们已经可以通过 Docker 完成对极简前端项目的部署。

但是,前端静态资源并不需要 nodejs 环境,且 nodejs 镜像较大,我们可以使用 nginx 作为基础镜像来部署前端。