企业必会技能Docker容器、部署web ui应用、资源限制、端口转发、异主容器互联、超细详解

部署docker web ui应用

下载并运行容器:

[root@docker-server ~]# docker pull uifd/ui-for-docker
[root@docker-server ~]# docker run -it -d --name docker-web -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock docker.io/uifd/ui-for-docker

浏览器访问测试:
在这里插入图片描述

Docker资源限制

系统压力测试工具stress
stress是一个linux下的压力测试工具,专门为那些想要测试自己的系统,完全高负荷和监督这些设备运行的用户。

cpu资源限制

限制CPU Share

什么是cpu share:

docker允许用户为每个容器设置一个数字,代表容器的 CPU share,默认情况下每个容器的 share 是 1024。这个 share 是相对的,本身并不能代表任何确定的意义。当主机上有多个容器运行时,每个容器占用的 CPU 时间比例为它的 share 在总额中的比例。docker 会根据主机上运行的容器和进程动态调整每个容器使用 CPU 的时间比例。

例子:

如果主机上有两个一直使用 CPU 的容器(为了简化理解,不考虑主机上其他进程),其 CPU share 都是 1024,那么两个容器 CPU 使用率都是 50%;如果把其中一个容器的 share 设置为 512,那么两者 CPU 的使用率分别为 70% 和 30%;如果删除 share 为 1024 的容器,剩下来容器的 CPU 使用率将会是 100%。

好处:
能保证 CPU 尽可能处于运行状态,充分利用 CPU 资源,而且保证所有容器的相对公平;
缺点:
无法指定容器使用 CPU 的确定值。
设置 CPU share 的参数:

 -c --cpu-shares,它的值是一个整数

我的机器是 4 核 CPU,因此运行一个stress容器,使用 stress 启动 4 个进程来产生计算压力:(无CPU限制)

[root@docker-server ~]# docker pull progrium/stress
[root@docker-server ~]# yum -y install epel-release
[root@docker-server ~]# yum install -y htop
[root@docker-server ~]# docker run --rm -it progrium/stress --cpu 4
stress: info: [1] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 12000us
stress: dbug: [1] --> hogcpu worker 4 [6] forked
stress: dbug: [1] using backoff sleep of 9000us
stress: dbug: [1] --> hogcpu worker 3 [7] forked
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [8] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [9] forked

在另外一个 terminal 使用 htop 查看资源的使用情况:
在这里插入图片描述上图中看到,CPU 四个核资源都达到了 100%。

为了比较,另外启动一个 share 为 512 的容器:

1.先将没有做限制的命令运行起来
[root@docker-server ~]# docker run --rm -it progrium/stress --cpu 4
2.在开启一个终端,运行做了CPU限制的命令
[root@docker-server ~]# docker run --rm -it -c 512 progrium/stress --cpu 4
stress: info: [1] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 12000us
stress: dbug: [1] --> hogcpu worker 4 [6] forked
stress: dbug: [1] using backoff sleep of 9000us
stress: dbug: [1] --> hogcpu worker 3 [7] forked
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [8] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [9] forked
3.在开启一个终端执行htop命令
[root@docker-server ~]# htop

因为默认情况下,容器的 CPU share 为 1024,所以这两个容器的 CPU 使用率应该大致为 2:1,下面是启动第二个容器之后的监控截图:
在这里插入图片描述
两个容器分别启动了四个 stress 进程,第一个容器 stress 进程 CPU 使用率都在 66% 左右,第二个容器 stress 进程 CPU 使用率在 33% 左右,比例关系大致为 2:1,符合之前的预期。

限制CPU 核数

限制容器能使用的 CPU 核数

-c --cpu-shares 参数只能限制容器使用 CPU 的比例,或者说优先级,无法确定地限制容器使用 CPU 的具体核数;从 1.13 版本之后,docker 提供了 --cpus 参数可以限定容器能使用的 CPU 核数。这个功能可以让我们更精确地设置容器 CPU 使用量,是一种更容易理解也因此更常用的手段.
--cpus 后面跟着一个浮点数,代表容器最多使用的核数,可以精确到小数点二位,也就是说容器最小可以使用 0.01 核 CPU。

限制容器只能使用 1.5 核数 CPU:

[root@docker-server ~]# docker run --rm -it --cpus 1.5 progrium/stress --cpu 3
stress: info: [1] dispatching hogs: 3 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 9000us
stress: dbug: [1] --> hogcpu worker 3 [6] forked
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [7] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [8] forked

