Docker 使用详解

本贴最后更新于 194 天前,其中的信息可能已经沧海桑田

虚拟机

使用的是 centos7,用户名 docker 密码 123456

网络使用的是桥接模式

配置虚拟机

查看网络

image

网卡名称是 ens33

image

重启网格

systemctl restart network

修改主机名

hostnamectl set-hostname zzj && bash

关闭防火墙

systemctl stop firewalld && systemctl disable firewalld

安装 iptables 防火墙

yum install iptables-services -y

禁用 iptables

service iptables stop && service disable iptables

清空防火墙规则

iptables -F

关闭 selinux

vi /etc/selinux/config

image

设置为 disabled

修改成功之后重启虚拟机才会生效

重启之后使用下面命令查看是否生效

getenforce

image

disabled 表示 selinux 已经关闭

配置时间同步

虚拟机想要和网络时间和北京时间同步需要进行配置,安装用于时间同步的工具

yum install -y ntp ntpdate

和网络时间进行同步

ntpdate cn.pool.ntp.org

编写一个计划任务,专门用来时间同步

crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org // 表示没一小时和网络时间进行同步

重启 crond 服务使配置生效

systemctl restart crond

安装基础软件包

 yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack

docker 安装

安装 docker 需要的基础包

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

配置安装 docker 国内 yum 源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装 docker-ce

yum install docker-ce -y
docker version # 查看docker版本

启动 docker 和配置 docker 开机自启动

systemctl start docker && systemctl enable docker

查看 docker 是否启动

systemctl status docker

image

修改 docker 内核参数

内核参数修改:br_netfilter 模块用于将桥接流量转发至 iptables 链,br_netfilter 内核参数需要开启转发。

modprobe br_netfilter # 加载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

net.ipv4.ip_forward = 1

将 Linux 系统作为路由或者 VPN 服务就必须要开启 IP 转发功能。当 linux 主机有多个网卡时一个网卡收 到的信息是否能够传递给其他的网卡 ,如果设置成 1 的话 可以进行数据包转发,可以实现 VxLAN 等功 能。不开启会导致 docker 部署应用无法访问。

使配置生效

 sysctl -p /etc/sysctl.d/docker.conf

查看 br_netfilter 是否生效

lsmod | grep br_netfilter

image

br_netfilter 模块在虚拟机重启之后又会失效,我们需要编写开机自动加载模块脚本,下面是脚本

vim /etc/rc.sysinit
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done
vim /etc/sysconfig/modules/br_netfilter.modules
modprobe br_netfilter

给文件设置权限

chmod 755 /etc/sysconfig/modules/br_netfilter.modules

配置好后,可以重启虚拟机查看 br_netfilter 模块是否开启加载了

重启 docker

systemctl restart docker

配置 docker 的阿里云镜像加速器

image

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dqk40brb.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

docker 基本用法

镜像相关操作

搜索镜像

docker search centos

image

解释说明

  • NAME:镜像仓库源名称
  • DESCRIPTION:镜像描述
  • STARS: 类似 GIthub 中的 Start
  • OFFICIAL:是否是官方发布

下载镜像

docker pull centos

查看本地镜像

docker images

把镜像做成离线压缩包

docker save -o centos.tar.gz centos

解压离线镜像压缩包

docker load -i centos.tar.gz

删除镜像

docker rmi -f centos:latest

容器相关操作

以交互式方式启动并进入容器

docker run --name=hello -it centos /bin/bash

使用 exit 命令退出容器,但是以交互式方式进入容器并退出,容器不会继续运行

  • docekr run 运行并创建容器
  • --name 容器名称
  • -i 交互式
  • -t 分配伪终端
  • centos 运行容器需要的镜像
  • /bin/bash 说明你的 shell 类型为 bash、bash shell 是最常用的一种 shell

以守护进程方式启动容器

docker run --name=hello -td centos

以守护进程方式启动容器之前,需要先把以交互式启动方式创建的容器删除。

进入容器内部

dockee exec -it 容器ID /bin/bash

容器相关命令

查看正在运行的容器

docker ps -a

查看所有容器,包括运行和退出的容器

docker ps -a

停止容器

docker stop 容器ID

删除容器

docker rm -f 容器ID
  • -f 表示强制删除容器,正在运行的容器也可以直接删除,不加 -f 只能删除停止运行的容器

docker 部署 NGINX

docker run --name nginx -p 80 -itd centos

-p 把容器端口在物理机随机映射一个端口

这个命令是以 centos 镜像创建一个名为 nginx 的容器,我们还需要进入到这个容器内部安装 nginx

安装 Nginx 命令

rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
yum -y clean all   //清除所有文件
yum -y makecache   //建立缓存
yum install nginx -y
yum install vim-enhanced -y  # 安装文本编辑器

创建目录

mkdir /var/www/html -p
cd /var/www/html/ 

编写页面

vim index.html
<html>
 <head>
 <title>nginx in docker</title>
 </head>
 <body>
 <h1>hello,My Name is xianchao</h1>
 </body>
</html>

修改 Nginx 配置文件中的 root 路径如下:

vim /etc/nginx/nginx.conf 

image

启动 Nginx

/usr/sbin/nginx

查看 Nginx 映射到物理机上的端口

image

流量走向: 访问物理节点 ip:port(容器在物理节点映射的端口)--→ 容器 ip:port(容器里部署的服务的端口)-> 就可以访问到容器里部署的应用了

dockerfile-基础语法

dockerfile 语法详解

创建一个 dockerfile 文件,内容如下

FROM centos
MAINTAINER zzj
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
RUN yum -y clean all
RUN yum -y makecache
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;"]

创建 index.html

<html>
<head>
 <title>page added to dockerfile</title>
</head>
<body>
 <h1>i am in df_test </h1>
</body>
</html> 

基于 dockerfile 构建镜像

docker build -t nginx:v1 .

这个 . 表示在当前目录下找 dockerfile 文件,-f 可以指定 dockerfile 文件

dockerfile 文件中的指令解释:

  • FROM:基础镜像,定制的镜像都是基于 centos 的镜像,这里的 centos 就是定制需要的基础镜像,后续的操作都是基于 centos 镜像。

  • MAINTAINER:指定镜像的作者信息

  • RUN:指定在当前镜像构建的过程中要运行的命令,包含两种模式:

    • Shell

      • RUN yum -y makecache
    • exec

      • RUN [“/bin/bash”,”-c”,”echo hello”]
  • EXPOSE:仅仅是声明端口

    • 这个镜像服务守护的端口,方便配置映射
    • 在运行时使用随机端口映射时,也就是 docekr run -p 时,会自动随机映射 EXPOSE 的端口
    • 可以指定多个端口
  • CMD

    • 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同

      • CMD 在 docker run 时运行
      • RUN 是在 docker build 构建镜像时运行的
    • 作用:为启动容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可以被 docker run 命令行参数中指定要运行的程序所覆盖

    • exec 模式

      • CMD[“executable”,“param1”,“param2”](exec 模式)
    • shell 模式

      • CMD command (shell 模式)
    • exec 模式可以作为 ENTRYPOINT 指令的默认参数

  • ENTRYPOINT

    • 类似 CMD 指令,但其不会被 docker run 命令行参数指定的指令所覆盖。而且这些命令行参数会被当做参数送给 ENTRYPOINT 指令指定的程序。
    • 但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint 指令指定的程序。
    • 优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
    • 注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
    • image
    • image
  • COPY

    • 复制指令:从上下文目录中复制文件或者目录到容器里指定的路径

    • 格式:

      • COPY [--chown=:] < 源路径 1>... < 目标路径 >

      • COPY [--chown=:] ["< 源路径 1>",... "< 目标路径 >"]

      • [--chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

      • < 源路径 >:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match

        • 规则例如:

          • COPY hom* /mydir/
          • COPY hom?.txt /mydir/
      • < 目标路径 >:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

  • ADD

    • ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

      • ADD 的优点:在执行 < 源文件 > 为 tar 压缩文件的话,压缩格式为 gzip、bzip2 以及 xz 的情况下,会自动复制并解压到 < 目标路径 >
      • ADD 缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失败,从而可能会令镜像构建变的缓慢。具体是否使用,可以根据是否需要自动解压来决定
  • VOLUME

    • 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

    • 作用:

      • 避免重要的数据,因容器重启而丢失。
      • 避免容器不断变大
    • 格式:

      • VOLUME ["< 路径 1>", "< 路径 2>"...]
      • VOLUME < 路径 >
      • 在启动容器 docker run 的时候,我们可以通过-v 参数修改挂载点
      • VOLUME [“/data”]
  • WORKDIR

    • 指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层都存在,(WORKDIR 指定的工作目录,必须是提前创建好的)

    • docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才 会一直存在。

    • 格式

      • WORKDIR < 工作目录路径 >
      • WORKDIR /path/to/workdir (填写绝对路径)
  • ENV

  • USER

    • 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已 经存在)。

    • 格式:

      • USER < 用户名 >[:< 用户组 >]
      • image
  • ONBUILD

    • 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜 像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

    • 格式

      • ONBUILD < 其它指令 >
    • 为镜像添加触发器 当一个镜像被其他镜像作为基础镜像时需要写上 OBNBUILD 会在构建时插入触发器指令

    • 演示

      • image
      • image
  • LABEL

    • LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

      • LABEL = = = ...
      • 比如我们可以添加镜像的作者:
      • LABEL org.opencontainers.image.authors="xianchao"
  • HEALTHCHECK

    • 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

    • 格式

      • HEALTHCHECK [选项] CMD < 命令 >:设置检查容器健康状况的命令
      • HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
      • HEALTHCHECK [选项] CMD < 命令 > : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
  • ARG

    • 构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就 是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

    • 构建命令 docker build 中可以用 --build-arg < 参数名 >=< 值 > 来覆盖

    • 格式

      • ARG < 参数名 >[=< 默认值 >]

