前端全栈之路 - 玩转 Docker (基础)

8,651 阅读7分钟

本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

前言

在之前的 Devops 小册中,为了节约资源选择了使用虚拟机来搭建服务端环境,但从收到的反馈来看,大部分的同学都很难独立完成虚拟机的搭建从而被劝退了。

可见虚拟机搭建的过程非常坎坷,小册中虚拟机搭建那一章节的内容其实已经很全面,但是仍然存在一些问题比如虚拟机的版本不一致以及宿主机的差异性(mac && windwos),从而导致没办法顺畅的按照步骤完成服务端的搭建,况且服务搭建的步骤本身就非常繁琐,除了安装系统之外还需要调整虚拟机的端口、防火墙等等内容。

这些对于无后端或者运维知识的同学来说,确实成本比较高,这是我之前没有考虑到的,很多买了小册的同学直接第一章劝退的也不少,也是为什么这次【全栈之路专栏】起手就介绍 Docker 的原因,准备好基础的环境才能继续走下去。

Docker 优势

老规矩,在学习 Docker 使用之前,我们先来看下为什么要学习 Docker

第一优势跨平台,由于 Docker 的镜像能够提供除了系统内核之外完成的运行环境,所以能在任何系统中都能提供一致的运行环境,这样就不需要考虑不同系统中间兼容性的问题,也就不存在虚拟机在各系统中间的配置不同的情况。

第二优势:就是借助于跨平台的特性,Docker 可以将很多配置复杂的服务端中间件打包成基础镜像提供给开发使用。这样无疑能够大大降低配置成本,开发只需要知道常规的 Docker 相关的命令或者直接运行提供的容器编排脚本就可以搭建出需要使用的服务端环境。同时公共的镜像仓库上已经有很多这种基础镜像,例如 MysqlRedisNode 等等,按需提取即可。

第三优势:这点对于运维同学比较好操作,Docker 能提供快速迁移以及配合 k8s,能够快速的伸缩副本,减少运维的工作成本与负担。

Docker 也是借助上述优势将非常迅速的发展自身生态,特别是近两年熟练使用 Docker 也已经频繁的出现在高级前端的 JD 中了。

虽然说了是跨平台,但结合自身的体验来看,Dockerwindows 11 中的兼容性做的并不好(如果有熟悉如果在 Windows 使用 Docker 的同学可以联系我沟通一下),此外由于文件内存处理格式的问题,在数据持久化中,直接使用 volumes 对大量文件读取性能有影响,这一点在之前字节的 Dev Better 沙龙中的前端工程化中也聊过(all in docker 方案),有兴趣的同学也可以联系我沟通。

image.png

Docker 基本知识

接下来在正式使用 Docker 之前,先来掌握两个必备的概念:镜像(Image)与容器(Container)。

何为镜像

如果喜欢折腾的同学应该自己装过 Windows 系统,我们在制作启动盘的时候,会将 Windows 某个版本的 ISO 镜像下载下来再制作系统盘,同理 Docker 的镜像也可以这么理解,它是包含了一个完整功能的最小系统。

Docker Image 作为文件联合系统(Union FS),它由一层层 layer 堆叠组成,这意味着我们可以基于基础镜像来构建各个业务的或者更高级的中间件镜像。同时借助镜像堆叠的功能,在拉取新的镜像时,避免拉取本地已存在的基础镜像,节约资源且提高效率。

何为容器

由上述安装 Windows 的例子来看,容器可以看成已经成功装机的电脑,可以运行某些命令、执行程序等操作。

一般只需要制作一个启动盘就可以安装多台电脑,Docker Image 构建完毕之后,与启动盘一样可以直接基于 Image 启动多个不同的容器,而且他们之间是相互隔离的。

简单的概念就如上所说,能够大概了解基本的特性即可满足常规使用,更加细节的原理性的问题则需要各位同学自己去探索。

Docker 命令的学习

再了解完 Docker 的一些基本概念后,接下来我们继续学习日常开发中常用的 Docker 命令。

首先可以使用以下命令获取 image 相关的命令信息:

$ docker image help

image.png

查看镜像

$ docker image
$ docker image ls
$ docker image ls -a 
$ docker image ls -q

image.png

如上图所示,除了最后一条命令只展现 Image ID 之外,前面三条都是一样的效果,所以随便输入就行。

拉取镜像

$ docker image pull 【imageName:version】

镜像的命名规则为 Name:version 的模板,一般在 CI/CD 的过程中,是按照 version 来判断是否需要拉取新的镜像,所以很少会同版本覆盖构建上传