在容器里启动三个 stress 来跑 CPU 压力,如果不加限制,这个容器会导致 CPU 的使用率为 300% 左右(也就是说会占用三个核的计算能力)。实际的监控如下图:
在这里插入图片描述
可以看到,每个 stress 进程 CPU 使用率大约在 50%,总共的使用率为 150%,符合 1.5 核的设置。

如果设置的 --cpus 值大于主机的 CPU 核数,docker 会直接报错:

[root@docker-server ~]# docker run --rm -it --cpus 8 progrium/stress --cpu 3  #启用三个进程做测试
docker: Error response from daemon: Range of CPUs is from 0.01 to 4.00, as there are only 4 CPUs available.
See 'docker run --help'.

如果多个容器都设置了 --cpus ,并且它们之和超过主机的 CPU 核数,并不会导致容器失败或者退出,这些容器之间会竞争使用 CPU,具体分配的 CPU 数量取决于主机运行情况和容器的 CPU share 值。也就是说 --cpus 只能保证在 CPU 资源充足的情况下容器最多能使用的 CPU 数,docker 并不能保证在任何情况下容器都能使用这么多的 CPU(因为这根本是不可能的)。

CPU 绑定

限制容器运行在某些 CPU 核

一般并不推荐在生产中这样使用

docker 允许调度的时候限定容器运行在哪个 CPU 上。

案例:

假如主机上有 4 个核,可以通过 --cpuset 参数让容器只运行在前两个核上:

[root@docker-server ~]# docker run --rm -it --cpuset-cpus=0,1 progrium/stress --cpu 2 
stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [6] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [7] forked 

这样,监控中可以看到只有前面两个核 CPU 达到了 100% 使用率。
在这里插入图片描述

mem资源限制

docker 默认没有对容器内存进行限制,容器可以使用主机提供的所有内存。

不限制内存带来的问题:

这是非常危险的事情,如果某个容器运行了恶意的内存消耗软件,或者代码有内存泄露,很可能会导致主机内存耗尽,因此导致服务不可用。
可以为每个容器设置内存使用的上限,一旦超过这个上限,容器会被杀死,而不是耗尽主机的内存。 

限制内存带来的问题:

限制内存上限虽然能保护主机,但是也可能会伤害到容器里的服务。如果为服务设置的内存上限太小,会导致服务还在正常工作的时候就被 OOM 杀死;如果设置的过大,会因为调度器算法浪费内存。

合理做法:

1. 为应用做内存压力测试,理解正常业务需求下使用的内存情况,然后才能进入生产环境使用
2. 一定要限制容器的内存使用上限,尽量保证主机的资源充足,一旦通过监控发现资源不足,就进行扩容或者对容器进行迁移
3. 尽量不要使用 swap,swap 的使用会导致内存计算复杂,对调度器非常不友好

docker 限制容器内存使用量:

docker 启动参数中,和内存限制有关的包括(参数的值一般是内存大小,也就是一个正数,后面跟着内存单位 b、k、m、g,分别对应 bytes、KB、MB、和 GB):

-m --memory:容器能使用的最大内存大小,最小值为 4m

如果限制容器的内存使用为 64M,在申请 64M 资源的情况下,容器运行正常(如果主机上内存非常紧张,并不一定能保证这一点):

[root@docker-server ~]# docker run --rm -it -m 64m progrium/stress --vm 1 --vm-bytes 64M --vm-hang 0
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [6] forked
stress: dbug: [6] allocating 67108864 bytes ...
stress: dbug: [6] touching bytes in strides of 4096 bytes ...
stress: dbug: [6] sleeping forever with allocated memory

容器可以正常运行。
-m 64m:限制你这个容器只能使用64M
--vm-bytes 64M:将内存撑到64兆是不会报错,因为我有64兆内存可用。
hang:就是卡在这里。
--vm:生成几个占用内存的进程

而如果申请 150M 内存,会发现容器里的进程被 kill 掉了(worker 6 got signal 9,signal 9 就是 kill 信号)

[root@docker-server ~]# docker run --rm -it -m 64m progrium/stress --vm 1 --vm-bytes 150M --vm-hang 0
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [6] forked
stress: dbug: [6] allocating 157286400 bytes ...
stress: dbug: [6] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 6 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 1s

端口转发

在这里插入图片描述使用端口转发解决容器端口访问问题

-p:创建应用容器的时候,一般会做端口映射,这样是为了让外部能够访问这些容器里的应用。可以用多个-p指定多个端口映射关系。 

mysql应用端口转发:

查看本地地址:

[root@docker-server ~]# ip a 
...
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:9c:bf:66 brd ff:ff:ff:ff:ff:ff
    inet 192.168.246.141/24 brd 192.168.246.255 scope global dynamic ens33
       valid_lft 5217593sec preferred_lft 5217593sec
    inet6 fe80::a541:d470:4d9a:bc29/64 scope link 
       valid_lft forever preferred_lft forever
