Skip to content

Docker概述

Docker是什么?

Docker是容器的称呼,常见的容器除了docker外,还有containerd、podman、CRl-O等,开 发写好的代码或者需要部署的服务,都打包到一个镜像里,然后基于docker或者containerd或者 podman运行镜像,就可以提供相应的服务了。

Docker基本概念

镜像(Image):一个可运行的二进制文件,包含了运行应用程序所需的所有依赖项和配置信息。可 以通过编写Dockerfile文件来创建镜像。 容器(Container):一个运行中的镜像实例,包含了应用程序和其依赖项。可以使用DockerCLI 或DockerCompose来创建和管理容器。 仓库(Registry):一个存储和分发镜像的地方。DockerHub是Docker官方提供的仓库,可以 在其中找到许多常用的镜像,也可以在其中上传和分享自己的镜像。

官网 www.docker.com

Docker的github地址: https://github.com/moby/moby

官网国内替代 https://hub-stage.docker.com/

dockerhub

Dockerhub:Dockerhub是存放docker镜像的一个官方网站,dockerhub上提供了很多常用的 镜像供用户下载,如ubuntu、centos、debian等操作系统镜像。通过dockerhub用户也可以存 自己的docker镜像,但是需要需要注册一个账在网站上创建一个docker仓库。

Docker特性

优点: 1、高度可移植性:Docker可以在任何支持Docker的平台上运行,而且容器可以在不同的环境 中快速、简单地部署和移植。 2、轻量级和高效:Docker容器非常轻量级,启动和停止速度快,并且对系统资源的占用非常少。 3、隔离性好:Docker使用Namespace和croups技术实现容器的隔离,每个容器都拥有自 已的进程、网络、文件系统和其他资源,保证了容器之间的隔离性和安全性。 4、易于管理和扩展:Docker提供了一系列的命令行工具和图形化界面,可以方便地管理和监控容 器。同时,Docker还支持容器编排工具,如Kubernetes,可以轻松地管理和扩展容器集群。 5、生态系统丰富:Docker拥有庞大的社区和生态系统,提供了丰富的容器镜像和插件,可以方便 地构建、部署和运行应用程序。

环境准备

  • 安装 rockyLinux8.8

  • 便携包

yum install -y lrzsz vim vim-enhanced
  • 开启网卡
nmcli c up ens160
  • 配置静态ip
vi /etc/sysconfig/network-scripts/ifcfg-ens160

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=192.168.59.63
NETMASK=255.255.255.0
GATEWAY=192.168.59.2
DNS1=192.168.59.2
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=eui64
NAME=ens160
DEVICE=ens160
ONBOOT=YES

备注:BOOTPROTO=static,表示静态配置ip ONBOOT=YES,表示启动机器会自动启动网卡 可以将机器环境装好后后面统一配置

修改后需要重启

nmcli connection reload
# 可能需要重启机器
  • 设置主机名
hostnamectl set-hostname master
  • 停防火墙
vim /etc/selinux/config

SELINUX=disabled

重启

reboot -f

查看是否关闭

[root@master ~]# getenforce
Disabled

关闭防火墙

systemctl stop firewalld && systemctl disable firewalld

时间同步

3、配置时间同步 基于chrony配置服务器时间跟网络时间同步梅 以前我们使用ntpdate来同步系统时间,但是,htpdate是立即同步,在生产环境下,系统时间大 范围的跳动,是非常严重的事件。 chrony是网络时间协议(NTP)的另一种实现,与网络时间协议后台程序(ntpd)不同,它可以更快地且 更准确地同步系统时钟。 两个主要程序:chronyd和chronyc chronyd:后台运行的守护进程,用于调整内核中运行的系统时钟和时钟服务器同步。它确定计算机 增减时间的比率,并对此进行补偿< chronyc:命令行用户工具,用于监控性能并进行多样化的配置。它在chronyd实例控制的计算机 上工作< 服务 unit 文件:/usr/lib/systemd/system/chronyd.service 监听端口: 323/udp,123/udp 配置文件:/etc/chrony.conf K ntpdate和chrony是服务器时间同步的主要工具,两者的主要区别就是: 1)执行ntpdate 后,时间是立即修整,中间会出现时间断档; 2)而执行chrony后,时间也会修正,但是是缓慢将时间追回,并不会断档。个

  • 安装
yum -y install chrony
systemctl enable chronyd --now
  • 设置同步源
vim /etc/chrony.conf 

# 添加到末尾
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
server ntp1.tencent.com iburst
server ntp2.tencent.com iburst
  • 重启
systemctl restart chronyd

修改内核参数

