busybox 忙碌的盒子 这个是docker的欺骗层
docker采用半解偶,普通采用完全解偶
根目录 下边两个proc(内存进程) sys伪文件系统
Namespace:六项隔离
usr mnt pid 隔离
uts ipc net 共享
[root@docker1 ~]# cd /proc/17853(进程号)/ns/
[root@docker1 ns]# ll
total 0
lrwxrwxrwx 1 root root 0 Oct 14 15:14 ipc -> ipc:[4026531839]信号量消息列队和共享内存
lrwxrwxrwx 1 root root 0 Oct 14 15:14 mnt -> mnt:[4026531840]挂载点
lrwxrwxrwx 1 root root 0 Oct 14 15:14 net -> net:[4026531962]网络栈端口等
lrwxrwxrwx 1 root root 0 Oct 14 15:14 pid -> pid:[4026531836]进程编号
lrwxrwxrwx 1 root root 0 Oct 14 15:14 user->user:[4026531837]用户和用户组
lrwxrwxrwx 1 root root 0 Oct 14 15:14 uts -> uts:[4026531838]主机名进程名
Cgroup:控制程序对资源的占用。ctrl
1资源的限制。Cgroup可以对进程组使用的资源总额进行限制。
2优先级分配:通过分配的CPU时间片数量及磁盘IO贷款大小,实际上就是相当于控制了进程运行的级别。
3资源统计:Cgroup可以统计系统资源使用量,比如CPU使用时间,内存使用量等课用于按量计费。
4进程控制:可以对进程组执行挂起、恢复等操作。
网络的I/O 磁盘的I/O
sys/fs()/cgroup/
[root@docker1 ns]# cd /sys/fs/cgroup/
[root@docker1 cgroup]# ls
blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd
cpu cpu,cpuacct devices hugetlb net_cls net_prio pids
[root@docker1 cpu]# cat cpu.shares
1024 (权重比) hooks---->钩子。能够钩到多少资源就用多少。
[root@docker1 cpu]# cat tasks ---->进程编号,这里的进程都是1024权限。
[root@docker1 cpu]# cd ../memory/ 内存对内存的限制。
Cgroup的应用:
1) 内存和交换分区限制;
容器内存包括两部分:物理内存和swap.
在docker中可以通过参数控制容器的内存使用:
-m 或 –memory:设置内存的使用限额
--memory-swap:设置内存swap的使用限额。
docker run -it -m 200M --memory-swap 300M centos
[root@docker1 memory]# cd /sys/fs/cgroup/memory/
[root@docker1 memory]# cat memory.limit_in_bytes 限制的内存量。
9223372036854771712 不限制
cat memory.memsw.max_usage_in_bytes 交换分区的限制
1958977536
2) 容器的CPU限制
3) 限制容器的Block io
dps:每秒读写的数据量。byte per second
iops:每秒IO的次数。 io per second
--device-read-bps:设置读取设备的bps
--device-write-bps:设置写入设备的bps
--device-read-iops:设置读取设备的IOPS
--device-write-iops:设置写入设备的iops
docker常见命令
镜像操作
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
搜索镜像
docker search是关键字
–automated=true|false:仅显示自动创建的镜像,默认为否
–no-trunc=true|false:输出信息不截断显示,默认为否
-s,–stars=X:制定仅显示评价为指定星级的以上的镜像,默认为0。
例如搜索nginx:
docker search --automated -s 3 nginx
Name:镜像名字 DESCRIPTION:描述 STARS:星级 OFFICIAL:是否官方 AUTOMATED是否自动
镜像下载:
docker pull NAME[:tag] name是仓库的名字tag是镜像的名字。
如果从别的地址下载镜像
如果下载别的网站的镜像需要在镜像前边加上URL
查看镜像信息:
docker images
Nginx与mynginx只是镜像的别名,image id是相同的,所以指的的同一个镜像文件。
如何改变文本的样式
docker inspect
docker inspect nginx
返回的json格式的信息也可以只要其中一个信息。
查看镜像的历史:
docker history nginx
删除镜像
docker rmi name(指的是ID),强行加-f
创建镜像
有三种方法创建镜像,基于已有镜像的容器创建、基于本地模板导入、基于dockerfile创建。
基于自己已有的创建。
docker commit [options] CONTAINER [repository:tag]
-a,–author=””:作者信息:
-c,–change=[]:提交的时候执行Dockerfile指令,包括
CMD|ENTRYPOINT|ENV|EXPOSE|LABEL|onbuild|user|volume|workdir等:
-m,–message=””:提交消息:
-p,–pause=true:提交时暂停容器运行。
启动容器更改后
docker run –it Ubuntu:14.04 /bin/bash
然后用:
docker commit 容器名字 镜像:注释
基于本地模板导入
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
OPTIONS说明:
-c :应用docker 指令创建镜像;
-m :提交时的说明文字;
示例
docker import my_ubuntu_v3.tar runoob/ubuntu:v4
基于dockerfile创建
举个栗子
FROM alpine:3.8.4
MAINTAINER Dark
#更新Alpine的软件源为国内(清华大学)的站点,因为从默认官源拉取实在太慢了。。。
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.8/main/" > /etc/apk/repositories
ADD ./na /mnt/
RUN apk update \
&& apk upgrade \
&& apk add --no-cache bash \
bash-doc \
bash-completion \
&& /bin/bash \
&& apk add --no-cache gcc \
&& apk add --no-cache make \
&& apk add --no-cache expat-dev \
&& apk add --no-cache zlib-dev \
&& apk add --no-cache pcre-dev \
&& apk add --no-cache openssl-dev \
&& apk add --no-cache tar \
&& apk add --no-cache libc-dev \
&& rm -rf /var/cache/apk/* \
&& cd /mnt \
&& tar zxf apr-1.6.5.tar.gz \
&& tar zxf apr-util-1.6.1.tar.gz \
&& cd /mnt/apr-1.6.5/ \
&& ./configure --prefix=/usr/local/apr \
&& make \
&& make install \
&& cd /mnt/apr-util-1.6.1/ \
&& ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr \
&& make \
&& make install \
&& cd /mnt \
&& tar zxf httpd-2.4.39.tar.gz \
&& cd /mnt/httpd-2.4.39/ \
&& ./configure --prefix=/usr/local/httpd \
--enable-so --enable-cgi \
--enable-cgid --enable-ssl \
--with-ssl --enable-rewrite \
--with-apr=/usr/local/apr \
--with-zlib --with-apr-util=/usr/local/apr-util \
--enable-modules=most --enable-mods-shared=most \
--enable-mpms-shared=all \
--with-mpm=event --enable-proxy \
--enable-proxy-fcgi \
--enable-expires \
--enable-deflate \
&& make && make install \
&& cd /mnt \
&& ln -s /usr/local/httpd/bin/* /usr/local/bin/ \
&& mkdir /var/www/html -p \
&& mv httpd.conf /usr/local/httpd/conf/httpd.conf \
&& mv httpd-vhosts.conf /usr/local/httpd/conf/extra/httpd-vhosts.conf \
&& rm -rf /tmp/* \
&& rm -rf /mnt/*
EXPOSE 80
CMD ["bash","-c","apachectl start && echo c; while true; do sleep 5; echo sleep; done"]
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。
创建镜像
docker build -t nginx:v3 .
上一节中,有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?
解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。
实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。
这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
CMD说明
这里要说一点关于cmd的问题,如果原始镜像有cmd那么dockerfile里也有会替换原始镜像的cmd,如果这里不写使用原始镜像,如果镜像的CMD被替换可能会出现镜像生成的容器只启动一次或者服务无法启动的问题。
容器的cmd会让容器的cmd生效 不会让镜像的cmd被替换。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ARG
构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
格式:
ARG <参数名>[=<默认值>]
VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
数据持久化的目录
避免容器不断变大。
格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
EXPOSE
仅仅只是声明端口。
作用:
帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:
EXPOSE <端口1> [<端口2>…]
WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:
WORKDIR <工作目录路径>
USER
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:
USER <用户名>[:<用户组>]
HEALTHCHECK
用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
ONBUILD
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式:
ONBUILD <其它指令>
存出和载入镜像
用户可以使用docker save 和 docker load 命令来存出和载入镜像
存出镜像
docker save -o ubuntu_14.04.tar Ubuntu:14.04
载入镜像
docker load --input Ubuntu_14.04.tar
docker load -i name:tag
上传镜像
docker push name:[:tag] |
容器操作手册
运行容器
镜像,容器之所以小使用的一些环境例如lib库使用的是宿主机的
1).新建容器
docker create –it Ubuntu
; –it 参数的作用是以交互模式进入容器,并打开终端。412b30588f4a 是容器的内部 ID。
-i 让容易的标准输入保持打开(即交互式)
-t 选项让DOCKER分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
-d 守护状态运行 •
[root@docker01 ~]# docker run -it --name test -P --rm httpd /bin/bash
--rm:自动删除容器(退出容器后)
查看所有容器(包括没有运行)
docker ps –a 把-a 去了是显示运行。
一些常用的容器操作命令:
docker stop容器名停止
docker start 容器名开始
docker restart容器名重启
docker inspect 容器名 详细信息
查看容器的PID
docker inspect -f {{.State.Pid}} d1f49e72b961
进入容器
exec进入的容器会从新开启一个进程,attch不会
1)
docker attach 容器名
docker attach --sig-proxy=false 容器名
–sig-proxy=false 不使用容器转发信号,允许我们使用Ctrl + c 来推出.
2)
docker exec -it 容器名 /bin/bash
docker exec -it XXX /bin/bash
使用nsenter进入容器
nsenter 工具在util-linux包2.23版本后包含。
安装(linux系统自带2.23的可以直接使用)
tar zxf util-linux-2.24.tar.gz
cd util-linux-2.24
./configure --without-ncurses && make nsenter
cp nsenter /usr/local/bin
这个是PID查看
PID=$(docker inspect –format “{{.state.Pid}}”)
示例:
docker ps (查看正在运行的容器)
docker inspect -f {{.State.Pid}} d1f49e72b961 容器名 (获得PID号)
nssnter –target pid号 –mount –uts –net –pid –ipc
#查找容器ID
docker inspect -f "{{.Id}}" $(docker ps -q) |grep <PID>
#查找k8s pod name
docker inspect -f "{{.Id}} {{.State.Pid}} {{.Config.Hostname}}" $(docker ps -q) |grep <PID>
#如果PID是容器内运行子进程那docker inspect就无法显示了
for i in `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i &&echo ID=$i; done | grep -A 10 <PID>
注:
可以直接用exec在后边加入命令即可输出结果例如ipa等命令。
容器的导入和导出
导出容器
dcoker export 容器名 > centos7.tar
导入容器
cat centos7.tar | docker import – centos:test
删除容器
删除容器 -f强制删除
docker rm 容器的id/容器name
批量删除多个容器
docker rm $(docker ps –a -q)
删除所有容器
docker ps -a -q | xargs docker rm -f
docker日志
docker logs 容器名:查看日志
-f 就是跟随日志更新。
docker 默认的网络行为
docker安装后会自动创建3个网络,可以使用docker network命令查看
docker network ls
运行容器的时候可以使用–network参数来制定你的容器连接到哪一个网络。
bridge网络(NAT模式)
默认连接到docker0这个网络
brctl命令在centos中可以使用yum install bridge-utile
来安装。
该模式下不具有公网IP ,因为宿主机的IP地址与vethpair的地址不在同一个网段内
DOCKER采用NAT方式,荣容器的内部的服务监听端口与素质及的某一个端口PORT进行绑定,似的宿主机意外的世界可以主动将网络保温发送至容器内部
外界访问需访问宿主机的端口和地址
NAT模式在三层网络的实现手段,故肯定影响传输香炉
容器拥有独立,隔离的网络栈;让容器和宿主机及意外的世界通过NAT建立通信。
none(仅主机模式)
什么都没有的网络 安全
既没有网络环境和网络接口。
容器只有127.0.0.1模式
它使用的场景:
docker -run -it -network none 容器名
host模式(桥接模式)
host可以和其他网络共存
容器的IP地址同DOCKERhost的IP地址
端口不能用HOST主机冲突就是相同
container模式
该模式创建的容器和一个已经存在的容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的文件系统、进程列表等还是隔离的。两个容器的进程可以通过LO网卡设备通信。
两个容器之间不存在网络隔离,但是与之外的容器和其宿主机存在隔离。
注意:因为测试两个容器要共享一个NERWORK namespace,因此需要注意端口冲突情况否则第二个容器无法被启动。
创建一个网卡名字为my_net 删除是RM
docker network create -d bridge my_net
自定义网卡的网络地址段。
docker network create -d bridge --subnet 172.22.0.0./24 my_net2
端口映射为-P(小写)手动指定
端口-P(大写)自动进行端口映射 端口从32768开始。
指定IP
docekr run -itd --name web07 --network my_net2 -ip 172.22.0.8 busybox
连接 网络到容器
docker network connect my_net web02
跨主机docker网络方案
基于实现方案
1隧道方案
在laaS层的网络中应用的也比较多,大家公识是随着节点的增多增长复杂度会提升。而且除了问题追踪和解决是麻烦,大规模情况下需考虑着问题。
通过隧道,或者overlay Networking 的方式。
1、 Weave:UDP广播,本机寄哪里新的BR,通过PCAP互通。
2、 open vswitch(ovs):基于VxLAN和GRE协议,但是性能损失比较严重
3、 flannel:udp广播,VxLAN
通过路由方案
CNM
Calice:基于BGP协议的路由方案,支持很细致的ACL控制,对混合云亲和度比较高。
Macvlan:从逻辑和kernel层来看隔离性和性能最优的方案,基于二层隔离,所以需要二级路由器支持,大多数云服务商不支持,所以混合云比较难以实现。
基于网络模型分类
docker Libnetwork container network mode(CNM)阵营
包含以下框架
sandbox。包含容器网络栈的配置,包括容器的接口,路右边,DNS配置等的管理。linux network namespace是常见的一种sandbox的实现。sandbox中包含众多的网络中的若干Endpoint
Endpoint。Neutron中endpoint相对的概念应该是vnic,也就是虚拟机的虚拟网卡(也可以看成VIF).Endpoint的常见实现方阔veth pair、Openvswich的internal port。当sandbox要和外界通信的时候就是通过Endpoint连接到外界的,最简单情况就是连接到Bridge上。
network。是一组可以相互通信的Endpoint集合,组内Endpoint可以相互通信。不同的组内endpoint是不能通讯的,完全隔离。常见的实现报告阔liunx bridge,vlan等。
1docker swarm overlay
2Macvlan&IP Network drivers
3Calico
4contiv(from Cisco)
docker Libnerwork的优势就是原生,而且和docker容器生命周期结合紧密;缺点也是可以理解为是原生,被docker’绑架’
CNI
Container Nerwork Interface(CNI)阵营
kubernetes(k8s)
weave
Macvlan
Flannel。 CoreOS团队针对k8S设计的一个网络重载工具,预先留出一个网段,每个主机使用其中一部分,然后每个容器被分配到不同的容器,让所有容器以为直连,底层通过UDP/VxLAN等进行报文的封装和转发。默认端口是8285端口最为UDP封装的报文的端口,Vxlan使用的是8472
1.容器接直接使用目标IP访问,默认通过容器内部的eth0发送出去。
2.报文通过veth pair被发送到vethXXX。
3.vethXXX是直接连接到虚拟交换机的docker0的,报文通过虚拟bridge docker0发送出去。
4.查找路由表,外部容器的ip的报文都会发送到flannel0的虚拟网卡,这是一个P2P的虚拟网卡,然后报文就会被转发到监听在另一端的flanneld.
5.flanneld通过etcd维护了哥哥节点之间的路由表,吧原来的报文UDP封装一层,通过配置的iface发送出去。
6.报文通过主机之间的网络找到目标主机。
7.报文继续往上,到传输层,交给监听的8285端口的flanneld程序处理。
8书记被解包,然后发送flannel0虚拟网卡。
9.查找路由表,发现对应容器的报文要交给docker0
10.docker0找到连到自己的容器,把报文发送过去。
Calico
优势:
- 网络托补直观易懂,平行式扩展,可扩展性强
- 容器间网络三层隔离,无需要担心ARP风暴
- 基于iptable/linux kernel包转发效率高,损耗低。
- 更容器的编程语言(python)
- 社区活跃,正式版本较成熟
缺点 - calico仅支持TCP,UDP,ICMP and ICMPv6协议,如果你想使用L4协议,你只能选择Flannel,Weave或Docker Overlay Network
- Calico没有加密数据路由。用不可信网络上Calico建立覆盖网络是不安全的。
- 没有IP重叠支持。虽然Calico社区正在开发一个实验功能,将重叠IPv4包放入IPv6。但这只是一个辅助解决方案,并不王权支持技术上的IP重叠。
Contiv
Mesos CNI
docker network create -d overlay my_overlay 创建全局的网卡
iptables -F 清除防火墙的规则
iptables -save 查看防火墙的记录
docker network ls 查看网卡
docker19.03版本及以上的版本打开buildx
首先centos7,我用的就是centos7内核版本需要在4.0以上网上这么说,我用的3.1的内核会报2020/11/20 15:14:09 Cannot read directory /etc/binfmt.d: open /etc/binfmt.d: no such file or directory这个错误
利用 Docker 19.03 引入的插件 buildx,可以很轻松地构建多平台 Docker 镜像。buildx 是 docker build … 命令的下一代替代品,它利用 BuildKit 的全部功能扩展了 docker build 的功能。
启用 buildx 插件
Docker 版本不低于 19.03,同时还要通过设置环境变量 DOCKER_CLI_EXPERIMENTAL 来启用。可以通过下面的命令来为当前终端启用 buildx 插件:
export DOCKER_CLI_EXPERIMENTAL=enabled
#验证命令
docker buildx version
#输出的结果
github.com/docker/buildx v0.3.1-tp-docker 6db68d029599c6710a32aa7adcba8e5a344795a7
这个是抄的别人的:
如果在某些系统上设置环境变量 DOCKER_CLI_EXPERIMENTAL 不生效(比如 Arch Linux),你可以选择从源代码编译:
export DOCKER_BUILDKIT=1
docker build --platform=local -o . git://github.com/docker/buildx
mkdir -p ~/.docker/cli-plugins && mv buildx ~/.docker/cli-plugins/docker-buildx
启动binfmt_misc插件 据说这个有脚本直接就做了不需要你干嘛运行一下就行特权?我就运行这个一部的时候出错
docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
原因就是4.0的内核 不过我直接升级到5.5.。。。不知道是不是4.0反正切换到。5.5内核的时候就成功了。
验证是 binfmt_misc 否开启:
ls -al /proc/sys/fs/binfmt_misc/
内核升级的方法贴这里吧
抄的
rpm安装包可以通过这个网站下载:
这个是CentOS6 x64 : http://elrepo.org/linux/kernel/el6/x86_64/RPMS/
这个是CentOS7 x64 : http://elrepo.org/linux/kernel/el7/x86_64/RPMS/ 或者 http://mirror.rc.usf.edu/compute_lock/elrepo/kernel/el7/x86_64/RPMS/
ubuntu的内核地址 http://kernel.ubuntu.com/~kernel-ppa/mainline/
RPM-GPG-KEY-elrepo.org : https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum install kernel-lt-4.4.103-1.el7.elrepo.x86_64.rpm -y #yum安装内核包
awk '$1=="menuentry" {print $2,$3,$4}' /etc/grub2.cfg #查看默认启动顺序
#如果没有外网先安装key,下载地址:https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm --import RPM-GPG-KEY-elrepo.org
rpm -ivh kernel-lt-4.4.103-1.el7.elrepo.x86_64.rpm -y
#设置默认启动项,0是按menuentry顺序。比如要默认从第四个菜单项启动,数字改为3,若改为 saved,则默认为上次启动项。
sed -i "s/GRUB_DEFAULT=saved/GRUB_DEFAULT=0/g" /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot #重启机器
uname -r #重启后查看内核版本
#注:装新内核是占用/boot空间的,可以使用yum remove kernel-ml-4.10.11-1.el6.elrepo.x86_64方式清理不用的kernel
#安装yum,kenel源
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
#稳定的kernel安装最新版
yum --enablerepo=elrepo-kernel install kernel-ml
#查看可用的kennel
yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
使用方法
据说不会将镜像保存在本地会在dockerhub上生成一个镜像不知道真的假的。
docker buildx build -t armcen .