前言
简单记录一些 Docker 相关的笔记,首先我们先明确何为 Docker?
由于之前一直做的是前端,在构建项目时,都是直接在服务器上装 node,nginx,又或者 pm2 之类的。直接了当,但如果出现那种,你需要将你的项目部署到对方的服务器上,当然你可以选择在对方服务器上安装 node,安装 nginx,前端部署相对简单,但如果涉及到后端,要部署软件就会偏多。
Docker 正是解决了这个痛点,Docker 会将你需要的软件安装到这个服务器上开辟的一个空间里,对于对方来说,他只需要安装 Docker 并且将你写好的 DockerFile 文件运行起来即可。
这种感觉非常像是虚拟机, Docker 经常也拿来与虚拟机做比较,但相对于虚拟机,Docker 的轻巧便捷是毋庸置疑的。
Docker 运行
Docker 运行绕不开 Image(镜像) 和 Container(容器)。
一般有 2 种方式:
-
编写
DockerFile,然后执行build命令,构建成Image(镜像) -
从 仓库 中直接
pull镜像下来(与 git 类似)
有了镜像,则可执行 run 命令将其运行起来,Container 就是运行起来的程序。
graph LR
D>DockerFile] --build--> I(Image镜像)
I --push--> 远程仓库 --pull--> I
I --run--> C(Container容器) --commit--> I
C --restart--> C
命令整理
docker images # 显示本地所有的镜像列表
docker build # 使用Dockerfile创建镜像(推荐)
docker commit # 从容器创建镜像
docker rmi # 删除一个镜像
docker create # 创建一个容器但是不启动它
docker run # 创建并启动一个容器
docker stop # 停止容器运行,发送信号SIGTERM,在一段时间后发送SIGKILL信号
docker start # 启动一个停止状态的容器
docker restart # 重启一个容器
docker rm # 删除一个容器
docker kill # 发送SIGKILL信号,立即停止该容器
Volume 数据卷
镜像是只读的,容器只是在镜像的基础上增加了一层 读写层,那么既然涉及到了写入操作,容器如果一旦被删除了,那么容器里的数据也将会被删除,数据卷就可以解决这个问题。
即使容器被删除,数据卷依然持久化保存在于你本地(这里的本地是相对于容器而言,即不保存在容器内),且数据卷可以在容器之间共享复用。
一般我们如何将源代码放进容器里?
-
制作镜像时直接把源代码嵌入里面(一般不考虑这种做法)
-
把源代码挂载到容器的读写层(数据卷做法)
如何编写数据卷?
你可以在镜像编写完成,准备生成容器时执行命令:
docker run --name v-test3 -v D:\Desktop\index.html:/usr/share/nginx/html/index.html -d -p 7778:7777 my-docker-test
这里用了非常多的选项,但只有 -v 是数据卷命令,其他顺便一起简单记录下。
--name:给容器命名,这里我命名了 v-test3
-d:容器在后台运行
-p:本机的 7778 端口 指向容器内的 7777 端口
my-docker-test:是我要运行的镜像名
-v:本机的 D:\Desktop\index.html 路径指向容器内 /usr/share/nginx/html/index.html,如此之后,修改本地的 index.html 就会使得容器内的一起改变。
当然你也可以在 Dockerfile 里定义一个数据卷:
# 指定数据卷
VOLUME /path/to/volume
通过该 dockerfile 创建的镜像运行的容器,在运行时候会自动创建数据卷,并将其关联到容器内的 /path/to/volume 路径。
但如果你要关联到本地的特定路径,那么还是要使用 -v 来指定。
【注】我这只是最浅显的,实际上 docker 也有 docker volume 命令,但这里就不记录了。
.dockerignore
和 .gitignore 类似,写在 .dockerignore 里的文件会在 docker build 时候被忽略掉。
node_modules/
.git
.vscode/
*.md
.gitignore
Dockerfile 例子
这里用到了多阶段构建一个简单的前端项目,让我们程序能自己 build ,自己弄到 nginx 上。当然前端也有很多构建方式,不一定使用这个,只作为举例使用,后面想结合 jenkins ,k8s 搞 CI/CD 之类的,由读者自己搞搞。
# 多阶段构建
# 拉取 node,并将当前构建阶段命名为 build-stage
FROM node:18-alpine3.14 as build-stage
# 指定工作目录:为容器内的 /docker-app
WORKDIR /docker-app
# 复制当前目录文件 到容器的工作目录内
COPY . .
# 设置变量
RUN npm config set registry https://registry.npmmirror.com
# 执行install 和 build。 现如今的node中默认安装了npm 和yarn,我们直接使用 yarn
RUN yarn install
RUN yarn build
# CMD 指令类似于 RUN 指令,不过是用来执行程序的,二者运行时机不一样
# CDM 在 docker run 时运行,RUN 是在 docker build 时运行
# =============================================================
# 这时候 build-stage 内已经存在了 dist 目录
# 拉取 nginx
FROM nginx as nginx-stage
# 从本地中拷贝 nginx 配置过去
COPY /nginx.conf /etc/nginx/nginx.conf
# 由于 build-stage 里的工作目录是 /docker-app,所以这里要注意前缀
# /usr/share/nginx/html 这个是我在 nginx.conf 里配置的根目录
COPY --from=build-stage /docker-app/dist /usr/share/nginx/html
# 仅作为声明端口
EXPOSE 7777