# 开启包转发功能
$ modprobe br_netfilter
# 修改内核参数
$ cat > /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
$ sysctl -p /etc/sysctl.d/docker.conf

备注,内核参数相关说明: 1、 net.bridge.bridge-nf-call-ip6tables = 1: 该参数启用了桥接网络设备(bridge)在IPv6包进行iptables规则过滤时,通过netfilter模块将 数据包传递给iptables处理。这个参数通常用于虚拟化环境,如Docker等,以支持IPv6流量的转发 和安全过滤。如果不启用该参数,则在桥接设备上的IPv6流量无法进行iptables规则过滤。 2、 net.bridge.bridge-nf-call-iptables = 1: 该参数启用了桥接网络设备(bridge)在IPv4包进行iptables规则过滤时,通过netfilter模块将 数据包传递给iptables处理。这个参数通常用于虚拟化环境,如Docker等,以支持IPv4流量的转发 和安全过滤。如果不启用该参数,则在桥接设备上的IPv4流量无法进行iptables规则过滤。 3、 net.ipv4.ip_forward = 1: 该参数启用了Linux操作系统的IP转发功能,允许路由器将接收到的数据包转发到其他网络。这个 参数通常用于构建网络拓扑,如在一个局域网内部部署多台主机并让它们可以访问外部互联网。如果不启 用该参数,则Linux系统默认不会转发IP数据包。

在线安装docker

$ yum install -y yum-utils
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 对应位置
$ ls /etc/yum.repos.d/docker-ce.repo 
/etc/yum.repos.d/docker-ce.repo
$ yum install docker-ce wget net-tools nfs-utils gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo libaio-devel wget ncurses-devel autoconf automake zlib-devel epel-release openssh-server
socatt ipvsadm conntrack -y --allowerasing
$ systemctl start docker && systemctl enable docker
$ docker version

hub-stage.docker.com 国内替代

配置docker镜像源

$ tee /etc/docker/daemon.json << 'EOF'
{
    "registry-mirrors":["https://rsbud4vc.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"]
}
EOF

最新

sudo vim /etc/docker/daemon.json <<EOF
{
    "registry-mirrors": ["https://docker.xuanyuan.me"]
}
EOF

重启docker服务使配置生效 (02_01:45:25)

docker 镜像操作

查询

docker search <镜像名>

加载镜像

# 在线拉取
docker pull nginx
# 离线加载
docker load -i nginx.tar

导出镜像

docker save -o nginx.tar nginx

镜像位置

$ cd /var/lib/docker/image/overlay2/imagedb/content/sha256/
$ ls
66f8bdd3810c96dc5c28aec39583af731b34a2cd99471530f53c8794ed5b423e

删除镜像

$ docker rmi <镜像ID>
$ docker rmi <镜像名称:tag>

docker 容器操作

运行容器

$ docker run -d -p 80:80 nginx
$ docker run --name mynginx -d -p 80:80 nginx
$ docker rename mynginx myothernginx

启动和停止

$ docker start <容器ID>
$ docker stop <容器ID>

进入容器

$ docker exec -it <容器ID> bash

基于dockerfile构建镜像

demo

FROM rockylinux:8.8
LABEL maintainer="pod<pod@example.com>"
RUN sed -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' -i.bak /etc/yum.repos.d/*.repo
RUN yum install wget -y
RUN yum install nginx -y
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]

端口映射

  • 解释
# 暴露80端口
EXPOSE 80 
# 暴露 80-100
EXPOSE 80-100
# 暴露 80 81 82
EXPOSE 80 81 82
  • 运行解释
# 会找容器内的 80 端口
docker run -d -p 80
# 将主机81端口映射到容器内的80端口
docker run -d -p 81:80
# 主机随机端口映射到容器dockerfile EXPOSE端口
docker run -d -P --name html1 hello/nginx:v1

命令

  • demo
FROM alpine
MAINTAINER gopher
RUN echo hello1 > test1.txt
RUN echo hello2 > test2.txt
# 命令
ENTRYPOINT ["echo"]
# 参数 多个CMD最后一个生效
CMD ["default value"]
  • 运行解释
$ docker run --rm myimage 
default value
# 替换参数
$ docker run --rm myimage hello world
hello world
# 替换命令
$ docker run --rm --entrypoint="cat" myimage test1.txt
hello1

cpu配额

docker run --rm --cpu-shares 512 nginx

