【CKA考试笔记】一、容器基础

使用 containerd + nerdctl 替换 dokcer

由于k8s1.24版本的kubelet中已经删除了dockershim,无法直接配置docker来作为k8s的runtime了,所以推荐使用containerd来作为k8s的运行时

什么是容器?

容器就好比是一个虚拟机,但是相比虚拟机,它轻量很多,只包含了容器内应用程序运行所必要的环境,去掉了其他不需要的部分,镜像是容器的模板,是静态的文件,当我们使用镜像在宿主机中创建一个容器,容器里的进程感知到的生态环境仍然是容器内(源机器)的运行环境,但是会占用宿主机的cpu、内存资源

谁来负责容器的管理(创建、删除、启动、关闭)?

负责容器的管理——低级别的runtime运行时
runtime分为高级别运行时和低级别运行时,低级别的运行时功能单一,就只是单纯地负责容器的创建、删除、启动、关闭等

低级别运行时:
runc
gvisor
kata
lxc

直接使用低级别运行时进行容器管理非常繁琐、效率低下,因此有了高级别运行时
高级别运行时底层调用低级别运行时来管理容器,一般选择调用runc
高级别运行时不仅可以管理容器,还可以管理镜像

高级别运行时:
docker
containerd
rkt
podman
cri-o

containerd安装

containerd与docker相比,调用链更少,效率更高,如下图所示
在这里插入图片描述

