WIP: Docker的底层机制
2022-7-20
| 2023-2-19
0  |  0 分钟
password
Created
Feb 19, 2023 04:38 PM
type
Post
status
Invisible
date
Jul 20, 2022
slug
summary
WIP: Docker的底层机制
tags
Docker
category
Go
icon
docker是一个虚拟化的系统环境, 主要是为了规避不同宿主机器上的不同的差异化配置导致的各种运维问题, 同时可以将一台物理主机的性能运用到极致
使用docker, 可以在一台物理机器上跑多个容器, 而每个容器又有独立的操作系统环境, 如: 文件系统, 网络端口等
 

Docker如何实现相互隔离

Docker本质上是依赖了操作系统的一种namespace机制
namespace可以给进程, 用户, 网络分配一个命名空间, 这个命名空间下的资源都是独立命名的
PID namespace: 进程命名空间, 它会是命名空间内的这个进程id变为1, 而linux的初始进程id就是1, 所以这个命名空间内它就是所有进程的父进程 IPC namespace: 限制只有这个namespace内的进程可以相互通信, 不能和namespace外的进程通信 Mount namespace: 创建一个新的文件系统, namespace内的文件访问都是在这个文件系统之上
Network namespace:网络的命名空间
User namespace:用户和用户组的命名空间
UTS namespace:主机名和域名的命名空间
通过这六种命名空间, Docker就实现了资源的隔离
 

Docker的资源复用

在docker中, 如果每个容器都是独立的文件系统, 那么势必会造成很大的资源浪费
例如: 某两个nodejs服务, 都是用了node:14-alpine的基础镜像, 如果每个镜像都复制一次基础镜像到自己的镜像中, 必然就太浪费资源了
因此, Docker设计出了一种”层”的机制, 镜像中每一层都是不可修改的, 如果需要修改, 则需要创建一个新的层, 而层, 是可以复用的, 也就是说, 上面例子中, 如果都是用了node:14-alpine的基础镜像, 那么基础镜像的那些层, 在两个nodejs服务中, 是完全一致的, 也就可以方便实现复用.
但有一个问题比较大的点是: 既然两个镜像是两个不同的”操作系统”, 那么它们之前怎么去共享多个可复用层呢?
这里就涉及到unix中的一个相对底层的文件机制, UnionFS了, 通过UnionFS, 可以将这些层进行虚拟化和复用
 

Docker的资源占用限制

对于每个Docker镜像, 我们可以对其设置CPU 内存 磁盘的使用限制, 通过限制镜像的使用资源量, 就不必担心某一个镜像因为异常等原因把宿主机的CPU或内存撑爆导致出问题了
这项能力依赖于linux中的底层机制Controll Group通过这项底层能力能够实现对资源占用的限制
 

关于使用

  1. 主要指令
  • FROM:基于一个基础镜像来修改
  • WORKDIR:指定当前工作目录
  • COPY:把容器外的内容复制到容器内
  • EXPOSE:声明当前容器要访问的网络端口,比如这里起服务会用到 8080
  • RUN:在容器内执行命令
  • CMD:容器启动的时候执行的命令
 
  1. 多阶段构建
把构建分到一个镜像里,然后把产物赋值到另一个镜像,这样单独跑产物, 这是比较推荐的做法
# build stage FROM node:10 AS build_image WORKDIR /app COPY . /app EXPOSE 8080 RUN npm install && npm run build # production stage FROM node:10 WORKDIR /app COPY --from=build_image /app/dist ./dist RUN npm i -g http-server CMD http-server ./dist
我们把两个镜像的生成过程写到了一个 dockerfile 里,这是 docker 支持的多阶段构建。
第一个 FROM 里我们写了 as build_image,这是把第一个镜像命名为 build_image。
后面第二个镜像 COPY 的时候就可以指定 --from=build_image 来从那个镜像复制内容了。
这样,最终只会留下第二个镜像,这个镜像里只有生产环境需要的依赖,体积更小。传输速度、运行速度也会更快。
 
一个前端项目的示例:
# build stage FROM node:14.15.0 as build-stage WORKDIR /app COPY package.json ./ RUN npm install COPY . . RUN npm run build # production stage FROM nginx:stable-perl as production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html COPY --from=build-stage /app/default.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
 
 
 
 
 
 
 
Go
  • Docker
  • CentOS安装redisRxjs和它的一些概念
    目录