图片来源:https://blog.papercut.com/wp-content/uploads/2019/02/docker-logo-1024x597.png
Docker 对于前端来说不是必须的,但是如果需要自己折腾前端工具、建站等,涉及到应用部署的话就必须要去了解下相关知识了。
本文只是对 Docker 的入门,看完本文后会对 Docker 的概念以及如何使用 docker 有个初步的认知。
对于前端来说,有个入门的认识应该就够了。
docker 音译过来是“容器”,但是 docker 有三大概念:
- 镜像 image
- 容器 container
- 仓库 repository
镜像和容器的关系就如 JS 中的类与实例。
在 JS 中,我们常用的包管理工具 npm,我们会将 npm 包 npm publish
到免费的公共服务上。
而 docker 的镜像就如同托管在远程服务的 npm 包一样,docker 也有托管服务 Docker Hub
,我们可以创建自己的 仓库 Respository,本地通过 docker push <仓库/name:tag>
同理,我们通过 npm install
安装在本地 node_modules
中的包的“形态”,就类似 容器 container。
关于 docker 的其他概念或作用,网上都能找到,就不再赘述了。
譬如,我有一个需求,是将一个 npm 命令行工具构建成 docker 包,并 push 到远程仓库,提供给运维部署时用。
首先我的思路有 2 种:
该镜像必然依赖 node,暂且是
node:latest
好了,因为不需要考虑其他功能。
- 在本地 npm 包的根目录下构建 docker 镜像,将完整的包构建进去,这样就不用再下载了
- 构建空的镜像,其中包含一条执行命令,去安装该 npm 包
于是,我去实践这 2 种思路。
实践的结果当然只能是方案二合理,因为构建的 docker 包,虽然上下文指定了当前目录,但是并未将文件拷贝到对应的 root 的文件系统中。需要自己去 COPY
,但是 copy 只能单个文件。
想想 node_modules 吧,因为 npm 命令行工具依赖。
于是乎,将 npm 包压缩成一个 zip 包后再 copy 到文件系统中似乎可行。的确如此!但是 copy 的过程也是很慢的,node_modules 的嵌套依赖太过庞大。
所以总的来看,通过在 node 容器中,执行安装命令清晰易懂
构建命令:
# -t 表示指定要创建的目标镜像名
# tag 默认为 latest
# context 表示构建上下文,下文会说
docker build -t <name:tag> <context>
查看本地镜像
docker images
docker image ls
有时候会出现 的镜像,可以使用 docker image prune 清除,这类镜像被称为“虚悬镜像”,无用。
根据镜像创建容器
# -i: 交互式操作
# -t: 终端
docker run -i -t <name:tag> /bin/bash/
镜像删除
docker rmi <name:tag>
通过镜像创建的容器实例,一般我们也只用关心简单的启动、停止和删除。
查看本地容器
docker ps -a
其它
# 启动
docker start <ID>
# 停止
docker stop <ID>
# 删除
docker rm -f <ID>
上面我们创建镜像的时候会指定 tag,也可以单独指定 tag。
docker tag <ID> <name:新的tag>
创建后会看到本地新增了一条镜像记录。
本地创建镜像后,便可以直接 push 到仓库
docker push <repository/name:tag>
这里需要自己注册 docker hub 的账号,并创建相应的仓库。
创建的构建文件名按照约定必须是 Dockerfile
构建时的 context 指定需要慎重,需要将当前目录无关的文件剔除,其余文件都会作为上下文去构建当前镜像,譬如我们要做 COPY
操作,对于相对路径就是依赖上下文 context。
我们可以使用 .dockerignore
来剔除无关文件,语法和 .gitignore
一致。
Dockerfile 的书写规范,语法类似 shell 语法,只不过需要使用 docker 的关键字命令来处理。
docker 中的关键字命令都会单独创建一个层来执行,一般对于前端命令,是没有必要创建多个层也就是多个 RUN
命令的,应该一行语句写完。