与 Node 一样,Docker 也提供了公共的仓库服务 Docker Hub

image.png

我们日常所需要的基础镜像都可以从公共仓库中获取:

image.png

为了后面的测试方便,我们可以先拉取一个 Node 的稳定版本 node:16-alpine3.15 镜像到本地

image.png

如果大家观察仔细的话,在拉取镜像的过程中,图中圈出来的内容在拉取中会带有 layer 标识。

一般来说名称带 AlpineBusyBox 的镜像都非常小,在构建业务镜像可以优先考虑,比如刚刚拉取的 node:16-alpine3.15 镜像包在 100M 左右,假设有特殊需求,需要 Linux 某些特殊功能如 ssh 的话,有能力话也可以基于基础镜像来构建,嫌麻烦的话则可以直接选择已有的 Centos 或者其他 Linux 镜像。

构建镜像

接下来我们将一起来构建一个简单的镜像,首先我们需要在 demo 工程的根目录下创建一个 Dockerfile,如下图所示:

image.png

# dockerfile

FROM node:16-alpine3.15

RUN mkdir -p /home/app/

WORKDIR /home/app/

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080

ENTRYPOINT ["npm", "run"]

CMD ["serve"]

接下来项目根路径下直接运行下述命令构建镜像:

$ docker build -f ./Dockerfile -t test:0.0.1 .

image.png

由于之前我们已经预先将 node:16-alpine3.15 基础包拉取下来了,所以在上图的构建过程中可以发现,并没有额外再拉取新的 layer

再次使用 docker images 可以看到本地多了一个 test/0.0.1 的镜像:

image.png

运行容器

$ docker run -d -p 8080:8080 test:0.0.1

image.png

如果与图上保持一致,那么代表已经完成容器的启动,浏览器 http://localhost:8080/ 可以看到如下节目则代表启动成功。

image.png

为了验证之前的容器概念,我们可以再次启动一个暴露端口为 3000 的容器:

$ docker run -d -p 3000:8080 test:0.0.1

image.png

基于这个特性,我们可以在开发工程的时候规范一下开发规则,使用运行时注入环境变量的方式来区分 devtestprod,可以达到一次构建多环境部署的效果,避免构建中出现其他依赖问题导致生产事故。

Demo 工程采用的是 vue-cli 创建的基础工程,如果想使用其他的前端工程,需要调整端口与启动命令。

查看容器

$ docker ps      查看当前运行中的容器
$ docker ps -a   查看所有容器,包括已停止的容器
$ docker stop [容器ID/Name] 停止选定的容器

image.png

删除容器跟镜像

$ docker rmi [镜像ID]   删除选定镜像
$ docker rm [容器ID/Name] 删除选定的容器

注意:运行中的镜像是无法删除的,存在容器的时候也是无法删除镜像的。

image.png

进入容器

$ docker exec -it [容器ID] /bin/sh

如果上述命令不行的话,最后的地址可以换成 /bin/bash,进入路径与构建镜像有关系,示例使用的 alpine 基础镜像,所示使用上述命令。

image.png

接下来我们来修改容器中的内容看看是否生效:

image.png

image.png

修改完毕,再次查看页面就能看到内容已经被修改完毕,最后可以使用 exit 退出当前容器。

查看容器日志

$ docker logs [容器ID]

使用 logs 命令,可以看到容器中运行的日志信息,下图就是我们 Vue 项目启动的日志以及我们修改之后重启的日志信息:

image.png

以上是一些常见的 Docker 命令,大家可以尝试使用下,更多的命令可以查看官网,下一篇将介绍 Docker 的一些高阶玩法。

写在最后

与上一个【前端工程化】专栏不同的是,【前端全栈之路】的技术角度不再仅仅限于前端范畴,会衍生到软件工程整体环节,包括测试、设计、运维以及服务端等等。所以你会在这个专栏里面看到非常全、广的技术体系,当然这些内容全部在一个专栏中会显得比较杂乱,尽量会用规范的标题来让你快速查到想要的内容。

而【前端工程化】专栏会更专注于前端领域,例如搭建、组件库、微前端、各种前端框架等前端技术体系,所以两种后期是作为互补的情况出现。

当然在全栈体系中,肯定会有些技术深度不够的情况,如果有遇到讲解不够清楚或者个人理解有偏差的情况,大家可以留言指正,及时修改避免误导有需要的读者。

有兴趣的同学可以加我微信号:cookieboty,一起学习前端工程化的内容,互相学习,共同进步。