使用 dockerfile 构建 nginx 镜像

mkdir nginx
cd nginx
vim dockerfile

dockerfile 内容

FROM centos
MAINTAINER zzj
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
RUN yum -y clean all
RUN yum -y makecache
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;"]

index.html 内容

<html>
<head>
 <title>page added to dockerfile</title>
</head>
<body>
 <h1>i am in df_test </h1>
</body>
</html>

构建镜像

docker build -t="zzj/nginx:v1" .

image

基于刚才构建的镜像启动容器

docker run -d -p 80 --name html2 c8a8cf3cb8b0

注意:ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]

表示容器运行时,自动启动容器内的 nginx 服务

使用 dockerfile 构建 Tomcat 镜像

创建目录

mkdir tomcat8
cd tomcat8

apache-tomcat-8.0.26.tar.gzjdk-8u45-linux-x64.rpm 上传到 tomcat8 目录中

创建 dockerfile

vim dockerfile

内容如下

FROM centos
MAINTAINER zzj
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
RUN yum -y clean all
RUN yum -y makecache
RUN yum install wget -y
ADD jdk-8u45-linux-x64.rpm /usr/local
ADD apache-tomcat-8.0.26.tar.gz /usr/local
RUN cd /usr/local && rpm -ivh jdk-8u45-linux-x64.rpm
RUN mv /usr/local/apache-tomcat-8.0.26 /usr/local/tomcat8
EXPOSE 8080
ENTRYPOINT /usr/local/tomcat8/bin/startup.sh && tail -F /usr/local/tomcat8/logs/catalina.out

ADD 会先把 apache-tomcat-8.0.26.tar.gz 压缩包解压,然后把目录拷贝到容器中

开始构建镜像

docker build -t="tomcat:v1" .

image

运行一个容器

docker run --name tomcat8 -itd -p 8080 tomcat:v1

image

Docker 容器的数据管理

Docker 容器的数据卷

什么是数据卷? 数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或者多个容器提供访问,数据卷 设计的目的,在于数据的永久存储,它完全独立于容器的生存周期,因此,docker 不会在容器删除时删 除其挂载的数据卷,也不会存在类似的垃圾收集机制,对容器引用的数据卷进行处理,同一个数据卷可 以只支持多个容器的访问。

数据卷的特点:

1.数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会被拷贝到新初始 化的数据卷中

2.数据卷可以在容器之间共享和重用

3.可以对数据卷里的内容直接进行修改

4.数据卷的变化不会影像镜像的更新

5.卷会一直存在,即使挂载数据卷的容器已经被删除

数据卷的使用:

1.为容器添加数据卷

docker run --name volume -v ~/datavolume:/data -itd centos /bin/bash

注:~/datavolume 为宿主机目录,/data 为 docker 启动的 volume 容器的里的目录 这样在宿主机的/datavolume 目录下创建的数据就会同步到容器的/data 目录下

(1)为数据卷添加访问权限

docker run --name volume1 -v ~/datavolume1:/data:ro -itd centos /bin/bash

添加只读权限之后在 docker 容器的/data 目录下就不能在创建文件了,为只读权限;在宿主机下的 /datavolume1 下可以创建东西

2.使用 dockerfile 构建包含数据卷的镜像

FROM centos
VOLUME ["/datavolume3","/datavolume6"]
CMD /bin/bash 

使用如下构建镜像

docker build -t="volume" . 

启动容器

docker run --name volume-dubble -it volume

会看到这个容器下有两个目录,/datavolume3 和/datavolume6

Docker 的数据卷容器

什么是数据卷容器:

命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷

挂载数据卷容器的方法

docker run --name data-volume -itd volume

(volume 这个镜像是上面创建的带两个数据卷 /datavolume3 和/ddatavolume6 的镜像)

docker exec -it data-volume /bin/bash(进入到容器中)
touch /datavolume6/lucky.txt 

退出容器 exit

创建一个新容器挂载刚才 data-volume 这个容器创建的数据卷