假设你的主机只有一个CPU核心,而且两个Docker容器需要运行。如果为这两个容器分配不同 的CPU份额值,将会有以下几种不同的情况: 1、容器A的CPU份额值是512,容器B的CPU份额值是256。这意味着容器A将获得主 机CPU时间片的2/3,而容器B将获得1/3。这种情况下,容器A可能会运行得更快,并且可能会 比容器B更快地响应请求,因为它获得了更多的CPU时间片。个 2、容器A的CPU份额值是256,容器B的CPU份额值是512。这意味着容器A将获得主 机CPU时间片的1/3,而容器B将获得2/3。这种情况下,容器B可能会运行得更快,并且可能会 比容器A更快地响应请求,因为它获得了更多的CPU时间片。 容器A和容器B的CPU份额值都是512。这意味着它们将平均获得主机CPU时间片的一半。 在这种情况下,两个容器的性能可能会非常相似,因为它们获得的CPU时间片相等。

限制cpu和内存节点

参数:: --cpuset-cpus 和--cpuset-mems

1、--cpuset-cpus:它用于指定容器可以使用的CPU节点列表,以逗号分隔。例如,如果将其设 置为--cpuset-cpus=0,1,则表示该容器可以在CPU 节点0 和 1 上运行。这有助于将容器限制在特 定的CPU上运行,以获得更好的性能或避免与其他容器共享CPU。 2、--cpuset-mems:它用于指定容器可以使用的内存节点列表,以逗号分隔。例如,如果将其设置 为--cpuset-mems=0,1,则表示该容器可以在内存节点0和1上运行。这有助于将容器限制在特定 的内存节点上运行,以控制容器对系统内存的使用情况。

  • 查看是否多内存系统
$ lshw -class memory | grep memory
*-memory 

多个 *-memory 则为多内存,否则单内存

  • cpu demo

例1:虚拟机一共有4个核心,创建的容器只能用0、1、2这三个核心。

$ docker run -it --name cpu1 --cpuset-cpus 0-2 rockylinux:8.8 bash
$ cat /sys/fs/cgroup/cpuset/cpuset.cpus 

cpu限制和cpu参数混合使用

cpu核心和共享权重

-cpuset-cpus-cpu-shares 一起使用

运行两个容器实例:

指定docker10只能在cpu0和cpu1上运行,而且docker10的使用cpu的份额512

指定docker20只能在cpu0和cpu1上运行,而且docker10的使用cpu的份额1024

$ docker run -itd --name docker10 --cpuset-cpus-0,1 --cpu-shares 512 rockylinux:8.8 /bin/bash
$ docker run -itd --name docker20 --cpuset-cpus-0,1 --cpu-shares 1024 rockylinux:8.8 /bin/bash

上面的命令中,--cpuset-cpus·指定了容器使用的·CPU,--cpu-shares·指定了容器·CPU·分配的权重。docker10使用CPU·0,1,权重为512,docker20使用·CPU·0,1,权重为1024。 这样的话,当·CPU·资源不足时,Docker·将按照权重分配·CPU·时间片,第二个容器获得的·CPU 时间片应该比第一个容器多一些。响应速度也更快。

  • docker10 设置
# 拷贝stress到容器中
docker cp /usr/bin/stress docker10:/usr/bin/
docker exec -it docker10 bash
stress -c 2 -v -t 10m
  • docker20 设置
# 拷贝stress到容器中
docker cp /usr/bin/stress docker10:/usr/bin/
docker exec -it docker10 bash
stress -c 2 -v -t 10m
  • 在主机top 1可观测到正确结果

alt text

时间配额

docker提供了 -cpu-period--cpu-quota两个参数控制容器可以分配到的CPU时间。单位us - --cpu-period 参数定义CPU周期长度,单位为微秒。它指定了CPU资源在多长时间内 可以被容器使用。默认值为0.1秒,例如,设置--cpu-period=100000意味着容器可以每 100毫秒使用一次CPU。 - --cpu-quota 参数定义CPU资源使用的时间配额,单位为微秒。它指定了容器可以在每 个CPU周期内使用CPU时间的最大量。例如,设置--cpu-quota=50000意味着容器每100 毫秒可以最多使用50毫秒的CPU时间。

  • 这两个参数的具体使用场景如下: 1、CPU资源分配:当多个容器运行在同一台主机上时,--cpu-period 和--cpu-quota 参数可以用 于限制容器使用的CPU资源。这样可以确保每个容器都能够获得足够的CPU时间,并避免某个容器占用过多的CPU资源 2、应用程序性能测试:--cpu-period和--cpu-quota参数可以用于测试应用程序在不同CPU限制下的性能。 例如,可以通过逐步减少--cpu-quota 参数的值,测试应用程序在不同CPU限制下的响应时间和处理能力。

  • 示例:每1s钟用0.2s cpu

  • 准备脚本calculate_sum.py

