全部的 K8S学习笔记总目录,请点击查看。
本节主要介绍containerd的基本概念,以及docker的一些总结。
containerd
容器运行时(ContainerRuntime),运行于 kubernetes(k8s)集群的每个节点中,负责容器的整个生命周期,其中 docker 是目前应用最广的。
随着容器云的发展,越来越多的容器运行时涌现。为了解决这些容器运行时和 k8s 的集成问题,在 k8s 1.5 版本中,社区推出了
CRI(ContainerRuntimeInterface,容器运行时接口),以支持更多的容器运行时。
Kubelet 通过 CRI 和容器运行时进行通信,使得容器运行时能够像插件一样单独运行。可以说每个容器运行时都有自己的优势,这就允许用户更容易选择和替换自己的容器运行时。
CRI & OCI
OCI(OpenContainerInitiative,开放容器计划)定义了创建容器的格式和运行时的开源行业标准,包括镜像规范(ImageSpecification)和运行时规范(
RuntimeSpecification)。
镜像规范定义了 OCI 镜像的标准。高层级运行时将会下载一个 OCI 镜像,并把它解压成 OCI 运行时文件系统包(filesystembundle)。
运行时规范则描述了如何从 OCI 运行时文件系统包运行容器程序,并且定义它的配置、运行环境和生命周期。如何为新容器设置命名空间(
namepsaces)和控制组(cgroups),以及挂载根文件系统等等操作,都是在这里定义的。它的一个参考实现是runC。我们称其为低层级运行时(Low-levelRuntime)。除
runC 以外,也有很多其他的运行时遵循 OCI 标准,例如 kata-runtime。
为什么弃用Docker
目前 docker 仍是 kubernetes 默认的容器运行时。那为什么会选择换掉 docker 呢?主要的原因是它的复杂性。
我们总结了 docker,containerd 以及 cri-o 的详细调用层级。Docker
的多层封装和调用,导致其在可维护性上略逊一筹,增加了线上问题的定位难度(貌似除了重启docker,我们就毫无他法了)。Containerd 和
cri-o 的方案比起 docker 简洁很多。因此我们更偏向于选用更加简单和纯粹的 containerd 和 cri-o 作为我们的容器运行时。
我们对 containerd 和 cri-o 进行了一组性能测试,包括创建、启动、停止和删除容器,以比较它们所耗的时间。containerd
在各个方面都表现良好,除了启动容器这项。从总用时来看,containerd 的用时还是要比 cri-o 要短的。
从功能性来讲,containerd 和 cri-o 都符合 CRI 和 OCI 的标准。从稳定性来说,单独使用 containerd 和 cri-o
都没有足够的生产环境经验。但庆幸的是,containerd 一直在 docker 里使用,而 docker 的生产环境经验可以说比较充足。可见在稳定性上
containerd 略胜一筹。所以我们最终选用了 containerd
containerd操作
更换 containerd 后,常用的 docker 命令也不再有用,containerd 命令行客户端如下图所示:
- ctr -v 输出的是 containerd 的版本,crictl -v 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。
- 一般来说你某个主机安装了 k8s 后,命令行才会有 crictl 命令。而 ctr 是跟 k8s 无关的,你主机安装了 containerd 服务后就可以操作
ctr 命令。 - 用 crictl 运行 Pod 沙盒对容器运行时排错很有帮助。 在运行的 Kubernetes 集群中,沙盒会随机地被 kubelet 停止和删除。因此
crictl 尽量不要在单独起容器的情况下使用,因为容器会被停止和删除。
先提前放出docker/ctr/crictl之间命令的对比,后面会详细介绍。
命令 | docker | ctr(containerd) | crictl(kubernetes) |
---|---|---|---|
查看运行的容器 | docker ps | ctr task ls/ctr container ls | crictl ps |
查看镜像 | docker images | ctr image ls | crictl images |
查看容器日志 | docker logs | 无 | crictl logs |
查看容器数据信息 | docker inspect | ctr container info | crictl inspect |
查看容器资源 | docker stats | 无 | crictl stats |
启动/关闭已有的容器 | docker start/stop | ctr task start/kill | crictl start/stop |
运行一个新的容器 | docker run | ctr run | 无(最小单元为pod) |
打标签 | docker tag | ctr image tag | 无 |
创建一个新的容器 | docker create | ctr container create | crictl create |
导入镜像 | docker load | ctr image import | 无 |
导出镜像 | docker save | ctr image export | 无 |
删除容器 | docker rm | ctr container rm | crictl rm |
删除镜像 | docker rmi | ctr image rm | crictl rmi |
拉取镜像 | docker pull | ctr image pull | ctictl pull |
推送镜像 | docker push | ctr image push | 无 |
登录或在容器内部执行命令 | docker exec | 无 | crictl exec |
清空不用的容器 | docker image prune | 无 | crictl rmi –prune |
更多命令操作,可以直接在命令行输入命令查看帮助。
1 | docker --help |
以下是各种客户端操作 containerd 的命令,因为之后会安装 k8s,很多操作通过 k8s 直接就完成了,所以对应命令可以先做了解即可。
containerd 客户端 ctr
ctr 是 containerd 项目的一部分提供的命令行客户端。如果一台机器上运行了 containerd,那么ctr二进制文件也一般会进行安装。
由于 containerd 有 namespaces 的概念,对于上层编排系统的支持,ctr 客户端主要区分了3个命名空间分别是k8s.io、moby和default,以上我们用
crictl 操作的均在 k8s.io 命名空间,使用 ctr 看镜像列表就需要加上 -n 参数。crictl 只有一个 k8s.io 命名空间,但是没有 -n 参数。
我们知道 Docker 也是默认调用的 containerd, Docker 使用的命名空间默认是 moby,而不是 default,所以假如我们用 docker
启动容器,那么我们也可以通过 ctr -n moby 来定位容器信息。
【温馨提示】ctr images pull 拉取的镜像默认放在default,而 crictl pull 和 kubelet 默认拉取的镜像都在 k8s.io 命名空间下。所以通过
ctr 导入镜像的时候特别注意一点,最好指定命名空间。
命令示例
1 | # 注意 -n 不能放在命令最后面,下面查看的镜像是一样的 |
ctr 命令
ctr 命令的参数和全局参数如下。
参数命令的格式为:ctr [global options] command [command options] [arguments...]
全局参数可以在任何命令后面使用,并且可以多个参数组合使用。
1 | COMMANDS: |
查看版本
1
2ctr -v
ctr --version指定空间
1
ctr -n k8s.io image ls
namespace 相关操作
ctr 所有的命令都支持 -n 参数,用于指定命名空间,如果不指定命名空间,默认为default命名空间。命名空间的概念类似于 docker
的仓库,但是不同的是,docker 的仓库是一个集中的仓库,而 ctr 的命名空间是分布式的,每个命名空间都是一个独立的仓库。
命令 ctr namespace
用于管理命名空间,包括查看、创建和删除命名空间。可以简化为 ctr ns
。
查看命名空间
1
ctr namespace ls
创建命名空间
1
ctr namespace create k8s.io
删除命名空间
1
ctr namespace rm k8s.io
镜像相关操作
镜像相关命令如下。
1 | # ctr image -h |
拉取推送镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 拉取镜像
# docker默认是docker.io官网去找镜像,所以docker拉去镜像可以这样写:docker pull nginx:alpine,而containerd没有默认仓库,所以必须写完整的镜像名字才能拉去镜像
ctr i pull docker.io/library/nginx:alpine
# 推送镜像到harbor
#
# --namespace=k8s.io 指定命名空间,不是必须,根据环境而定
# --skip-verify 跳过认证
# --user 指定harbor用户名及密码
ctr --namespace=k8s.io images push harbor.mydomain.com/k8s/pause:1.25.1 --skip-verify --user admin:Harbor12345
# 不想 -u user:password 可以在配置文件进行配置,也可以使用 nerdctl ,下面有介绍
# 拉取带认证的镜像
ctr images pull --user admin:Harbor12345 --tlscacert=/etc/containerd/harbor.mydomain.com/ca.crt harbor.mydomain.com/k8s/pause:1.25.1检查镜像列表,确认镜像是否存在以及镜像的完整性,主要查看其中的
STATUS
,complete
表示镜像是完整可用的状态。1
2ctr image check
ctr i check导入/导出镜像
1
2ctr i export nginx.tar.gz docker.io/library/nginx:alpine
ctr i import nginx.tar.gz查看镜像列表
1
2
3
4ctr i ls
ctr i list
# 只查看镜像名称
ctr i ls -q挂载/卸载镜像
1
2
3# ctr 支持将镜像挂载到指定目录,这样就可以直接访问镜像中的文件了,而不需要启动容器,可以确认镜像中的文件是否正确
ctr i mount docker.io/library/nginx:alpine /tmp/nginx
ctr i unmount /tmp/nginx删除镜像
1
2ctr i rm nginx:alpine
ctr i remove nginx:alpine打标签
1
2# crictl 没有 tag 命令,只能使用 nerdctl 和 ctr,必须指定命名空间,要不然 kubelet 无法使用。
ctr -n k8s.io i tag my-nginx:v1 harbor.mydomain.com/my-nginx:v1镜像转换
1
2
3
4# ctr 支持将镜像转换为 OCI 格式,这样就可以使用其他容器运行时运行镜像了,比如 runc
ctr i convert --oci nginx:alpine nginx:alpine-oci
# 也支持将 OCI 格式的镜像转换为 docker 格式
ctr i convert nginx:alpine nginx:alpine-docker镜像构建
containerd 不提供开箱即用的镜像构建支持。一般使用更高级别的工具用来构建镜像,比如 docker。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20cat > Dockerfile <<EOF
FROM nginx:alpine
RUN echo 'Build Image From Containerd' > /usr/share/nginx/html/index.html
EOF
# 可以使用docker构建镜像,然后导出到本地,再使用ctr导入到containerd
docker build -t my-nginx:v1 .
docker save -o my-nginx.tar my-nginx:v1
ctr images import my-nginx.tar
# 或者使用nerdctl进行构建,与docker功能一样
# 不加-n指定命名空间,crictl看不到,kubelet也不能使用它,默认在default命名空间下
nerdctl -n k8s.io build -t nginx:nerctl -f ./Dockerfile .
# 参数解释:(下一节会有 nerctl 介绍)
# -t:指定镜像名称
# . :当前目录Dockerfile
# -f:指定Dockerfile路径
# --no-cache:不缓存
容器相关操作
容器相关操作,包括创建、启动、停止、删除等。
1 | :~# ctr container --help |
创建容器
1
2# container 只是创建了静态容器,此时容器还未启动运行。如果要启动容器,需要使用 task start 命令。
ctr c create docker.io/library/nginx:alpine my-nginx删除容器
1
2
3ctr c rm my-nginx
ctr c delete my-nginx
ctr c del my-nginx查看指定容器的信息
1
ctr c info my-nginx
查看所有容器
1
2ctr c ls
ctr c list容器标签
1
2# 容器标签可以用来标记容器,方便管理(只能通过 ctr c info 查看, ctr ls 不会显示)
ctr c label my-nginx mylabel=nginx容器检查点
1
2
3# 容器检查点可以用来备份容器,方便恢复 (没有测试)
ctr c checkpoint my-nginx mycheckpoint
ctr c restore my-nginx mycheckpoint
管理任务
管理任务,包括创建、启动、停止、删除等。
1 | # ctr task --help |
启动已经创建的容器
1
2ctr t start my-nginx
ctr t start -d my-nginx查看任务
1
2ctr t ls
ctr t list查看任务中的进程
1
2# 注意:这里的进程是指容器中进程在宿主机上的进程号。
ctr t ps my-nginx任务中执行命令
1
2
3ctr t exec my-nginx ls /
# 进入容器内部终端,997,是随便指定的,只要不重复就行
ctr t exec --exec-id 997 -t my-nginx /bin/sh暂停/回复任务
1
2ctr t pause my-nginx
ctr t resume my-nginx杀死/删除任务
1
2
3
4
5
6
7
8# 只是给任务发送了 SIGTERM 信号,任务还是存在的,状态为 stopped
ctr t kill my-nginx
# 删除任务,任务必须是 stopped 状态
ctr t rm my-nginx
ctr t delete my-nginx
# 给特定进程发送信号,这里是把刚刚创建的进程强制杀死
ctr t kill --exec-id 999 -s SIGTERM my-nginx关于信号量相关的内容,可以参考这篇文章 Linux 信号量详解。
获取任务的指标
1
2# 我们可以通过metric命令获取容器关于cgroup相关的信息,包括CPU、内存、PID的限额和使用情况等。
ctr t metric my-nginx
运行容器
容器运行需要进行两步,第一步是创建容器,第二步是启动容器。
使用 ctr run
命令可以一步到位,创建并启动容器。
1 | # ctr run --help |
创建并启动容器
1 | ctr run -d -t --net-host docker.io/library/nginx:alpine my-nginx |
containerd 客户端 nerdctl
推荐使用 nerdctl,使用效果与 docker 命令的语法一致
二进制包的 github 下载链接:https://github.com/containerd/nerdctl/releases
- 精简 (nerdctl-{version}-linux-amd64.tar.gz): 只包含nerdctl
- 完整 (nerdctl-full-{version}-linux-amd64.tar.gz): 包含 containerd, runc, and CNI等依赖
nerdctl 的目标并不是单纯地复制 docker 的功能,它还实现了很多 docker 不具备的功能,例如延迟拉取镜像(lazy-pulling)、镜像加密(imgcrypt)等。
安装 nerdctl
精简版只包含nerdctl,完整版包含nerdctl和CNI插件等依赖,k8s的网络插件会在/opt/cni/bin/下会生成cni插件目录。这里选择完整版进行安装,因为启动容器的时候配置网络需要cni网络插件的支持。
精简版 nerdctl 安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-0.22.2-linux-amd64.tar.gz
# 解压
tar -xf nerdctl-0.22.2-linux-amd64.tar.gz
# 查看解压后的文件,可以看见除了nerdctl还有containerd-rootless-setuptool.sh、containerd-rootless.sh,另外两个文件是用来在非root用户下使用nerdctl的
ls -l
total 37624
-rwxr-xr-x 1 root root 21562 Aug 1 2022 containerd-rootless-setuptool.sh
-rwxr-xr-x 1 root root 7032 Aug 1 2022 containerd-rootless.sh
-rwxr-xr-x 1 root root 27807744 Aug 1 2022 nerdctl
-rw-r--r-- 1 root root 10685899 Aug 1 2022 nerdctl-0.22.2-linux-amd64.tar.gz
# 将nerdctl复制到/usr/local/bin/目录下,这样就可以直接使用nerdctl命令了。具体目录根据机器上的PATH环境变量来定。
cp nerdctl /usr/local/bin/完整版 nerdctl 安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-full-0.22.2-linux-amd64.tar.gz
# 解压后还有如下4个目录
# 1. bin(二进制模式,包括 nerdctl buildkitd runc tini等)
# 2. lib(systemctl 的 service 文件)
# 3. libexec(cni组件)
# 4. share(说明文档)
tar -xf nerdctl-full-0.22.2-linux-amd64.tar.gz -C /usr/local/
# 将service文件复制到/etc/systemd/system/目录下
cp /usr/local/lib/systemd/system/*.service /etc/systemd/system/
# 启动服务buildkit
systemctl enable buildkit containerd --now
systemctl status buildkit containerd安装 buildkit 支持构建镜像
buildkit GitHub地址: https://github.com/moby/buildkit
使用精简版 nerdctl 无法直接通过 containerd 构建镜像,需要与 buildkit 组全使用以实现镜像构建。当然你也可以安装上面的完整
nerdctl,完整版可以直接使用 nerdctl build 命令构建镜像,是因为完整版已经有现成的 buildkit.service 服务了。buildkit项目是Docker公司开源出来的一个构建工具包,支持OCI标准的镜像构建。它主要包含以下部分:
- 服务端buildkitd,当前支持runc和containerd作为worker,默认是runc;
- 客户端buildctl,负责解析Dockerfile,并向服务端buildkitd发出构建请求。
- buildkit是典型的C/S架构,client和server可以不在一台服务器上。而nerdctl在构建镜像方面也可以作为buildkitd的客户端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38# 下载地址 https://github.com/moby/buildkit/releases
wget https://github.com/moby/buildkit/releases/download/v0.10.4/buildkit-v0.10.4.linux-amd64.tar.gz
# 解压之后只有一个bin目录,里面有buildkit所需要的二进制文件
# 以下的命令会将buildkit的二进制文件合并到/usr/local/bin/目录下
tar -xf buildkit-v0.10.4.linux-amd64.tar.gz -C /usr/local/
# buildkit需要配置两个文件:
# 1. /usr/lib/systemd/system/buildkit.socket
# 2. /usr/lib/systemd/system/buildkit.service
cat > /etc/systemd/system/buildkit.socket <<EOF
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
[Socket]
ListenStream=%t/buildkit/buildkitd.sock
SocketMode=0660
[Install]
WantedBy=sockets.target
EOF
cat > /etc/systemd/system/buildkit.service << EOF
[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentation=https://github.com/moby/buildkit
[Service]
# Replace runc builds with containerd builds
ExecStart=/usr/local/bin/buildkitd --addr fd://
[Install]
WantedBy=multi-user.target
EOF
# 启动buildkit
systemctl daemon-reload
systemctl enable buildkit --now设置nerdctl自动补全
1
2
3
4
5# 编辑文件
vim /etc/profile
source <(nerdctl completion bash)
# 让其生效
source /etc/profile
namespace 相关操作
创建 namespace
1
nerdctl namespace create mynamespace
列出 namespace
1
nerdctl namespace ls
删除 namespace
1
nerdctl namespace rm mynamespace
镜像相关操作
拉取镜像
1
nerdctl pull nginx:alpine
列出镜像
1
nerdctl image ls
删除镜像
1
nerdctl image rm nginx:alpine
拉取推送镜像
1
2
3
4
5
6# 拉取镜像
nerdctl pull nginx:alpine
# 重命名镜像
nerdctl image tag nginx:alpine harbor.mydomain.com/library/nginx:alpine
# 推送镜像
nerdctl push harbor.mydomain.com/library/nginx:alpine更详细的镜像拉取操作请参考下面的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39# http方式,配置如下:
mkdir -p /etc/containerd/harbor.mydomain.com
cat > /etc/containerd/certs.d/harbor.mydomain.com/hosts.toml <<EOF
server = "https://docker.io"
[host."http://myharbor-minio.com"]
capabilities = ["pull", "resolve","push"]
# skip_verify = true
# ca = "ca.crt" #相对路径
# ca = "/opt/auth/ca.crt" #绝对路径
# ca = ["/opt/auth/ca.crt"]
# ca = ["ca.crt"]
# client = [["/opt/auth/nginx.cclinux.cn.crt", "/opt/auth/nginx.cclinux.cn.key"]]
EOF
# https方式,配置如下:
mkdir -p /etc/containerd/certs.d/harbor.secure.mydomain.com:443
cat > /etc/containerd/certs.d/harbor.secure.mydomain.com\:443/hosts.toml <<EOF
server = "https://docker.io"
[host."https://harbor.secure.mydomain.com:443"]
capabilities = ["pull", "resolve","push"]
skip_verify = true
# ca = "ca.crt" #相对路径
# ca = "/opt/auth/ca.crt" #绝对路径
# ca = ["/opt/auth/ca.crt"]
ca = ["/etc/containerd/harbor.secure.mydomain.com/ca.crt"]
# client = [["/opt/auth/nginx.cclinux.cn.crt", "/opt/auth/nginx.cclinux.cn.key"]]
EOF
# 可以通过 nerdctl 登录
echo Harbor12345 | nerdctl login --username "admin" --password-stdin harbor.secure.mydomain.com:443
# 登出命令
# nerdctl logout harbor.secure.mydomain.com:443
# 推送到私有仓库
nerdctl --insecure-registry --namespace=k8s.io push harbor.secure.mydomain.com:443/k8s/pause:1.25.1镜像构建
1
2
3
4# 从Dockerfile构建镜像
nerdctl build -t nginx:my-alpine -f Dockerfile .
# 从Dockerfile构建镜像并推送到私有仓库
nerdctl build -t harbor.secure.mydomain.com:443/k8s/nginx:alpine -f Dockerfile .
容器相关操作
创建容器
1
nerdctl run -d --name mynginx -p 80:80 nginx:alpine
列出容器
1
2nerdctl ps -a
nerdctl container ls -a删除容器(停止容器后才能删除)
1
2
3
4
5nerdctl stop mynginx
nerdctl rm mynginx
nerdctl container stop mynginx
nerdctl container rm mynginx进入容器
1
2
3nerdctl exec -it mynginx sh
nerdcrl container exec -it mynginx sh查看容器日志
1
2
3nerdctl logs mynginx
nerdctl container logs mynginx查看容器详细信息
1
2
3nerdctl inspect mynginx
nerdctl container inspect mynginx查看容器内进程
1
nerdctl top mynginx
k8s 操作 containerd 的客户端 crictl
crictl 命令
这里我使用的是 crictl v1.26.0 版本,命令里面有些是与 pod 相关的,暂时略过,这里只介绍与 container 相关的命令。
1 | crictl -h |
命令示例
使用 crictl 命令之前,需要先配置 /etc/crictl.yaml
如下:
1 | vim /etc/crictl.yaml |
命令行示例:
1 | # crictl 没有 -n 参数,操作都在 k8s.io 命名空间下。 |
image 相关操作
1
2
3
4
5
6
7
# 查看所有的 image
crictl image list
# 拉取 image
# 注意:回车之后屏幕会卡住,不要着急,正常现象。crictl 没有进度条,拉取镜像的过程中,会一直卡在这里,直到拉取完成,只能耐心等待完成。
crictl pull nginx:1.25
# 删除 image
crictl rmi nginx:1.25
container 相关操作
1
2
# 查看所有的 container
crictl ps -a
crictl 运行一个容器比较复杂,需要书写两个 json 文件
比如以下两个文件,一个是 pod-config.json,一个是 container-config.json,其中 pod-config.json 是 pod 的配置,container-config.json 是 container 的配置。
pod 的概念是 k8s 中有的,这里先知道即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ cat pod-config.json
{
"metadata": {
"name": "nginx-sandbox",
"namespace": "default",
"attempt": 1,
"uid": "hdishd83djaidwnduwk28bcsb"
},
"log_directory": "/tmp",
"linux": {
}
}
$ cat container-config.json
{
"metadata": {
"name": "busybox"
},
"image":{
"image": "busybox"
},
"command": [
"top"
],
"log_path":"busybox.0.log",
"linux": {
}
}
1
2
3
4
5
6
7
8
9
10
# 根据以上两个文件创建 container, 注意如果 k8s 没有安装好可能会报错,因为 crictl 是 k8s 的客户端,需要 k8s 的环境。
crictl run container-config.json pod-config.json
# 删除 container
crictl rm mynginx
# 进入 container,注意这里的 container id 是 crictl ps -a 查看到的
crictl exec -it <container id> sh
# 查看 container 日志
crictl logs <container id>
# 查看 container 详细信息
crictl inspect <container id>
总结
- 使用 k8s 后,对于容器的操作,基本上都是通过 kubelet 完成,这个之后会使用到。
- 镜像的构建推荐使用
docker build
等方式,推送到镜像仓库后,再通过 containerd 进行使用。 - 查看容器中的日志,使用
crictl logs
命令。 - 常规的对于 containerd 的操作,推荐使用
nerdctl
命令,使用效果与 docker 命令的语法一致。
docker 总结
实用技巧
清理主机上所有退出的容器
1
$ docker rm $(docker ps -aq)
调试或者排查容器启动错误
1
2
3## 若有时遇到容器启动失败的情况,可以先使用相同的镜像启动一个临时容器,先进入容器
$ docker run --rm -ti <image_id> sh
## 进入容器后,手动执行该容器对应的ENTRYPOINT或者CMD命令,这样即使出错,容器也不会退出,因为bash作为1号进程,我们只要不退出容器,该容器就不会自动退出
docker总结
- 为了解决软件交付过程中的环境依赖,同时提供一种更加轻量的虚拟化技术,Docker出现了。
- 2013年诞生,15年开始迅速发展,从17.03月开始,使用时间日期管理版本,稳定版以每季度为准。
- Docker是一种CS架构的软件产品,可以把代码及依赖打包成镜像,作为交付介质,并且把镜像启动成为容器,提供容器生命周期的管理。
- 使用yum部署docker,启动后通过操作docker这个命令行,自动调用docker daemon完成容器相关操作。
- 常用操作,围绕
镜像|容器|仓库
三大核心要素- systemctl start|stop|restart docker
- docker build | pull -> docker tag -> docker push
- docker run –name my-demo -d -p 8080:80 -v /opt/data:/data demo:v20200327 ping xx.com
- docker cp /path/a.txt mycontainer:/opt
- docker exec -ti mycontainer /bin/sh
- docker logs -f –tail=100 mycontainer
- 通过dockerfile构建业务镜像,先使用基础镜像,然后通过一系列的指令把我们的业务应用所需要的运行环境和依赖都打包到镜像中,然后通过CMD或者ENTRYPOINT指令把镜像启动时的入口制定好,完成封装即可。有点类似于,先找来一个集装箱模板(
基础镜像),然后把项目依赖的服务都扔到集装箱中,然后设置好服务的启动入口,关闭箱门,即完成了业务镜像的制作。 - 容器的实现依赖于内核模块提供的namespace和control-group的功能,通过namespace创建一块虚拟空间,空间内实现了各类资源(
进程、网络、文件系统)的隔离,提供control-group实现了对隔离的空间的资源使用的限制。 - docker镜像使用分层的方式进行存储,根据主机的存储驱动的不同,实现方式会不同,kernel在3.10.0-514以上自动支持overlay2存储驱动,也是目前Docker推荐的方式。
- 得益于分层存储的模式,多个容器可以通过copy-on-write的策略,在镜像的最上层加一个可写层,同时利用存储驱动的UnionFS的能力,实现一个镜像快速启动多个容器的场景。
- docker的网络模式分为4种,最常用的为bridge和host模式。bridge模式通过docker0网桥,启动容器的时候通过创建一对虚拟网卡,将容器连接在桥上,同时维护了虚拟网卡与网桥端口的关系,实现容器间的通信。容器与宿主机之间的通信通过iptables端口映射的方式,docker利用iptables的PREROUTING和POSTROUTING的nat功能,实现了SNAT与DNAT,使得容器内部的服务被完美的保护起来。
- 本章重点内容是docker的核心要素及基础的操作,实现原理以及docker的网络模式为选修包,目的为了帮助有docker基础及经验的同学更好的进一步理解docker。