ref: https://www.jianshu.com/p/62e71584d1cb
1 docker rootless模式
首先,安全原因,请尽量使用rootless模式来运行容器。
https://docs.docker.com/engine/security/rootless/
要安装uidmap
在rootless模式下,Docker守护进程(dockerd)和所有的容器都是以普通用户的身份运行的,而不是以root用户运行。
正常情况下,Docker需要使用root用户权限来进行一些操作,比如创建和管理容器的内核命名空间和cgroups。但是,rootless模式通过使用user_namespaces功能,使得一个普通用户可以在其自己的用户命名空间中拥有“root”权限。这使得Docker可以在没有真正的root权限的情况下运行。
这种模式的优点是,即使Docker进程被攻击者利用,攻击者也不能获取到主机的root权限,从而增强了系统的安全性。
完成后试试这个
docker run -d --name dind-rootless --privileged docker:24.0-dind-rootless
2. Containerd
已经被docker组织捐给cncf了,这玩意是k8s的默认容器
3. podman
平替,用法基本一致,细节上还是有些区别。【同时装的话且alias docker=podman的话,which docker可以找docker本身的位置】
podman没有dameaon守护进程来运行,如果用户退了podman容器作为用户会话子进程会一同被杀掉/关掉, 要用screen和tmux维持。或者nohup podman start xxx &。
还有就是网络组方面拉跨 由于没有 link 别的容器的方法,只能建pod放一起互联。podman compose也因此经常有问题。
podman pod 不是很方便。建立pod时要把端口都一股脑都声明完。-p 123:123 -p 124:124 -p 1234:1234 -p ....一大长串
OCI 对容器 runtime 的标准主要是指定容器的运行状态,和 runtime 需要提供的命令。下图可以是容器状态转换图:
ref: https://www.51cto.com/article/687502.html
- init 状态:这个是我自己添加的状态,并不在标准中,表示没有容器存在的初始状态
- creating:使用 create 命令创建容器,这个过程称为创建中
created:容器创建出来,但是还没有运行,表示镜像和配置没有错误,容器能够运行在当前平台
- running:容器的运行状态,里面的进程处于 up 状态,正在执行用户设定的任务
- stopped:容器运行完成,或者运行出错,或者 stop 命令之后,容器处于暂停状态。这个状态,容器还有很多信息保存在平台中,并没有完全被删除
4. 不要贪多先学这俩吧
runc:这是 OCI 的一个参考实现,也是 Docker 的底层技术。runc 是一个轻量级的工具,可以直接运行 OCI 容器。
CRI-O:这是一个轻量级的容器运行时,专为 Kubernetes 设计。它与 OCI 容器运行时规范兼容。
gVisor:这是一个由 Google 开发的沙盒容器运行时。它提供了一个隔离的环境,用于运行不信任的应用程序。gVisor 也是 OCI 兼容的。
Kata Containers:这是一个开源项目,通过提供轻量级虚拟机,对容器进行更强的隔离,同时保持短暂性和性能。Kata Containers 是 OCI 兼容的。
- LXC/LXD
Linux 容器,值得拥有
LXC(Linux Containers)和LXD是Linux系统的容器技术。
LXC:Linux容器(LXC)是一个操作系统级别的虚拟化方法,用于在单个控制主机上运行多个隔离的Linux系统(容器)。LXC使用了Linux内核中在2.6.24版本引入的cgroups功能,让主机CPU能将内存划分给不同的容器。它还结合了网络命名空间以实现应用的隔离和沙箱化。
LXD:LXD是LXC的扩展,旨在为管理LXC容器提供更用户友好和可扩展的解决方案。LXD提供了一种REST API,用于远程管理容器,并使用基于镜像的工作流程取代模板来创建容器。LXD还提供了高级功能,如容器快照和实时迁移。
可以将LXC看作是一种轻量级的VM技术,而LXD是一种更高级、更友好的方式来管理这些容器。这些容器可以用来在隔离的环境中运行应用程序或服务,类似于使用虚拟机的方式,但开销更小,因为容器共享主机系统的内核,而不需要为每个虚拟机提供完整的操作系统。
底下是Go的特性和(优点?)
1、兼顾开发效率和性能
Go语言兼顾开发效率和性能。可以像Python那样有很快的开发速度,也可以像C++那样有很快的执行速度。
2、编译速度很快
编译速度很快,减少编译等待时间。其实编译时间长,对开发人员未必是坏事,可以有个正当理由摸鱼了,哈哈!
3、没有面向对象的束缚
Go语言有些面向对象的特性,没有太多面向对象的束缚,但是一样可以做到代码复用。
Go语言虽然不是面向对象的语言,但是依然支持面向对象的开发模式,只是没有继承这种特性。
Go语言推荐使用组合而非继承的设计模式,只需要将一种类型嵌入到另一种类型,就能复用所有的功能。
4、自带垃圾回收器
自带垃圾回收器,不需要用户自己管理内存。
5、最吸引我的特性 — 并发
Go语言最吸引我的特性的是它天生对并发的支持。采用了类似虚拟线程的概念,使用很少的代码,占用更少的内存,就可以写出复杂的并发程序。
Go语言的并发同步模型,是以消息传递为模型。通过通道(channel)在各个goroutine之间传递消息,来实现同步访问,而非通过对数据加锁来实现同步,这一点与其他语言不同。
Go语言内部实现了一个逻辑处理器,每个逻辑处理器对应一个线程,每个逻辑处理器可以处理多个并发程序。正是因为这种并发程序不会独占线程的方式,所以Go语言的并发会占用更少的线程和内存。
6、独特的接口实现机制
Go语言具有独特的接口实现机制,允许用户对行为进行建模,而不是对类型进行建模。
在Go语言中,不需要声明某个类型实现了某个接口,编译器会自动判断一个类型的实现是否符合正在使用的接口。
说白了就是不需要强制指定某个类实现了某个接口。
7、独特的_符号
Go语言的_特性是为了让程序的可读性更强,Go编译器不允许声明导入某个包却不使用,也不允许在函数中声明了某个变量却不使用。
8、init函数
Go语言中可以定义init函数,程序中每个代码文件里的init函数都会在main函数执行前调用。
9、允许一个函数返回多个值
Go语言中允许一个函数返回多个值,单就这一点就可以让程序员写代码更舒心了,有时候代码写的很舒畅的时候,突然为了几个简单的返回值再去定义一个对象,实在有点糟心。
10、所有的变量都以值的方式传递。
Go语言中,所有的变量都以值的方式传递。指针变量有点特殊。因为指针变量的值是所指向的内存地址,在函数间传递指针变量,是在传递这个地址值,所有依旧被看做以值的方式在传递。
11、支持闭包
Go语言支持闭包,在闭包里并不是拿到外部变量的副本,而是直接访问外层函数作用域中声明的这些变量本身。
12、关键字Defer
Defer后的代码会在函数返回时才会执行。哪怕函数意外奔溃终止,也能保证Defer安排的函数会被执行。
引入这个关键字的初衷是为了提高代码可读性。可以将打开、关闭资源的代码成对靠近的写在一起,避免了try…catch…finally这样散落的代码组织形式。
13、函数和方法
Go语言有些函数式编程的特性。Go语言中有函数和方法,他俩的区别是:如果声明的函数带有接受者,则是方法。
方法的接受者分为:指针接受者、值接受者。使用指针接受者的方法,只能使用指针类型调用。使用值接受者的方法,使用指针类型和值类型都可以调用。