docker run --name data-volume2 --volumes-from data-volume -itd centos /bin/bash

进入到新创建的容器

docker exec -it data-volume2 /bin/bash

查看容器的/datavolume6 目录下是否新创建了 lucky.txt 文件

docker 数据卷的备份和还原

数据备份方法:

docker run --volumes-from [container name] -v $(pwd):/backup centos tar czvf
/backup/backup.tar [container data volume] 

[container name] 从这个容器中备份文件

$(pwd) 宿主机上要存储备份文件的目录

backup 容器中要存储备份文件的目录

tar czvf /backup/backup.tar 容器中压缩文件存储的目录和名称

[container data volume] 容器中要备份的目录

例子

docker run --volumes-from data-volume2 -v /root/backup:/backup --name datavolume-copy
centos tar zcvf /backup/data-volume2.tar.gz /datavolume6

数据还原方法:

docker run --volumes-from [container name] -v $(pwd):/backup centos tar xzvf
/backup/backup.tar.gz [container data volume]

把挂载目录 $(pwd):/backup 中的文件 tar xzvf /backup/backup.tar.gz 进行解压,放入到 [container data volume]

例:

docker exec -it data-volume2 /bin/bash
cd /datavolume6
rm -rf lucky.txt
docker run --volumes-from data-volume2 -v /root/backup/:/backup centos tar zxvf
/backup/data-volume2.tar.gz -C /datavolume6
docker exec -it data-volum2 /bin/bash
cd /datavolum6

可以看到还原后的数据

docker 资源配额

docker 容器控制 cpu

Docker 通过 cgroup 来控制容器使用的资源限制,可以对 docker 限制的资源包括 CPU、内存、磁盘

指定 docker 容器可以使用的 cpu 份额

#查看配置份额的帮助命令:

docker run --help | grep cpu-shares

image

CPU shares (relative weight) 在创建容器时指定容器所使用的 CPU 份额值。cpu-shares 的值不能保证可以获得 1 个 vcpu 或者多少 GHz 的 CPU 资源,仅仅只是一个弹性的加权值。

默认每个 docker 容器的 cpu 份额值都是 1024。在同一个 CPU 核心上,同时运行多个容器时,容器的 cpu 加权的效果才能体现出来。

例: 两个容器 A、B 的 cpu 份额分别为 1000 和 500,结果会怎么样? 情况 1:A 和 B 正常运行,占用同一个 CPU,在 cpu 进行时间片分配的时候,容器 A 比容器 B 多一倍 的机会获得 CPU 的时间片。

情况 2:分配的结果取决于当时其他容器的运行状态。比如容器 A 的进程一直是空闲的,那么容器 B 是可以获取比容器 A 更多的 CPU 时间片的; 比如主机上只运行了一个容器,即使它的 cpu 份额只有 50,它也可以独占整个主机的 cpu 资源。

cgroups 只在多个容器同时争抢同一个 cpu 资源时,cpu 配额才会生效。因此,无法单纯根据某个容 器的 cpu 份额来确定有多少 cpu 资源分配给它,资源分配结果取决于同时运行的其他容器的 cpu 分 配和容器中进程运行情况。

例 1:给容器实例分配 512 权重的 cpu 使用份额

docker run -it --cpu-shares 512 centos /bin/bash
cat /sys/fs/cgroup/cpu/cpu.shares # 查看结果

注:稍后,我们启动多个容器,测试一下是不是只能使用 512 份额的 cpu 资源。单独一个容器,看 不出来使用的 cpu 的比例。 因没有 docker 实例同此 docker 实例竞争。

总结:

通过-c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能 分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。通过 cpu share 可以设置容器使用 CPU 的优先级。

比如在 host 中启动了两个容器:

docker run --name "container_A" -c 1024 ubuntu
docker run --name "container_B" -c 512 ubuntu

container_A 的 cpu share 1024,是 container_B 的两倍。当两个容器都需要 CPU 资源时, container_A 可以得到的 CPU 是 container_B 的两倍。

需要注意的是,这种按权重分配 CPU 只会发生在 CPU 资源紧张的情况下。如果 container_A 处于空 闲状态,为了充分利用 CPU 资源,container_B 也可以分配到全部可用的 CPU。

CPU core 核心控制

参数:--cpuset 可以绑定 CPU

对多核 CPU 的服务器,docker 还可以控制容器运行限定使用哪些 cpu 内核和内存节点,即使用-- cpuset-cpus 和--cpuset-mems 参数。对具有 NUMA 拓扑(具有多 CPU、多内存节点)的服务器尤其有 用,可以对需要高性能计算的容器进行性能最优的配置。如果服务器只有一个内存节点,则-- cpuset-mems 的配置基本上不会有明显效果。