[root@docker-server ~]# docker pull daocloud.io/library/mysql:5.7
[root@docker-server ~]# docker run -d --name mysql1 -p 3307:3306  -e MYSQL_ROOT_PASSWORD=Qf@123! daocloud.io/library/mysql:5.7
a4327dbddf665b4302c549320bff869b8a027c2e1eead363d84ce5d06acf2698

-e MYSQL_ROOT_PASSWORD= 设置环境变量,这里是设置mysql的root用户的密码

通过本地IP:192.168.246.141的3307端口访问容器mysql1内的数据库,出现如下提示恭喜你

1.安装一个mysql客户端
[root@docker-server ~]# yum install -y mysql
2.登录
[root@docker-server ~]# mysql -uroot -p'Qf@123!' -h 192.168.246.141 -P 3307
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.26 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>
-P(大P):当使用-P标记时,Docker 会随机映射一个 32768~49900 的端口到内部容器开放的网络端口。如下:
[root@docker-server ~]# docker pull daocloud.io/library/redis
[root@docker-server ~]# docker images
REPOSITORY                   TAG        IMAGE ID            CREATED           SIZE
daocloud.io/library/redis    latest     598a6f110d01        2months ago       118MB
[root@docker-server ~]# docker run --name myredis -P -d daocloud.io/library/redis
ca06a026d84a0605d9a9ce6975389a79f4ab9a9a043a03f088cd909c1fe52e29
[root@docker-server ~]# docker ps 
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                               NAMES
ca06a026d84a        daocloud.io/library/redis       "docker-entrypoint.s…"   22 seconds ago      Up 21 seconds       0.0.0.0:32768->6379/tcp             myredis

从上面的结果中可以看出,本地主机的32768端口被映射到了redis容器的6379端口上,也就是说访问本机的32768端口即可访问容器内redis端口。

在别的机器上通过上面映射的端口32768连接这个容器的redis

[root@docker-server2 ~]# yum install -y redis
[root@docker-server2 ~]# redis-cli -h 192.168.246.141 -p 32768
192.168.246.141:32768> ping
PONG
192.168.246.141:32768>

容器卷

把本地宿主机上面的某一个目录挂载到容器里面的目录去。这两个目录都不用提前存在,会自动创建
新卷只能在容器创建过程当中挂载

[root@docker-server ~]# docker run -it --name testnginx -v /test:/test2 daocloud.io/library/nginx /bin/bash
root@86320e734cd1:/# ls
root@86320e734cd1:/# ctrl+p+q  #退出	· 

测试:
[root@docker-server ~]# cd /test/
[root@docker-server test]# ls
[root@docker-server test]# touch a.txt 
[root@docker-server test]# cd
[root@docker-server ~]# docker exec -it testnginx /bin/bash
root@86320e734cd1:/# cd test2/
root@86320e734cd1:/test2# ls
a.txt

共享文件:
[root@docker-server ~]# mkdir /dir
[root@docker-server ~]# vim /dir/a.txt
123
[root@docker-server ~]# docker run -it --name testnginx2 -v /dir/a.txt:/dir1/a.txt daocloud.io/library/nginx /bin/bash
root@f899be627552:/# cat dir1/a.txt 
123

共享其他容器的卷(其他容器用同一个卷):

[root@docker-server ~]# docker run -it --name testnginx1 --volumes-from testnginx daocloud.io/library/nginx /bin/bash
root@50e6f726335c:/# ls
bin   dev  home  lib64	mnt  proc  run	 srv  test2  usr
boot  etc  lib	 media	opt  root  sbin  sys  tmp    var
root@50e6f726335c:/# cd test2/
root@50e6f726335c:/test2# ls
a.txt

实际应用中可以利用多个-v选项把宿主机上的多个目录同时共享给新建容器:

比如:

# docker run -it -v /abc:/abc -v /def:/def 1ae9

Docker数据存储位置

查看存储路径
[root@docker-server ~]# docker info | grep Root
 Docker Root Dir: /var/lib/docker

修改默认存储位置:
在dockerd的启动命令后面追加--data-root参数指定新的位置
[root@docker-server ~]# vim  /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data

[root@docker-server ~]# systemctl daemon-reload 
[root@docker-server ~]# systemctl restart docker

查看是否生效:
[root@docker-server ~]# docker info | grep Root
 Docker Root Dir: /data
 
[root@docker-server ~]# cd /data/
[root@docker-server data]# ls
builder  buildkit  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes

Docker网络

容器网络分类
注:

面试用,用了编排之后就没有用了

查看当前网络:

[root@docker-server ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
9b902ee3eafb        bridge              bridge              local
140a9ff4bb94        host                host                local
d1210426b3b0        none                null                local

docker安装后,默认会创建3种网络类型,bridge、host和none

1、bridge:网络桥接

默认情况下启动、创建容器都是用该模式,所以每次docker容器重启时会按照顺序获取对应ip地址。

2、none:无指定网络

启动容器时,可以通过--network=none,docker容器不会分配局域网ip 

3、host:主机网络

docker容器和主机共用一个ip地址。
使用host网络创建容器:
[root@docker-server ~]# docker run -it --name testnginx2 --net host 98ebf73ab
[root@docker-server ~]# netstat -lntp | grep 80
tcp6       0      0 :::80                   :::*                    LISTEN      3237/docker-proxy

浏览器访问宿主ip地址

4、固定ip:

创建固定Ip的容器:

4.1、创建自定义网络类型,并且指定网段
[root@docker-server ~]# docker network create --subnet=192.168.0.0/16 staticnet
4efd309244c6ad70eda2d047a818a3aec5b162f5ca29fb6024c09a5efbf15854
通过docker network ls可以查看到网络类型中多了一个staticnet:
[root@docker-server ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9b902ee3eafb        bridge              bridge              local
140a9ff4bb94        host                host                local
d1210426b3b0        none                null                local
4efd309244c6        staticnet           bridge              local
 4.2、使用新的网络类型创建并启动容器
[root@docker-server ~]# docker run -itd --name server --net staticnet --ip 192.168.0.2 daocloud.io/library/centos:7
 通过docker inspect可以查看容器ip为192.168.0.2:
[root@docker-server ~]# docker inspect userserver | grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "192.168.0.2",

关闭容器并重启,发现容器ip并未发生改变
4.3、删除已创建网络
需要删除使用当前网络的容器。才能删除网络
[root@docker-server]# docker network rm staticnet

异主容器互联

方式1、路由方式

小规模docker环境大部分运行在单台主机上,如果公司大规模采用docker,那么多个宿主机上的docker如何互联
在这里插入图片描述
Docker默认的内部ip为172.17.42.0网段,所以必须要修改其中一台的默认网段以免ip冲突。

注:docker版本为1.13
1.在docker-server1上面操作----192.168.246.141
[root@docker-server1 ~]# docker pull daocloud.io/library/centos
[root@docker-server1 ~]# vim /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=--bip=172.17.0.1/16
[root@docker-server1 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@docker-server1 ~]# sysctl -p
[root@docker-server1 ~]# reboot
[root@docker-server1 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
daocloud.io/library/centos   latest              0f3e07c0138f        3 weeks ago         220MB
[root@docker-server1 ~]# docker run -it --name centos daocloud.io/library/centos:latest /bin/bash
[root@ef1a4d6be97f /]#
[root@docker-server1 ~]# docker inspect centos | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
===============================================
2.docker-server2(192.168.246.143)上:
[root@docker-server2 ~]# vim /etc/sysconfig/docker-network
DOCKER_NETWORK_OPTIONS=--bip=172.18.0.1/16
[root@docker-server2 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@docker-server2 ~]# sysctl -p
[root@docker-server2 ~]# reboot
[root@docker-server2 ~]# systemctl daemon-reload
[root@docker-server2 ~]# systemctl restart docker
[root@docker-server2 ~]# docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
daocloud.io/library/centos   latest              0f3e07c0138f        3 weeks ago         220MB
[root@docker-server2 ~]# docker run -it --name centos daocloud.io/library/centos:latest /bin/bash 
[root@c84a8c704d03 /]#
[root@docker-server2 ~]# docker inspect centos| grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.18.0.2",
                    "IPAddress": "172.18.0.2",

添加路由:

[root@docker-server1 ~]# route add -net 172.18.0.0/16 gw 192.168.246.143
[root@docker-server2 ~]# route add -net 172.17.0.0/16 gw 192.168.246.141

验证:

进入到docker-server1主机的centos容器中,ping docker-server2主机的centos容器,进行测试

在这里插入图片描述
进入到docker-server2主机的centos容器中,ping docker-server1主机的centos容器,进行测试
在这里插入图片描述
现在两台宿主机里的容器就可以通信了。

方式二、open vswitch

如果要在生产和测试环境大规模采用docker技术,首先就需要解决不同物理机建的docker容器互联问题。

centos7环境下可以采用open vswitch实现不同物理服务器上的docker容器互联

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值