total = 0
for i in range(1,1000000000000000001):
    total += i
    print(f"The sum of all integers from 1 to 1000000000000000001 is: {total}")
  1. dockerfile
FROM python:3.9-slim-buster
COPY calculate_sum.py /
CMD["python", "/calculate_sum.py"]
  1. 编译运行
$ docker build -t my-image .
$ docker run --name cal -it --cpuset-cpus 0 --cpu-period 1000000 --cpu-quota 200000 my-image
  1. 查看结果
$ docker stats

alt text

可以看到cpu占用基本为百分之20

备注:

Docker运行容器如果制定了--cpu-period或者--cpuset-cpus怎么解除限制?

docker update --cpuset-cpus=0-3 my-container

docker容器实例运行结束后自动释放资源

eg: 10s 后自动删除

docker run -it -rm --name mk rockylinux:8.8 sleep 10

docker 限制内存

# 限制内存为 256m
$ docker run --name m1 -itd -m 256m rockylinux:8.8
# 查看生效(单位字节)
$ cat /sys/fs/cgroup/memory/memory.limit_in_bytes
268435456 

压测

docker cp /usr/bin/stress m1:/usr/bin/stress-ng

# 进入将内存压满
$ stress-ng --vm-bytes 1024M --vm-keep -m 100

外部查看结果

$ docker stats
alt text

docker运行容器限制磁盘1O

为什么要限制

对磁盘 IO·做限制是为了防止过多的·1/0·请求导致磁盘性能下降,甚至是岩机。当多个进程或容器 同时访问磁盘时,如果没有限制磁盘 IO,可能会导致·1/0·瓶颈,使得磁盘无法承受过多的请求,从而 降低系统的整体性能。 通过限制容器的磁盘 IO,可以保证每个容器在一定程度上独享磁盘·10?资源,避免容器之间的竞争 和影响。同时,限制磁盘·10?也可以避免恶意容器滥用系统资源,对系统的稳定性和安全性造成影响。 举个例子,如果一个应用程序或容器在短时间内对磁盘资源进行了大量的读写操作,那么可能会导致 其他应用程序或容器无法及时访问磁盘资源,进而影响系统整体的性能和稳定性。

docker中限制

--device-write-bps·value··#限制容器向指定设备写入的字节数/秒。个 --device-read-bps·value·#限制容器从指定设备读取的字节数/秒。金 这两个选项都需要指定限制的字节数/秒。可以使用以下格式指定: 以字节为单位的值,例如·--device-read-bps=/dev/sda:1024·表示限制从·/dev/sda 设备读取的速率为每秒·1024·字节。 可选的单位有·B(字节)、K(干字节)、M(兆字节)和·G(吉字节),例如·--device-read-bps=/dev/sda:1M·表示限制从·/dev/sda·设备读取的速率为每秒1兆字节。

  • 例1:限制容器实例对硬盘的最高写入速度设定为·1MB/s。

假设我们要创建一个名为my-app的Docker容器,并将其对硬盘的最高写入速度限制为1MB/s。 可以通过在容器运行时使用--device参数挂载磁盘设备,并通过--device-write-bps 参数限制写入速度 实现。具体操作步骤如下:

查看宿主机使用的分区 alt text

$ mkdir my-data
# 映射分区
$ docker run -it --device /dev/nvme0n1:/dev/nvme0n1 --device-write-bps /dev/nvme0n1:1mb -v "$(pwd)/my-data:/data" --name my-app rockylinux:8.8
# 测试 oflag 后的参数表示不走缓存 我测试未生效,不知道为什么,不知是否为 nvme 硬盘原因
$ time dd if=/dev/nvme0n1 of=/data/test.out bs=1M count=50 oflag=direct,nonblock
  • 例 2:限制容器实例对硬盘的最高读取速度设定为·1MB/s。

首先,在宿主机上创建一个文件用于挂载到Docker容器中进行测试。例如,可以在宿主机上创建一 个大小为500M的文件:

# 宿主机生成
$ time dd if=/dev/nvme0n1 of=my-data/test.out bs=1M count=500 oflag=direct,nonblock
$ docker run -it --name test --mount type=bind,source=$(pwd)/my-data/test.out,target=/testfile rockylinux:8.8
# 进入 普通读
$ dd if=/testfile of=/dev/null bs=1M count=500 iflag=direct
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 0.573419 s, 914 MB/s
# 测试限制
$ docker run -it --name test1 --mount type=bind,source=$(pwd)/my-data/test.out,target=/testfile --device-read-bps /dev/nvme0n1:1mb rockylinux:8.8
# 测试, 同理,本机还是不行
$ dd if=/testfile of=/dev/null bs=1M count=500 iflag=direct

Comments