扩展: 服务器架构一般分: SMP、NUMA、MPP 体系结构介绍 从系统架构来看,目前的商用服务器大体可以分为三类:

  1. 即对称多处理器结构(SMP : Symmetric Multi-Processor) 例: x86 服务器,双路服务 器。主板上有两个物理 cpu
    1. 非一致存储访问结构 (NUMA : Non-Uniform Memory Access) 例: IBM 小型机 pSeries 690
    1. 海量并行处理结构 (MPP : Massive ParallelProcessing) 。 例: 大型机 Z14

CPU 配额控制参数的混合使用

在上面这些参数中,cpu-shares 控制只发生在容器竞争同一个 cpu 的时间片时有效。 如果通过 cpuset-cpus 指定容器 A 使用 cpu 0,容器 B 只是用 cpu1,在主机上只有这两个容器使用 对应内核的情况,它们各自占用全部的内核资源,cpu-shares 没有明显效果。

如何才能有效果?

容器 A 和容器 B 配置上 cpuset-cpus 值并都绑定到同一个 cpu 上,然后同时抢占 cpu 资源,就可以 看出效果了。

例 1:测试 cpu-shares 和 cpuset-cpus 混合使用运行效果,就需要一个压缩力测试工具 stress 来让 容器实例把 cpu 跑满。

如何把 cpu 跑满?

如何把 4 核心的 cpu 中第一和第三核心跑满?可以运行 stress,然后使用 taskset 绑定一下 cpu。

先扩展:stress 命令

概述:linux 系统压力测试软件 Stress 。

yum install -y epel-release
yum install stress -y

stress 参数解释

  • -? 显示帮助信息

  • -v 显示版本号

  • -q 不显示运行信息

  • -n 显示已完成的指令情况

  • -t --timeout N 指定运行 N 秒后停止

    • --backoff N 等待 N 微妙后开始运行
  • -c 产生 n 个进程 :每个进程都反复不停的计算随机数的平方根,测试 cpu

  • -i 产生 n 个进程 :每个进程反复调用 sync(),sync()用于将内存上的内容写到硬 盘上,测试磁盘 io

  • -m --vm n 产生 n 个进程,每个进程不断调用内存分配 malloc()和内存释放 free()函 数 ,测试内存

    • --vm-bytes B 指定 malloc 时内存的字节数 (默认 256MB)
    • --vm-hang N 指定在 free 栈的秒数
  • -d --hadd n 产生 n 个执行 write 和 unlink 函数的进程

    • -hadd-bytes B 指定写的字节数
    • --hadd-noclean 不 unlink
  • 注:时间单位可以为秒 s,分 m,小时 h,天 d,年 y,文件大小单位可以为 K,M,G

例 1:产生 2 个 cpu 进程,2 个 io 进程,20 秒后停止运行

stress -c 2 -i 2 --verbose --timeout 20s

如果执行时间为分钟,改 20s 为 1m

查看:

top

image

例 2:测试 cpuset-cpus 和 cpu-shares 混合使用运行效果,就需要一个压缩力测试工具 stress 来让 容器实例把 cpu 跑满。 当跑满后,会不会去其他 cpu 上运行。 如果没有在其他 cpu 上运行,说明 cgroup 资源限制成功。

实例 3:创建两个容器实例:docker10 和 docker20。 让 docker10 和 docker20 只运行在 cpu0 和 cpu1 上,最终测试一下 docker10 和 docker20 使用 cpu 的百分比。实验拓扑图如下:

image

运行两个容器实例

docker run -itd --name docker10 --cpuset-cpus 0,1 --cpu-shares 512 centos /bin/bash

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

参数-itd 就是又能打开一个伪终端,又可以在后台运行着 docker 实例

docker run -itd --name docker20 --cpuset-cpus 0,1 --cpu-shares 1024 centos /bin/bash 

指定 docker20 只能在 cpu0 和 cpu1 上运行,而且 docker20 的使用 cpu 的份额 1024,比 dcker10 多 一倍

测试 1: 进入 docker10,使用 stress 测试进程是不是只在 cpu0,1 上运行:

docker exec -it docker10 /bin/bash
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
yum -y clean all   //清除所有文件
yum -y makecache   //建立缓存
yum install -y epel-release #安装 epel 扩展源
yum install stress -y #安装 stress 命令 
stress -c 2 -v -t 10m

运行 2 个进程,把两个 cpu 占满 在物理机另外一个虚拟终端上运行 top 命令,按 1 快捷键,查看每个 cpu 使用情况:

image

测试 2: 然后进入 docker20,使用 stress 测试进程是不是只在 cpu0,1 上运行,且 docker20 上运行 的 stress 使用 cpu 百分比是 docker10 的 2 倍