当系统启动containerd服务时,会生成一个接口文件(unix:///var/run/containerd/containerd.sock)供各客户端连接

如使用docker时,docker客户端连接到docker服务器端,docker服务器端连接到containerd服务端,最后调用runc管理容器

containerd服务的其他一些客户端:
在这里插入图片描述
其中,nerdctl客户端的命令与docker相似

(1)安装containerd及cri工具

#配置yum源
rm -rf /etc/yum.repos.d/* ; wget ftp://ftp.rhce.cc/k8s/* -P /etc/yum.repos.d/
#安装containerd及cri工具
yum install containerd.io cri-tools -y

(2)启动containerd服务,并设为开机自启动

systemctl enable containerd --now

(3)containerd配置国内镜像仓库加速器
containerd的配置文件为:/etc/containerd/config.toml
初始配置文件中的配置项比较少,因此我们手动重新生成一个默认配置文件去覆盖

containerd config default > /etc/containerd/config.toml

配置阿里云镜像地址

#打开配置文件
vim /etc/containerd/config.toml

#1.打开后输入"/mirrors"搜索
#找到[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
#在下面加上:
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
	endpoint = ["https://tcvfiu1v.mirror.aliyuncs.com"]
#endpoint后面即加速器地址,可以在阿里云容器镜像服务中查看自己的加速器地址

#2.将[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]下的SystemdCgroup改为true,并将其他的配置项删除
SystemdCgroup = false 改为 SystemdCgroup = true

#3.搜索”sandbox“,将sandbox_image后面的值改为
"registry.aliyuncs.com/google_containers/pause:3.7"

#4.重启服务
systemctl restart containerd

可以查看containerd当前已生效配置,检查一下

containerd config dump

nerdctl安装

安装nerdctl客户端(替代docker),kubelet直接访问containerd服务,这里装上这个客户端只是为了我们自己管理镜像、容器更方便

(1)下载nerdctl并解压到/usr/bin/下

wget https://github.com/containerd/nerdctl/releases/download/v0.20.0/nerdctl-0.20.0-linux-amd64.tar.gz

tar zxf nerdctl-0.20.0-linux-amd64.tar.gz -C /usr/bin/

(2)授予可执行权限

chmod +x /usr/bin/nerdctl

(3)下载并安装网络插件,用于工具的通信

wget https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz

mkdir -p /opt/cni/bin/
tar zxf cni-plugins-linux-amd64-v1.1.1.tgz -C /opt/cni/bin/

(4)设置nerdctl子命令可以使用tab键

#1.编辑/etc/profile文件
vim /etc/profile
#2.在注释 “# /etc/profile” 下增加下面这条配置,保存退出
source <(nerdctl completion bash)
#3.使设置生效
source /etc/profile

(5)生成一个nerdctl的配置文件,设置连接的接口为“unix:///var/run/contianerd/containerd.sock”

mkdir /etc/nerdctl/
cat > /etc/nerdctl/nerdctl.toml <<EOF
debug             = false
debug_full        = false
address           = "unix:///var/run/containerd/containerd.sock"
namespace         = "default"
#snapshotter      = "stargz"
cgroup_manager    = "systemd"
#hosts_dir        = ["/etc/containerd/certs.d", "/etc/nerdctl/certs.d"]
insecure_registry = true
EOF

(6)给nerdctl配置加速器(前面配置的阿里云加速器是在containerd配置文件中,在nerdctl中不会生效)

#1.创建cert.d目录
mkdir /etc/containerd/certs.d

#2.进入目录
cd /etc/containerd/certs.d

#3.根据想要加速的镜像仓库,创建相应目录
#如,想要加速docker.io这个镜像仓库,则在certs.d目录下创建docker.io目录
mkdir docker.io

#4.进入/etc/containerd/certs.d/docker.io/目录下,生成hosts.toml配置文件
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<EOF
# server = "https://docker.io"
 
[host."https://tcvfiu1v.mirror.aliyuncs.com"]
  capabilities = ["pull", "resolve"]
  override_path = true
EOF

使用nerdctl管理镜像、容器

同docker类似,如使用 nerdctl images 可以查看所有镜像,使用 nerdctl ps 可以查看当前所有正在运行的容器
与docker不同的是,创建的容器,开机的时候并不会自动启动

loginctl show-user root | grep Linger
#输出:Linger=no,表示root创建的容器开机都不会自动启动

#设置root用户创建的容器开机自启动
loginctl enable-linger root

容器里运行的进程是什么?
(1)我们可以手动指定,容器里运行什么
(2)若没有指定,则默认运行镜像里规定的进程,使用“nerdctl history”查看镜像结构,CMD里指定的就是,容器里要运行的是什么

#查看镜像结构、构建过程
nerdctl history [镜像名]
#显示完整内容
nerdctl history [镜像名] --no-trunc

镜像管理

镜像的命名规则:主机名:端口/分类/镜像名:tag
例如:nginx的完整名字为:docker.io/library/nginx:latest

主机名不写则默认为:docker.io
分类不写则默认为:library
tag不写则默认为:latest

镜像重命名

nerdctl tag [原镜像名] [新名字]

将镜像保存为本地文件

nerdctl save [镜像名] > filename.tar

从本地导入镜像

nerdctl load -i filename.tar

删除镜像

nerdctl rmi [镜像名]

扩展:不同的containerd客户端工具pull下来的镜像的命名空间(namespace)不同,都有自己默认的命名空间,因此若使用crictl工具pull下来的镜像,在nerdctl images时是看不到的,若想使得这个镜像可以在nerdctl工具下管理,可以使用CONTAINERD_NAMESPACE=[命名空间]来临时修改nerdctl工具的命名空间为crictl工具的命名空间,创建好容器后再修改回去即可
打开nerdctl的配置文件cat /etc/nerdctl/nerdctl.toml可以看到命名空间属性 namespace=“default”
也可以通过echo $CONTAINERD_NAMESPACE查看当前命名空间

容器管理

#查看所有正在运行的容器
nerdctl ps
#查看所有运行和停止的容器
nerdctl ps -a

容器的生命周期
一个容器里必须要有一个运行的进程,不然容器就没有存在的意义了,即容器存活的时间由容器里进程的运行时间决定,容器里的进程还在运行,容器的状态就为(Up),进程运行完了,容器也就不再存活了(Exited)

创建一个容器

nerdctl run [镜像名]

#参数:
--name=[容器名]#创建时指定容器名
-d#不进入容器,后台运行
-it#创建后即进入容器终端 i(交互) t(终端)
-p#指定端口,冒号左边为宿主机端口,右边为容器端口,如“-p 3306”表示指定了该进程在容器中的端口,宿主机端口随机生成,“-p 8000:3306”表示该容器的进程在宿主机中访问的端口为8000,容器的端口为3306
--restart=always#容器运行结束后会一直重启
--rm#容器运行结束后即删除,不能和restart一起使用
-e#创建时指定变量,如创建mysql容器时,可以指定root用户名密码、创建一个数据库“-e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=test”
--privileged=true#以特权来运行
--network [网络名]#指定连接到哪个网络

#例
nerdcrl run --name=abc --restart=always -p 80:80 nginx

查看容器里的日志

nerdctl logs [容器id/容器名]

#实时监控日志,日志一有更新,就会继续输出
nerdctl logs -f [容器id/容器名]

查看容器的端口映射

nerdctl port [容器id/容器名]

查看容器内属性

nerdctl container inspect [容器id/容器名]
#查看容器属性时,container可忽略不写

nerdctl中,查看属性的通用语法

#查看容器内属性,容器时,类型可忽略,但其他类型时不能忽略
nerdctl container inspect [容器id/容器名]  /  nerdctl inspect [容器id/容器名]

容器内执行某个命令

nerdctl exec -it [容器名/id] [命令]
#例
nerdctl exec -it nginx ls
#进入容器内的命令行工具bash
nerdctl exec -it nginx bash

退出容器内的bash命令行工具

exit

查看容器内运行了哪些进程

nerdctl top [容器名/id]

开启容器

nerdctl start xxx

关闭容器

nerdctl stop

重启容器

nerdctl restart xxx

删除容器

nerdctl rm [容器id/容器名]
nerdctl rm -f [容器id/容器名]

把容器导出为镜像文件到本地

nerdctl commit -a "作者信息" -m "提交信息" [容器id] [导出镜像名]

nerdctl中,查看属性的通用语法

nerdctl [类型] inspect [名字]

#查看容器内属性,容器时,类型可忽略,但其他类型时不能忽略
nerdctl container inspect [容器id/容器名]  /  nerdctl inspect [容器id/容器名]
#查看镜像内属性
nerdctl image inspect [镜像名/镜像id]
#查看网络属性
nerdctl network inspect [网络名]
#查看数据卷属性
nerdctl volume inspect [数据卷名]

数据卷

由于容器内的数据不是持久化的,随着容器的删除,数据也就没了,因此,若想要使得数据持久化,就可以使用数据卷

数据卷——在宿主机中开辟一块空间(目录)用作永久保存数据,并将容器内保存数据的目录与之映射,使得容器内数据可以永久保存在宿主机中

数据卷使用方法

#列出当前所有数据卷
nerdctl volume list

#创建数据卷
#第一种创建方式:创建容器时,指定数据卷
-v [映射到宿主机中的数据卷目录名]:[容器数据卷目录名]
#指定一个数据时,表示指定的是容器内数据卷,宿主机中则随机生成一个数据卷与之映射,如:
-v /data

#例:
#只指定容器数据卷,宿主机数据卷随机生成
nerdctl run -d --name=v1 -v /data hub.c.163.com/public/centos:6.7-tools
#同时指定宿主机数据卷与容器数据卷
nerdctl run -d --name=v2 -v /vtest:/data hub.c.163.com/public/centos:6.7-tools

#第二种创建方式:
#先在宿主机中指定数据名称创建好数据卷
#这里创建的数据卷不再是目录名了,而是自定义一个数据卷名称(可以通过nerdctl volume list查看该名称数据在宿主机中的位置)
#然后创建容器时指定宿主机数据卷名称(不再是目录了)
nerdctl volume create [数据卷名称]
nerdctl run -d --name=v3 -v [数据卷名称]:/data hub.c.163.com/public/centos:6.7-tools

使用第二种创建方式会产生一个问题:
若忘记了容器里有一个数据卷/data挂载到了宿主机中的一个数据卷,导致自始至终都没有利用这部分空间

实例–使用第一种创建方式:
创建一个镜像名为hub.c.163.com/public/centos:6.7-tools的容器,指定一个数据卷 /data

nerdctl run -d --name=v1 -v /data hub.c.163.com/public/centos:6.7-tools

创建好后查看该容器属性

nerdctl inspect v1

就会看到Mounts这一项属性中,Destination表示为容器内数据卷,Source表示映射宿主机中的数据卷

		...
		"Name": "v1",
        "RestartCount": 0,
        "Driver": "overlayfs",
        "Platform": "linux",
        "AppArmorProfile": "",
        "Mounts": [
            {
                "Type": "volume",
                "Name": "557d34b658e792ddea648c4ceda7d4814f5b863414bf735cebedb6fe4e01110e",
                "Source": "/var/lib/nerdctl/1935db59/volumes/default/557d34b658e792ddea648c4ceda7d4814f5b863414bf735cebedb6fe4e01110e/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
		...

此时,进入容器v1的bash工具,并创建aaa.txt

#1
nerdctl exec -it v1 bash
#2
mkdir /data/aaa.txt
#3
exit

进入宿主机数据卷目录下,可以看到aaa.txt也存在了

#1
cd /var/lib/nerdctl/1935db59/volumes/default/557d34b658e792ddea648c4ceda7d4814f5b863414bf735cebedb6fe4e01110e/_data
#2
ls

但此时若删除容器v1,用刚刚通用的方式重新创建容器(只指定一个数据卷/data),会发现容器里的数据卷目录下(/data)并没有aaa.txt文件,这是因为只指定一个数据卷的时候,对应宿主机的数据卷是随机生成的,因此并不是映射到之前的宿主机数据卷
所以我们通过第二种方式创建数据卷,同时指定容器数据卷与宿主机数据卷
1.首先在宿主机中创建数据卷 /vtest(与docker不同,docker中若该数据卷不存在会自动创建,但nerdctl不会,所以先要创建好数据卷)

mkdir /vtest

2.创建容器时指定宿主机数据卷(/vtest)和容器内数据卷(/data)

nerdctl run -d --name=v2 -v /vtest:/data hub.c.163.com/public/centos:6.7-tools

容器、宿主机数据拷贝

#将容器里的数据拷贝到宿主机中
nerdctl cp [容器名]:[容器文件目录名] [宿主机目录名]
#将宿主机中数据拷贝到容器里
nerdctl cp [宿主机文件目录名] [容器名]:[容器目录名]

nerdctl网络管理

宿主机中,每一个容器都有自己的网络空间,宿主机也有自己的网络空间,对于宿主机中的多个容器,假设容器a中主要的进程端口为80,容器b中主要的进程的端口也可以为80,不会产生端口冲突,是因为每个容器本质上就是在宿主机中的各个虚拟机,它们虽然会占用宿主机的cpu、内存,但不会占用宿主机的网络空间,即每个容器都有各种的虚拟网络(不同的网段)
若想从外部访问宿主机来访问各个容器中的进程,则需要将各个容器的进程端口映射到宿主机的某一个端口上,这时就要注意端口冲突(因为都在同一个宿主机的网络空间),各个容器的虚拟网络通过NAT连接到宿主机的网络与外界通信
在这里插入图片描述
也可以让容器直接使用宿主机的网络空间而不需要端口映射(就好像直接在宿主机中开启了一个服务)
创建容器时指定使用宿主机网络

#创建容器时参数,指定某个网络环境
--netword [网络名]

#例:共享宿主机的网络空间
nerdctl run -d --name=web1 --restart=always --network host nginx
#例:指定网络为"none",成为“孤岛”,没有连接到任何网络,一般在测试时使用
nerdctl run -d --name=web2 --restart=always --network none nginx

查询容器的虚拟网络地址(IP地址)

#-i:忽略大小写
nerdctl inspect [容器名/id] | grep -i ipaddress

练习:搭建一个wordpress网站的容器,外部可以访问

在这里插入图片描述

1.拉取mysql、wordpress镜像
2.宿主机创建数据卷/blog、/db

mkdir /blog
mkdir /db

3.创建容器
需要的变量
mysql:
root用户密码:MYSQL_ROOT_PASSWORD
创建的数据库名:MYSQL_DATABASE
wordpress:
连接数据库地址:WORDPRESS_DB_HOST
登录哪个数据库:WORDPRESS_DB_NAME
登录数据库用户:WORDPRESS_DB_USER
登录数据库密码:WORDPRESS_DB_PASSWORD

#创建mysql容器
nerdctl run -d --name=db --restart=always -v /db:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=sa -e MYSQL_DATABASE=wordpressdb hub.c.163.com/library/mysql:latest
#查询mysql容器IP
nerdctl inspect db | grep -i ipaddress
#创建wordpress容器
nerdctl run -d --name=blog --restart=always -v /blog:/var/www/html -p 80:80 -e WORDPRESS_DB_HOST=10.4.0.14 -e WORDPRESS_DB_NAME=wordpressdb -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=sa hub.c.163.com/library/wordpress:latest

构建镜像

使用nerdctl工具进行构建镜像,不仅需要下载buildkit工具,而且没法基于本地镜像去构建,因此构建镜像包括搭建私有仓库,还是推荐使用docker来进行

安装docker

#配置yum源
rm -rf /etc/yum.repos.d/* ; wget ftp://ftp.rhce.cc/k8s/* -P /etc/yum.repos.d/
#安装docker
yum install docker-ce -y

开启docker服务、开机自启动

systemctl enable docker --now

查看docker启动脚本

systemctl status docker

可以看到 Loaded:loaded(/usr/lib/systemd/system/docker.service)
打开 /usr/lib/systemd/system/docker.service 文件
看到 ExecStart=/usr/bin/dockerd -H fd:// -containerd=/run/containerd/containerd.sock
可以知道docker客户端连接到的是dockerd服务端,dockerd服务也是要连接到containerd=/run/containerd/containerd.sock这个接口服务

docker的配置文件
docker的配置文件是 “/etc/docker/daemon.json”,这个时候可能没有这个文件,我们可以手动生成一份,并且配置阿里云加速器
我们登录阿里云镜像服务,直接将镜像加速器的配置复制过来
在这里插入图片描述

vim /etc/docker/daemon.json

#插入:
{
  "registry-mirrors": ["https://tcvfiu1v.mirror.aliyuncs.com"]
}

使用docker构建镜像

一般情况下,构建镜像并非是一个从零到有的过程,而是要基于一个已经存在的镜像(基础镜像、基镜像)基础上进行构建,通过基镜像,先生成一个临时容器,然后在这个临时容器里去进行一些修改(添加包、拷贝等),最后将临时容器导出为新镜像

即编写一个DockerFile脚本文件,其中定义基镜像、定义临时容器中要做的修改等,最后通过DokerFile脚本进行构建新镜像,构建时会先根据定义的基镜像创建一个临时容器,执行修改,构建好新镜像后会自动删除临时容器
在这里插入图片描述
DockerFile脚本相关指令

FROM [基镜像名]——指定基镜像,构建新镜像时会先通过这个创建一个临时容器
MAINTAINER [作者] #作者
RUN [命令] #临时容器中要执行的命令
ADD [文件名] [临时容器目录名] #拷贝宿主机文件到临时容器内,若是tar文件,带有自动解压功能
COPY [文件名] [临时容器目录名] #同ADD,但是没有自动解压功能 
ENV [变量名] [] #定义变量
VOLUME ["宿主机数据卷位置", "容器内数据卷位置"]["容器内数据卷位置"] #指定数据卷,规则就和docker run时一样
USER [用户名] #指定用户登录运行

EXPOSE [端口号] #通知使用者创建容器时需要映射宿主机哪个端口
CMD["nginx","-g","daemon off;"] #新镜像创建出来的容器,运行什么进程

将宿主机内容拷贝到临时容器:
使用ADD或者COPY都可以,只是COPY没有自动解压功能
注意,要拷贝的文件必须要与DockerFile文件在同一个目录下

构建镜像指令

#-t 指定新镜像名称
#-f 在指定的地址中寻找名为xxx的DockerFile文件,若文件名为”Dockerfile“,则可以忽略
docker build -t [新镜像名] [DockerFile文件的绝对地址,若就在当前目录,可以写“.”] -f [DockerFile文件名]

例:
DockerFile文件名为”Dockerfile“,就在当前目录下,构建名为centos:v1的镜像
docker build -t centos:v1 .

实验一:构建一个拥有ifconfig命令的镜像

使用hub.c.163.com/library/centos作为基镜像,在基镜像中添加ifconfig命令工具包(net-tools、iproute工具包中都有ifconfig命令)
第一步:拉取centos镜像

docker pull hub.c.163.com/library/centos

第二步:编辑DockerFile文件
新建名为"Dockerfile"的DockerFile

vim Dockerfile

插入:

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN yum install net-tools -y
RUN yum install iproute -y

CMD ["/bin/bash"]

第三步:构建镜像

docker build -t centos:v1 .

新镜像构建完毕,但是我们通过docker images发现,新镜像的SIZE很大, 我们只是想要添加ifconfig命令,但是却比原来的基镜像SIZE大出了很多
这是因为刚刚编写的DockerFile文件中,我们执行了两个RUN去安装工具包,每一个RUN都需要消耗一定的空间、数据去执行,执行第一个RUN的时候,将数据堆叠在新镜像的第一层layer,执行第二个RUN的时候,将数据堆叠在第二层,而这两个RUN都是去执行安装工具包的命令,因此产生了很多相同内容

第四步:优化
使用一个RUN命令去安装两个工具包,用一层layer实现两个包的安装,减少冗余

RUN yum install net-tools iproute-y 
#或者
RUN yum install net-tools && yum install iproute
#可以使用”\“换行,结束后不能再跟”\“
RUN yum install net-tools -y && \
    yum install iproute -y

修改后的DockerFile为:

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN yum install net-tools -y && \
    yum install iproute -y

CMD ["/bin/bash"]

同时,我们可以将自己配置了阿里云的yum源替换调基镜像中yum源

#1.进入/etc/yum.repos.d
cd /etc/yum.repos.d
#2.将自己配置了阿里云的yum源CentOS-Base.reop、epel.repo打包
tar zcf /root/repo.tar CentOS-Base.repo epel.repo
#3.编辑DockerFile
vim Dockerfile
#增加清理原有yum源命令
RUN rm -rf /etc/yum.repos.d/*
#将自己宿主机的yum源替换上去
ADD repo.tar /etc/yum.repos.d/

修改后的DockerFile为:

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN rm -rf /etc/yum.repos.d/*
ADD repo.tar /etc/yum.repos.d/
RUN yum install net-tools -y && \
    yum install iproute -y

CMD ["/bin/bash"]

最后,还可以进一步优化,清理yum缓存、临时数据

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN rm -rf /etc/yum.repos.d/*
ADD repo.tar /etc/yum.repos.d/
RUN yum install net-tools -y && \
    yum install iproute -y && \
    yum clean all && rm -rf /var/cache/yum/x86_64/*

CMD ["/bin/bash"]

这时再构建镜像后会发现SIZE小了很多

多阶段构建

通过基镜像生成一个临时容器,在临时容器里添加包,然后再建一个临时容器,直接从第一个临时容器中拷贝需要的文件,而不需要装任何包了

根据之前的例子,我们只需要在第一个临时容器中安装net-tools、iproute两个包,然后第二容器直接从第一个容器中拷贝ip命令、ifconfig命令即可
DockerFile内容如下:
COPY --from=0 表示从编号为0(即第一个)的临时容器中拷贝

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN rm -rf /etc/yum.repos.d/*
ADD repo.tar /etc/yum.repos.d/
RUN yum install net-tools -y && \
    yum install iproute -y

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
COPY --from=0 /sbin/ifconfig /sbin
COPY --from=0 /sbin/ip /sbin

CMD ["/bin/bash"]

通过这个方法构建的镜像SIZE是最小的

实验二:自定义一个nginx镜像

自定义一个nginx镜像,使用hub.c.163.com/library/centos作为基镜像
第一步:编辑一个index.html

vim index.html
#插入:
hello world

第二步:编辑DckerFile
1.结合实例一,清理yum源,并将配置了阿里云的yum源替换调原yum源
2.定义安装nginx的命令
3.将index.html拷贝到临时容器的nginx文件里
4.暴露端口为80
5.CMD指定运行nginx进程的命令

vim nginxDockerfile
#插入:
FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN rm -rf /etc/yum.repos.d/*
ADD repo.tar /etc/yum.repos.d/
RUN yum install nginx -y
COPY index.html /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

第三步:构建镜像

docker build -t ng:v1 . -f nginxDockerfile

创建容器进行访问测试

实验三:搭建一个可以ssh,也可以运行nginx的镜像

使用hub.c.163.com/library/centos作为基镜像
ssh必需的包为两个:openssh-clients、openssh-server
编辑DockerFile
1.指定安装openssh-clients、openssh-server包的命令
2.指定生成ssh时必需的key
3.指定ssh时root用户密码
4.将sshd_config中de “UseDNS” 改为 “cUseDNS no”

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN yum install openssh-clients openssh-server -y && \
    ssh-keygen -t sha -f /etc/ssh/ssh_host_rsa_key && \
    ssh_keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
    ssh_keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key && \
    echo "sa" | password --stdin root && \
    sed -i '/UseDNS/cUseDNS no' /etc/ssh/sshd_config

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"] 

此时,可以ssh的容器镜像完成了
但是既要可以运行nginx,无非就是再安装个nginx的包,但是CMD怎么指定既运行ssh又运行nginx呢?
这时候就可以写一个运行脚本run.sh:vim run.sh
插入以下内容:(-D后台运行)
#!/bin/bash
nginx &
ssh -D

修改DockerFile文件:
1.添加nginx包
2.将run.sh拷贝至/bin下
3.指定赋予run.sh可执行权限的命令
4.公布端口80
5.CMD指定运行/bin/run.sh脚本

FROM hub.c.163.com/library/centos
MAINTAINER ctyFL
RUN yum install openssh-clients openssh-server nginx -y && \
    ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
    ssh_keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
    ssh_keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key && \
    echo "sa" | password --stdin root && \
    sed -i '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
ADD run.sh /bin
RUN chmod +x /bin/run.sh

EXPOSE 22 80
CMD ["/bin/run.sh"] 

使用harbor搭建私有仓库

搭建自己的私有仓库,就可以将自己的镜像push到私有仓库、从私有仓库pull镜像
我们使用刚刚安装了docker的这台机器作为仓库
在这里插入图片描述
使用harbor搭建私有仓库
harbor是一个通过web界面管理仓库的镜像,安装harbor需要compose,compose是一种容器编排工具
一:安装docker-compose工具
docker-compose是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务

yum install docker-compose -y

查看docker-compose版本

docker-compose -v

二:配置不使用证书
我们对私有仓库进行pull、push的时候,https协议下需要一个证书,比较麻烦,我们也可以通过配置使得docker通过http访问,从而可以不使用证书

方式1:
通过systemctl status docker找到docker的启动脚本,既:loaded (/usr/lib/systemd/system/docker.service)
编辑docker启动脚本

vim /usr/lib/systemd/system/docker.service

ExecReload=/usr/bin/dockerd 后 增加 --insecure-registry 192.168.26.12(宿主机IP地址)

ExecStart=/usr/bin/dockerd --insecure-registry 192.168.26.12 -H fd:// --containerd=/run/containerd/containerd.sock

方式2:
也可以在docker的配置文件 /etc/docker/daemon.json 中配置

}
	"registry-mirrors": ["https://tcvfiu1v.mirror.aliyuncs.com"],
	"insecure-registries": ["192.168.26.12"]
}

以上两种方式只能选择一种,否则会报错
修改后重新加载配置文件,重启docker

systemctl daemon-reload ; systemctl restart docker

若docker启动报错:Job for docker. service failed because the control process exited with error code,可以尝试修改daemon.json文件名为daemon.conf

mv daemon.json daemon.conf

三:下载 harbor-offline-installer 离线安装包并安装
1.在/root下操作,将harbor离线安装包传输到/root下,进行解压

tar zxf harbor-offline-installer-v2.3.5.tgz

2.解压好后,进入harbor目录并导入离线镜像

cd /root/harbor
ls
docker load -i harbor.v2.3.5.tar.gz

3.harbor目录下也提供了harbor的配置文件的模板 barbor.yml.tmpl
我们拷贝出一个副本,进行编辑

cp harbor.yml.tmpl harbor.yml
vim harbor.yml

将配置项hostname配置为自己的IP地址
将https相关配置删除
harbor_admin_password项可以配置登录密码
4.使配置生效

./prepare

5.安装

./install.sh

四:浏览器访问ip使用harbor,使用用户名admin登录
在这里插入图片描述
点击【新建项目】创建名为cka的公开项目
公开\不公开:公开既不需要提前登录就可以pull,和push无关,push必须要登录才可以
在这里插入图片描述

测试push镜像到私有仓库
根据镜像命名规则,例如centos镜像的全名为docker.io/library/centos:latest,因此,若我们在推送镜像时若不指定,则默认推送到了docker.io的library库中,所以,我们需要重新tag一下镜像,才可以push到我们的私有仓库
例如将centos:v1镜像推送到主机为“192.168.26.12”的私有仓库的cka库中

#1.修改标记
docker tag centos:v1 192.168.26.12/cka/centos:v1
#2.宿主机登录harbor
docker login 192.168.26.12 -u admin -p [harbor.yml中配置的密码]
#3.推送
docker push 192.168.26.12/cka/centos:v1

在这里插入图片描述
打开harbor管理页面可以看到镜像
在这里插入图片描述
使用nerdctl工具拉取私有仓库的镜像时,nerdctl默认使用的是https连接,因此这里会报错,编辑 /etc/nerdctl/nerdctl.toml,将 insecure_registry = true (允许使用不安全连接)

vim /etc/nerdctl/nerdctl.toml

若想使用crictl工具进行http拉取,同样需要修改配置,而它的配置文件也就是containerd的配置文件 /etc/containerd/config.toml
编辑/et/containerd/config.toml,/搜索mirrors
在[plugins.“io.containerd.grpc.v1.cri”.registry.mirrors]下增加一个代理

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.26.12"]
	endpoint = ["http://192.168.26.12"]

资源限制

由于容器会直接占用宿主机的cpu、内存,假设宿主机的内存为4G,若不做资源限制,则容器在需要的时候会毫不客气地去使用这4个G的内存,因此需要进行资源限制,来对资源进行分配

这里要利用Linux里本身的一个特性——cgroup
cgroup(Linux Control Groups)主要作用是限制、记录和隔离进程组使用的物理资源(cpu、memory、IO等)
cgroup接口有两个封装:cgroupfs、Systemd,k8s中推荐使用Systemd

对容器使用内存作限制:

创建容器时通过-m指定

#-m [能使用的最大内存] (-m底层就是cgroup实现的)
#例:限制512M的内存
nerctl run -it --rm --name=c1 -m 512M hub.c.163.com/library/centos
``  `

对容器占用作cpu限制
假设宿主机中有6个cpu,若我们进行规划,使得容器a运行时占用cpu1、cpu2的资源,容器b运行的时候占用cpu2、cpu3的资源,容器c运行的时候占用cpu3、cpu4的资源,这样即使是某个容器的cpu消耗率达到了100%,也不会影响其他的cpu

```bash
#查看进程分别运行在哪个cpu上面
ps mo pid,psr $(pgrep cat)

创建时通过 --cpuset-cpus=“cpu编号” 指定容器的进程在哪个cpu上运行(只会占用哪几个cpu资源)

# --cpuset-cpus=[cpu编号]
#例:容器只会占用0号cpu的资源
nerdctl run -it --rm --name=c1 --cpuset-cpus=0 hub.c.163.com/library/centos
#例:容器只会占用0号和1号的cpu的资源
nerdctl run -it --rm --name=c1 --cpuset-cpus=0,1 hub.c.163.com/library/centos
#例:容器只会占用0号和1号的cpu的资源
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戴陵FL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值