docker exec -it docker20 /bin/bash
rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
yum -y clean all   //清除所有文件
yum -y makecache   //建立缓存
yum install -y epel-release #安装 epel 扩展源
yum install stress -y #安装 stress 命令 
stress -c 2 -v -t 10m

在另外一个虚拟终端上运行 top 命令,按 1 快捷键,查看每个 cpu 使用情况:

image

注:两个容器只在 cpu0,1 上运行,说明 cpu 绑定限制成功。而 docker20 是 docker10 使用 cpu 的 2 倍。说明--cpu-shares 限制资源成功。

docker 容器控制内存

Docker 提供参数-m, --memory=""限制容器的内存使用量。

例 1:允许容器使用的内存上限为 128M:

docker run -it -m 128m centos 

进入容器查看查看:

cat /sys/fs/cgroup/memory/memory.limit_in_bytes

注:也可以使用 tress 进行测试,到现在,我可以限制 docker 实例使用 cpu 的核心数和权重,可以 限制内存大小。

例 2:创建一个 docker,只使用 2 个 cpu 核心,只能使用 128M 内

 docker run -it --cpuset-cpus 0,1 -m 128m centos

docker 容器控制 IO

查看限制 IO 的命令

 docker run --help | grep write-b

image

限制此设备上的写速度(bytes per second),单位可以是 kb、mb 或者 gb。 --device-read-bps value

限制此设备上的读速度(bytes per second),单位可以是 kb、mb 或 者 gb。

情景:防止某个 Docker 容器吃光你的磁盘 I / O 资源

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

--device 参数:将主机设备添加到容器

mkdir -p /var/www/html/
docker run -it -v /var/www/html/:/var/www/html --device /dev/sda:/dev/sda --device-write-bps /dev/sda:2mb centos /bin/bash
time dd if=/dev/sda of=/var/www/html/test.out bs=2M count=50 oflag=direct,nonblock

注:dd 参数:

direct:读写数据采用直接 IO 方式,不走缓存。直接从内存写硬盘上。

nonblock:读写数据采用非阻塞 IO 方式,优先写 dd 命令的数据

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

docker run --help | grep rm 

image

作用:当容器命令运行结束后,自动删除容器,自动释放资源

例:

docker run -it --rm --name xianchao centos sleep 6

等 5s 后,查看容器是否被删除

docker 容器互联

docker run 创建 Docker 容器时,可以用--net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:

  • bridge 模式:使--net =bridge 指定,默认设置;
  • host 模式:使--net =host 指定;
  • none 模式:使--net =none 指定;
  • container 模式:使用--net =container:NAME orID 指定。

docker 容器的网络基础

1、docker0:

安装 docker 的时候,会生成一个 docker0 的虚拟网桥

2、Linux 虚拟网桥的特点:

可以设置 ip 地址

相当于拥有一个隐藏的虚拟网卡

image

每运行一个 docker 容器都会生成一个 veth 设备对,这个 veth 一个接口在容器里,一个接口在物理机 上。

安装网桥管理工具:

yum install bridge-utils -y

brctl show 可以查看到有一个 docker0 的网桥设备,下面有很多接口,每个接口都表示一个启动的 docker 容器,因为我在 docker 上启动了很多容器,所以 interfaces 较多,如下所示:

image

docker 容器的互联

下面用到的镜像的 dockerfile 文件如下:

mkdir inter-image
vim dockerfile

内容如下

FROM centos
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
RUN yum -y clean all
RUN yum -y makecache
RUN yum install wget -y
RUN yum install nginx -y
EXPOSE 80
CMD /bin/bash
docker build -t="inter-image" .

允许所有容器间互联(也就是访问)

第一种方法:

(1)基于上面的 inter-image 镜像启动第一个容器 test1

docker run --name test1 -itd inter-image

进入到容器里面启动 nginx:

/usr/sbin/ngnx

(2)基于上面的 inter-image 镜像启动第二个容器 test2

docker run --name test2 -itd inter-image

(3)进入到 test1 容器和 test2 容器,可以看两个容器的 ip,分别是

172.17.0.6(test1) 和 172.17.0.7(test2)

进入 test2 容器

docker exec -it test2 /bin/bash 

ping 172.17.0.6 可以看见能 ping 同 test1 容器的 ip

curl http://172.17.0.6

可以访问到 test1 容器的内容

上述方法假如 test1 容器重启,那么在启动就会重新分配 ip 地址,所以为了使 ip 地址变了也可以访问 可以采用下面的方法

第二种方法:

docker link 设置网络别名

可以给容器起一个代号,这样可以直接以代号访问,避免了容器重启 ip 变化带来的问题

--link
docker run --link=[CONTAINER_NAME]:[ALIAS] [IMAGE][COMMAND]

例:

1.启动一个 test3 容器

docker run --name test3 -itd inter-image /bin/bash

2.启动一个 test4 容器,--link 做链接,那么当我们重新启动 test3 容器时,就算 ip 变了,也没关系, 我们可以在 test4 上 ping 别名 webtest

docker run --name test4 -itd --link=test3:webtest inter-image /bin/bash

webtest 是 test3 容器的别名

3.test3 和 test4 的 ip 分别是 172.17.0.8(test3) 和 172.17.0.9(test4)

4.重启 test3 容器

docker restart test3

发现 ip 变成了 172.17.0.25

5.进入到 test4 容器

docker exec -it test4 /bin/bash

ping test3 容器的 ip 别名 webtest 可以 ping 通,尽管 test3 容器的 ip 变了也可以通

docker 容器的网络模式

docker run 创建 docker 容器时,可以用--net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:

  • bridge 模式:使--net =bridge 指定,默认设置;
  • host 模式:使--net =host 指定;
  • none 模式:使--net =none 指定;
  • container 模式:使用--net =container:NAME orID 指定。

none 模式

Docker 网络 none 模式是指创建的容器没有网络地址,只有 lo 网卡

 docker run -itd --name none --net=none --privileged=true centos

进入到容器

docker exec -it none /bin/bash
ip addr

image

container 模式

Docker 网络 container 模式是指,创建新容器的时候,通过--net container 参数,指定其和已经存 在的某个容器共享一个 Network Namespace。如下图所示,右方黄色新创建的 container,其网卡共享左 边容器。因此就不会拥有自己独立的 IP,而是共享左边容器的 IP 172.17.0.2,端口范围等网络资源,两 个容器的进程通过 lo 网卡设备通信。

image

和已经存在的 none 容器共享网络

docker run --name container2 --net=container:none -it --privileged=true centos
 ip addr

image

bridge 模式

默认选择 bridge 的情况下,容器启动后会通过 DHCP 获取一个地址

创建桥接网络

 docker run --name bridge -it --privileged=true centos bash
ip addr

image

host 模式

Docker 网络 host 模式是指共享宿主机的网络

共享宿主机网络

docker run --name host -it --net=host --privileged=true centos bash

docker 私有镜像仓库 harbor

Harbor 介绍 Docker 容器应用的开发和运行离不开可靠的镜像管理,虽然 Docker 官方也提供了公共的镜像仓库, 但是从安全和效率等方面考虑,部署我们私有环境内的 Registry 也是非常必要的。Harbor 是由 VMware 公司开源的企业级的 Docker Registry 管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、 自我注册、镜像复制和中文支持等功能。 官网地址:https://github.com/goharbor/harbor

实验环境:

安装 harbor 的机器,主机名设置成 harbor 机器需要的内存至少要 2G,我分配的是 4G

虚拟机 IP:192.168.101.36"

配置虚拟机网络

一般我们新创建的虚拟机网卡都是 ens33

vi /etc/sysconfig/network-scripts/ifcfg-ens33

修改网卡配置文件

# 修改
BOOTPROTO="static"
ONBOOT="yes"
# 新增
IPADDR="192.168.101.36"
GATEWAY="192.168.101.1"
NETMASK="255.255.255.0"
DNS1="8.8.8.8"
DNS2="114.114.114.114"
ZONE=public

重启网络

systemctl restart network

修改主机名

 hostnamectl set-hostname harbor && bash

为 Harbor 自签发证书

创建目录存放私钥

mkdir /data/ssl -p
cd /data/ssl/

生成 ca 证书

openssl genrsa -out ca.key 3072

生成一个 3072 位的 key,也就是私钥

openssl req -new -x509 -days 3650 -key ca.key -out ca.pem

生成一个数字证书 ca.pem,3650 表示证书的有效时间是 3 年,按箭头提示填写即可,没有箭头标注的为 空:CH(中国)BJ(北京)

image

生成域名的证书

openssl genrsa -out harbor.key 3072

生成一个 3072 位的 key,也就是私钥

openssl req -new -key harbor.key -out harbor.csr

生成一个证书请求,一会签发证书时需要的,标箭头的按提示填写,没有箭头标注的为空:

image

签发证书

openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650

显示如下,说明证书签发好了:

image

安装 Harbor

关闭虚拟机防火墙

systemctl stop firewalld && systemctl disable firewalld

安装 iptables

yum install iptables-services -y

禁用 iptables

service iptables stop && service disable iptables

清空防火墙规则

iptables -F

关闭 selinux

vi /etc/selinux/config

image

设置为 disabled

修改成功之后重启虚拟机才会生效

重启之后使用下面命令查看是否生效

getenforce

image

disabled 表示 selinux 已经关闭

配置时间同步

虚拟机想要和网络时间和北京时间同步需要进行配置,安装用于时间同步的工具

yum install -y ntp ntpdate

和网络时间进行同步

ntpdate cn.pool.ntp.org

编写一个计划任务,专门用来时间同步

crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org // 表示没一小时和网络时间进行同步

重启 crond 服务使配置生效

systemctl restart crond

配置 hosts 文件

如果你想在别的机器上访问到 harbor 就把 192.168.101.36 harbor 配置到 hosts 文件

vi /etc/hosts

文件内容

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.101.35 zzj
192.168.101.36 harbor

安装 docker

安装基础软件包

 yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack

docker 安装

安装 docker 需要的基础包

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

配置安装 docker 国内 yum 源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装 docker-ce

yum install docker-ce -y
docker version # 查看docker版本

启动 docker 和配置 docker 开机自启动

systemctl start docker && systemctl enable docker

查看 docker 是否启动

systemctl status docker

image

修改 docker 内核参数

内核参数修改:br_netfilter 模块用于将桥接流量转发至 iptables 链,br_netfilter 内核参数需要开启转发。

modprobe br_netfilter # 加载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

net.ipv4.ip_forward = 1

将 Linux 系统作为路由或者 VPN 服务就必须要开启 IP 转发功能。当 linux 主机有多个网卡时一个网卡收 到的信息是否能够传递给其他的网卡 ,如果设置成 1 的话 可以进行数据包转发,可以实现 VxLAN 等功 能。不开启会导致 docker 部署应用无法访问。

使配置生效

 sysctl -p /etc/sysctl.d/docker.conf

查看 br_netfilter 是否生效

lsmod | grep br_netfilter

image

br_netfilter 模块在虚拟机重启之后又会失效,我们需要编写开机自动加载模块脚本,下面是脚本

vim /etc/rc.sysinit
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done
vim /etc/sysconfig/modules/br_netfilter.modules
modprobe br_netfilter

给文件设置权限

chmod 755 /etc/sysconfig/modules/br_netfilter.modules

配置好后,可以重启虚拟机查看 br_netfilter 模块是否开启加载了

重启 docker

systemctl restart docker

配置 docker 的阿里云镜像加速器

image

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dqk40brb.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

安装 harbor

安装目录创建

mkdir /data/install -p
cd /data/install/

下载 harbor 离线包

https://github.com/goharbor/harbor/releases

放入到 /data/install/ 目录

解压

tar -zxvf harbor-offline-installer-v2.11.0.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
vim harbor.yml

修改 harbor.yml 配置

hostname: harbor #修改 hostname,跟上面签发的证书域名保持一致
# 协议用 https
certificate: /data/ssl/harbor.pem
private_key: /data/ssl/harbor.key

邮件和 ldap 不需要配置,在 harbor 的 web 界面可以配置 其他配置采用默认即可 修改之后保存退出 注:harbor 默认的账号密码:admin/Harbor12345

安装 docker-compose

最新版的 docker 不需要再手动安装 docker-compose,安装 docker 的时候已经自带

安装

./install.sh # 执行安装脚本

image

安装脚本执行完成之后,harbor 相关的容器服务已经启动,如果下次需要重新启动或者停止,可以使用 docker-compose 命令,不用在执行安装脚本了,安装脚本执行一次就行。

修改电脑的 hosts 文件

image

在文件中添加如下一行:

192.168.101.36 harbor

Harbor 图像化界面使用说明

访问地址

新建项目

image

image

测试使用 harbor 私有镜像仓库
vim /etc/docker/daemon.json

内容如下

"insecure-registries": ["192.168.101.36","harbor"]

image

重启 docker 服务

systemctl daemon-reload && systemctl restart docker
systemctl status docker # 查看docker是否重启成功
使用 docker 登录 harbor
docker login 192.168.101.36
用户名:admin
密码:Harbor123456

image

如果登录失败出现如下错误,就重启容器:

docker compose start

image

导入 tomcat 镜像

docker load -i tomcat.tar.gz

把 tomcat 镜像打标签

docker tag tomcat:latest 192.168.101.36/test/tomcat:v1

image

把镜像推送到 harbor

docker push 192.168.101.36/test/tomcat:v1

image

删除机器上我们打标签的 tomcat 镜像

 docker rmi -f 192.168.101.36/test/tomcat:v1

在从 harbor 仓库下载镜像

docker pull 192.168.101.36/test/tomcat:v1

  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    492 引用 • 926 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...