虚拟化分类
- 虚拟化资源提供者
- 硬件平台虚拟化
- 操作系统虚拟化
虚拟化实现方式
Type I 半虚拟化(裸机虚拟化)
特点:直接运行在硬件之上,只需要通过Hypervisor,所以效率很高
Type II 硬件辅助全虚拟化
特点:硬件全仿真,隔离好,用的也是最多的
Type III
软件全虚拟化
特点:全部都是虚拟的效率比较差
操作系统虚拟化
主机虚拟化
主机虚拟化的优缺点
- 应用程序运行环境强隔离
- 虚拟化操作系统与底层操作系统无关化
- 虚拟机内部操作不会影响到物理机
- 拥有操作系统会占用部署资源及存储
- 网络传输效率低
- 当应用程序需要调用硬件响应用户访问时间延迟大
容器虚拟化
容器虚拟化优缺点
- 可以实现应用程序的隔离
- 直接使用物理机操作硬件响应时间短
- 不占用部署时间
- 占用少量的磁盘空间
- 缺点:学习成本增加、操作控制麻烦、网络控制与主机虚拟化有所区别、服务治理
云平台的技术实现
IaaS 虚拟机
- 阿里云 ECS
- OpenStack VM实例
- 底层的网络,存储,硬件,虚拟化,服务都由服务商提供,你所使用的使用上面的数据库,安全,运行时,与开发的应用程序
PaaS 容器(CaaS)
- LXC
- Docker
- OpenShift
- Rancher
- 底层的一切环境全部打包,只需要开发的应用程序即可,就好像各大互联网公司在微信开发的小程序,底层都由为微信所提供
SaaS 应用程序
- 互联网中应用都是
- 全是别人开发好的,你直接用就是了
容器所涉及内核技术
- NameSapce
UTS:每一个NameSapce的都拥有独立的主机名或域名,可以把每一个NameSpace认为是一个独立的主机
Mount:每一个容器的文件系统都是独立的
Net:每一个容器的网络都是隔离的
PID:每一个容器都拥有独立的进程树,容器是物理机的一个进程,容器的进程是物理机的线程
USER:每个容器的用户与组ID的都是独立的,每个容器都拥有自己的root用户
IPC:实现进程之间的通信,每个容器依旧使用Linux内核中的进程交互方法
总结:
容器使用的命名空间有哪些?
应用程序应用的隔离空间,就是一个容器,每一个容器都有UTS,Mount,Net,PID,USER,IPC
Cgroups
-
控制组
-
作用:用于实现容器资源的隔离
-
可对进程做资源隔离
-
9大子系统
- 把资源定义为子系统,可以通过子系统对资源进行限制
- CPU可以让进程使用CPU的比例
- memory限制内存使用,例如50Mi,150Mi
- blkio 限制块设备IO
- cpuacct 生成Cgroup使用CPU的资源报告
- cpuset 用于多CPU执行Cgroup时,对进程进行CPU分组
- devices 允许或拒绝设备的访问
- freezer 暂停或恢复Cgroup运行
- net_cls
- ns
-
应用案例
通过Cgroup限制进程对CPU的使用
第一步:部署Cgroup
yum install -y libcgroup*
systemctl start cgconfig
第二步:创建cgroup组
vim /etc/cgconfig.conf
group lesscpu {
cpu {
cpu.shares=200;
}
}
group morecpu {
cpu {
cpu.shares=800;
}
}
#在文件的最后加上这么两段
#修改完配置文件记得重启
systemctl restart cgconfig
第三步:把进程添加到cgroup
cgexec -g cpu:lesscpu md5sum /dev/zero
#终端1
cgexec -g cpu:morecpu sha1sum /dev/zero
#终端2
top
#终端3
限制内存使用
第一步:修改配置文件
vim /etc/cgconfig.conf
group lessmem {
memory {
memory.limit_in_bytes=268435465;
memory.memsw.limit_in_bytes=268435465;
}
}
#限制内存连swap交换分区一起限制不然是没用的
#重启一下服务
systemctl restart cgconfig
第二步:验证
mkdir /mnt/mem_test
mount -t tmpfs /dev/shm /mnt/mem_test
cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M count=200
记录了200+0 的读入
记录了200+0 的写出
209715200字节(210 MB)已复制,0.105744 秒,2.0 GB/秒
cgexec -g memory:lessmem dd if=/dev/zero of=/mnt/mem_test/file1 bs=1M count=500
已杀死
- 扩展
-
主机虚拟化实现资源隔离的方式
- 使用Hypervisor中的VMM实现资源隔离
-
PAM
-
用户认证
-
资源限制
-
ulimit
-
仅对用户做资源限制
-
-
-
容器管理工具
-
LXC
- 2008
- 是第一套完整的容器管理解决方案
- 不需要任何补丁直接运行在linux内核之上管理容器
- 缺点:创建容器慢,不方便移置
-
Docker
- 2013
- dotcloud
- 是在LXC基础上发展起来的
- 拥有一套容器管理生态系统
- 生态系统包含:容器镜像、注册表、RESTFul API 及命令行操作界面
-
Docker版本介绍
-
2017之前的版本
- 最新版本为1.13
-
2017年3月1日后
- docker成为了商业开源
- docker-ce(社区版)
- docker-ee(商业版)
- docker成为了商业开源
-
容器管理工具Docker安装
部署docker
- docker
- 作用:用于管理容器
- 官方网址 www.docker.com
- 镜像仓库 https://hub.docker.com
- 开发语言:golang
第一步:卸载旧版本docker
[root@localhost ~]#yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
或者
[root@localhost ~]# yum remove docker*
第二步:安装yum-utils获取yum-config-manager
[root@localhost ~]#yum install -y yum-utils device-mapper-persistent-data lvm2
第三步:通过yum-config-manager获取docker-ce.repo
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
ls /etc/yum.repos.d/ |grep docker
docker-ce.repo
第四步:安装docker-ce
yum repolist
yum list |grep docker-ce
yum install -y docker-ce
第五步:启动docker并设置开机自启
systemctl enable docker
systemctl start docker
第六步:查看docker版本
docker version
Client: Docker Engine - Community
Version: 20.10.8
API version: 1.41
Go version: go1.16.6
Git commit: 3967b7d
Built: Fri Jul 30 19:55:49 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.8
API version: 1.41 (minimum version 1.12)
Go version: go1.16.6
Git commit: 75249d8
Built: Fri Jul 30 19:54:13 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.9
GitCommit: e25210fe30a0a703442421b0f60afac609f950a3
runc:
Version: 1.0.1
GitCommit: v1.0.1-0-g4144b63
docker-init:
Version: 0.19.0
GitCommit: de40ad0
#此文档为2021年9月份中旬更新所以是当前的最新版本
使用docker管理容器
容器、镜像、仓库、daemon、client之间关系
启动容器
验证是否有镜像在本地
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
本地没有镜像,需要去dockerhub仓库search镜像
docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 6765 [OK]
本地没有镜像,需要下载镜像到本地
#centos为镜像名字
docker pull centos
#查看本地是否有镜像
docker images
#如果docker官方镜像下载慢可以使用阿里镜像
#在 /etc/docker/daemon.json 文件中添加以下参数
#①进入/etc/docker/
cd/etc/docker
#如果没有daemon.json这个文件则创建一个
#将下面代码添加到daemon.json文件中保存
{
"registry-mirrors": ["https://9cpn8tt6.mirror.aliyuncs.com"]
}
#②然后重启服务
systemctl daemon-reload #---重启守护线程
systemctl restart docker #---重启docker
运行容器
docker run -it --name haojuetrace centos:latest /bin/bash
[root@80aad1c39409 /]#
查看运行中的容器
docker ps
docker daemon管理
- 远程管理docker daemon充分条件
- 可以把docker client与docker daemon分开部署
- 可以通过第三方软件管理docker daemon创建的容器
第一步:关闭docker daemon
修改docker配置文件前,先关闭docker守护进程
systemctl stop docker
第二步:修改docker daemon配置文件
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/docker
#只需要修改这一行就可以了
#如果想使用/etc/docker/daemon.json管理docker daemon,默认情况下,/etc/docker目录中并没有daemon.json文件,添加后会导致docker daemon无法启动,在添加daemon.json文件之前,需要先修改这一行的内容
第三步:加载配置文件
systemctl daemon-reload
第四步:重新开启docker守护进程
systemctl start docker
第五步:添加配置文件对docker daemon配置
通过/etc/docker/daemon.json文件对docker守护进程文件进行配置
cd /etc/docker
vim daemon.json
{
"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]
}
ss -anput |grep ":2375"
ls /var/run
systemctl restart docker
第六步:实例远程连接方法
docker -H 远程容器主机 version
docker命令行实现容器管理
-
容器镜像分类
- 系统镜像
- 应用镜像
搜索镜像
docker search centos
获取镜像(pull)
docker pull centos
或
docker image pull centos
容器镜像传输
- 为了方便使用容器镜像启动多服务
打包本地容器镜像(打包成压缩包保存在本地)
docker save --help
Usage: docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
Options:
-o, --output string Write to a file, instead of STDOUT
docker save -o centos.tar centos:latest
传输
scp haonginx.tar 192.168.122.130:/root
将镜像包导入到本地docker镜像目录
docker load --help
docker load -i centos.tar
启动容器
docker run 设置项 镜像名 运行命令
#设置项 -d 后台运行 --restart=always 开启自启
docker run -it --name c1 centos:latest /bin/bash
或
docker container run -it --name c2 centos:latest /bin/bash
修改一个容器的设置项
docker update mynginx --restart=always
启动一个运行httpd服务的容器
docker run -it --name c1 centos:latest /bin/bash
在容器中安装httpd
yum install -y httpd
/usr/sbin/httpd -k start
curl http://localhost
基于容器生成文件导入容器镜像
docker export --help
Usage: docker export [OPTIONS] CONTAINER
Export a container's filesystem as a tar archive
Options:
-o, --output string Write to a file, instead of STDOUT
docker import --help
Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
Import the contents from a tarball to create a filesystem image
Options:
-c, --change list Apply Dockerfile instruction to the created
image
-m, --message string Set commit message for imported image
--platform string Set platform if server is multi-platform capable
docker import -m httpd centos-httpd.tar centos-httpd:v1
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos-httpd v1 da4dfb859952 26 seconds ago 295MB
docker history centos-httpd:v1
#查看历史版本改变
docker run -it --name wyb centos-httpd:v1 /bin/bash
httpd -k start
curl http://localhost
查看容器IP地址
ip a s
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group
default
link/ether 02:42:51:3d:45:08 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:51ff:fe3d:4508/64 scope link
valid_lft forever preferred_lft forever
方法一:
docker run -it --name c2 centos /bin/bash
yum install -y iproute
ip a s
方法二:
docker inspect c2
#查看容器详细
方法三:
docker exec c2 ip a s
停止运行中的容器
docker ps
#查看正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
80aad1c39409 centos:latest "/bin/bash" 2 hours ago Up 5 seconds wyb
docker stop 8
#ID的简写,还是容器的名字的都是可以的,只要是唯一匹配的结果即可
docker ps
docker ps --all
#关闭或启动多个容器
docker stop c1 wyb
docker start c1 wyb
进入容器
#进入容器内部的系统 ,修改容器内容
[root@localhost ~]# docker exec -it 容器id /bin/bash
或者
[root@localhost ~]# docker exec -it 容器id /bin/sh
docker attach --help
Usage: docker attach [OPTIONS] CONTAINER
Attach local standard input, output, and error streams to a running container
Options:
--detach-keys string Override the key sequence for detaching
a container
--no-stdin Do not attach STDIN
--sig-proxy Proxy all received signals to the
process (default true)
docker attach c1
删除已停止的容器
docker rm mynginx
容器端口映射
docker run -it -p 80:80 --name c101 centos:latest /bin/bash
yum install -y httpd iproute
echo "web test" >> /var/www/html/index.html
httpd -k start
curl http://172.17.0.2
#在容器里访问自己的IP
curl http://172.17.0.2
#在容器主机里访问容器
curl http://192.168.122.130
#同一网段的其他主机访问容器主机的80端口
#如果仅定义了容器的端口,那么容器主机会随机添加映射端口到容器80端口,随机端口大于或等于32768
docker run -it -p 80 --name c101 centos:latest /bin/bash
docker ps
#使用容器主机的某一IP地址上的端口做随机映射
docker run -it -p 192.168.122.197::80 --name c101 centos /bin/bash
提交改变镜像
作用:可以保存修改好的镜像
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f8dd863c2fc nginx "/docker-entrypoint.…" 15 minutes ago Up 15 minutes 0.0.0.0:88->80/tcp, :::88->80/tcp mynginx
[root@localhost ~]# docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John
Hannibal Smith
<hannibal@a-team.com>")
-c, --change list Apply Dockerfile
instruction to the
created image
-m, --message string Commit message
-p, --pause Pause container during
commit (default true)
[root@localhost ~]# docker commit -a "haojuetrace" -a "首页变化" 3f8dd863c2fc haonginx:v1.0
容器使用Docker HOST存储数据
第一步:在Docker HOST创建用于存储的目录
mkdir /opt/volume
第二步:运行容器并挂载上述目录
docker run -it -v /opt/volume:/data --name c103 centos:latest /bin/bash
ls / |grep data
案例:运行在容器中的http服务,使用docker host的/web目录中的网页文件,并在docker host上进行修改,修改后即可生效
第一步:创建存储目录
mkdir /web
第二步:容器对/web目录进行挂载
docker run -it -p 8080:80/tcp -v /web:/var/www/html --name c100 centos:latest /bin/bash
第三步:验证
curl http://192.168.122.170:8080
同步容器时间
docker run -it -v /etc/localtime:/etc/localtime centos:latest /bin/bash
在容器外执行容器内命令
docker exec c1 ls /
容器间互联(--link)
第一步:创建被依赖容器
docker run -it --name c202 centos:latest /bin/bash
第二步:创建依赖于源容器的容器
docker run --link c202:mysqldb -it --name c203 centos:latest /bin/bash
ping mysqldb
cat /etc/hosts
第三步:验证
关闭容器
docker stop c202 c203
添加一个新的容器抢占c202的IP
docker run -it centos /bin/bash
启动c202及c203
docker start c202
docker start c203
docker exec c203 cat /ect/hosts
docker容器镜像
容器与镜像之间的关系:
- docker client向docker daemon发起创建容器的请求
- docker查找有无客户端需要的镜像
- 如果没有,则需要到镜像仓库下载需要的镜像
- 拿到容器镜像后,启动容器
容器镜像概述
Docker镜像是一组可读的目录,是容器的静态时,从官方文档的图片来看,容器也只比镜像多出了一个读写层
容器中的进程运行在这个可写层,可写层有两个状态,运行态与退出态,当docker run运行时,就进入了运行态,退出时就进入了退出态,期间发生的一切变化都会写入到文件系统中,而不是dokcer镜像
联合文件系统(UnionFS)是一种轻量级的高性能分层系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一虚拟文件系统下,应用看到的是挂载的最终结果
联合文件系统是实现docker镜像的技术基础,docker镜像可以通过分层来进行继承。例如,用户基于基础镜像(用来生成其他镜像的基础,往往没有父镜像)来制作各种不同的应用镜像,这些镜像共享同一个基础镜像层,提高了存储效率,此外,当用户改变了一个docker镜像(比如升级程序到新的版本),则会创建一个新的层(layer),因此,用户不用替换整个原镜像或重新建立,只需要添加新层即可,用户分发镜像的时候,也需要分发被改动的新层内容(增量部分),这让docker的镜像管理变得十分轻量级和快速。
制作基础镜像
第一步:
方法一:安装一个最小化的操作系统
方法二:用guestmount工具将镜像挂载
这里记录方法二:
安装guestmount工具
[root@master ~]# yum provides guestmount
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
1:libguestfs-tools-c-1.40.2-10.el7.x86_64 : System administration tools for virtual machines
Repo : base
Matched from:
Filename : /usr/bin/guestmount
1:libguestfs-tools-c-1.40.2-10.el7.x86_64 : System administration tools for virtual machines
Repo : local
Matched from:
Filename : /usr/bin/guestmount
[root@master ~]# yum install -y libguestfs-tools-c-1.40.2-10.el7.x86_64
挂载镜像
[root@master ~]# mkdir cirros
[root@master ~]# guestmount -a cirros-0.3.0-x86_64-disk.img -i cirros
第二步:打包操作系统的根目录(排除/proc /sys)
cirros.tar.gz代表压缩后的文件名
cirros代表需要压缩的目录
./ 压缩后文件存放的目录
[root@master ~]# tar --numeric-owner --exclude=/proc --exclude=/sys -cvf cirros.tar.gz -C cirros ./
第三步:将打包好的根文件导入docker host
cirros.tar.gz 需要导入的压缩包
cirros:v1.0 导入后的镜像名称以及版本号
[root@master ~]# docker import cirros.tar.gz cirros:v1.0
或者
[root@master ~]# cat cirros.tar.gz | docker import - cirros:v1.0
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cirros v1.0 49378bd68b43 3 seconds ago 11.9MB
第四步:使用基础镜像启动容器
[root@master ~]# docker run -it --name haojuetrace cirros:v1.0 /bin/bash
ls /proc
制作应用镜像
第一步:在基础镜像运行中的容器安装应用(例如httpd)
yum install -y httpd
第二步:使用commit命令将运行中的容器提交为一个应用镜像
docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith
<hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
docker commit -a haojuetrace centos7u6-httpd:v1
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7u6-httpd v1 df2118a32640 6 seconds ago 1.26GB
centos7u6 latest 4a357a4b11db 19 minutes ago 1.08GB
第三步:使用应用镜像
[root@docker01 ~]# docker run -it centos7u6-httpd:v1 /bin/bash
[root@f0a71ce03e99 /]# echo "haojuetrace" >> /var/www/html/index.html
[root@f0a71ce03e99 /]# httpd -k start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[root@f0a71ce03e99 /]# curl http://localhost
wyb
使用Dockerfile创建容器镜像
Dockerfile原理
在Dockerfile定义所要执行的命令,使用docker build创建镜像,过程中会按照Dockerfile所定义的内容打开临时性容器(使用docker commit进行提交),把dockerfile文件中的命令全部执行完成,就得到了一个容器应用镜像
执行命令越多,最终得到的容器镜像越大,所以要做优化
Dockerfile关键字
-
FROM(指定基础什么image镜像)
-
WORKDIR(指定shell语句运行在那个路径下)
-
MAINTAINER(用来指定镜像创建者信息)
-
COPY(将宿主机的文件拷贝到容器某路径下)
-
ADD(从src复制文件到container的dest路径/可以从url中复制到容器中)
-
RUN(运行shell语句,只要构建就会运行,如echo 321 >> 1.txt)
-
CMD(设置container(容器)启动时执行的操作)
- 如果容器镜像中要此命令,启动容器时,不要手动让容器执行其命令
- 指定镜像启动运行的脚本,只有容器真正运行的时候才会运行的脚本,执行后容器的生命周期即结束,且一般为阻塞式语句,如tail语句
-
ENTRYPOINT(设置container(容器)启动时执行的操作)
- ENTRYPOINT非json则以ENTRYPOT为准,如果ENTRYPOINT和CMD都是JSON则ENTRYPOINT+CMD拼接成shell
-
USER(设置container容器的用户)
-
EXPOSE(指定容器需要映射(暴露)到虚拟机(服务器)的端口)
-
ENV(用于设置docker容器的环境变量,运行时一直生效)
-
ARG(构建参数,运行时无效,可以构建时候临时修改变量)
-
**
-
VOLUME(指定挂载点)
-
LABEL(指定元数据,便于找到docker)
-
ONBUILD(当前镜像构建的时候不会执行,基于当前镜像的镜像去构建的时候才会执行)
-
STOPSIGNAL(指定容器使用什么信号,一般指定信号名)
-
HEALTHCHECK(检查容器的健康状态)
-
SHELL(指定linux为/bin/sh,windows为cmd)
Dockerfile应用案例
案例1.
目的:通过Dockerfile创建一个可以在启动时就直接启动httpd应用的镜像
第一步:创建目录
[root@haojuetrace ~]# mkdir dockerfile_Test
第二步:进入目录并创建用于启动httpd的脚本文件
[root@haojuetrace ~]# cd dockerfile_Test/
[root@haojuetrace dockerfile_Test]# cat createHttp.sh
#!bin/sh
#清除yum缓存
yum clean all
#安装httpd服务
yum install -y httpd
第三步:创建用于测试httpd的主页文件
[root@haojuetrace dockerfile_Test]# echo "my name is haojuetrace" >> index.html
第四步:创建Dockerfile
[root@haojuetrace dockerfile_Test]# cat Dockerfile
FROM centos:7 #指定镜像
MAINTAINER "HaoJueTrace" # 指定作者
WORKDIR / #指定shell脚本工作目录
ADD ./createHttp.sh ./createHttp.sh #拷贝文件到容器中
RUN chmod +x ./createHttp.sh #给文件赋权
RUN source ./createHttp.sh
ADD ./index.html /var/www/html/ #将文件添加进容器中/var/www/html目录
EXPOSE 80 #暴露80端口
CMD ["/usr/sbin/httpd","-D","FOREGROUND"] # 前台启动httpd服务
第五步:使用docker bulid创建镜像(最后的有个.代表dockerfile位于当前目录下)
[root@haojuetrace dockerfile_Test]# docker build -t httpd:v0.1 .
第六步:使用上述创建的应用镜像启动容器
[root@haojuetrace dockerfile_Test]# docker run -d httpd:v0.1
第七步:验证容器及httpd可用性
docker inspect 8ab
#查看容器IP地址
curl http://172.17.0.3
第八步:替代原网站内容案例(-v表示将本地目录映射到容器中的目录)
mkdir /wwwroot
echo "wwwroot" >> /wwwroot/index.html
docker run -d -v /wwwroot:/var/www/html centos7-httpd:v1
1ff9b907576a84e7a5f1a6f779749a35bc2f4d21984527dd046599b63a9
docker inspect 1ff
curl http://172.17.0.4
wwwroot
如果遇到Rpmdb错误,可以考虑安装:yum-plugin-ovl软件包。
案例2:把nginx应用容器化
要求:
- 通过基础镜像做nginx应用镜像
- 使用nginx应用容器时,nginx要求启动
- 验证nginx服务是否启动
第一步:创建目录
mkdir nginx
第二步:创建测试文件
cd nginx
echo "nginxtest" >> index.html
第三步:创建Dockerfile文件
vim Dockerfile
FROM centos7u6:latest
MAINTAINER "wyb"
RUN yum clean all && yum install -y yum-plugin-ovl && yum install -y epel-release
RUN yum install -y nginx
ADD index.html /usr/share/nginx/html/
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
CMD /usr/sbin/nginx
第四步:创建应用镜像
docker build -t centos-nginx:v1 .
第五步:启动容器测试
[root@docker01 ~]# docker run -d centos-nginx:v1
ce5dd1e2f4206643d3ead85935f6c85298e51ca420378235eb9cde044233
[root@docker01 ~]# docker inspect ce5dd
[root@docker01 ~]# curl 172.17.0.3
nginxtest
容器镜像在Docker host存储位置
从图中可以看出,除了最上面一层为读写层以外,下面的层都为镜像层,除了最下层以外,没一层都会指向他的更下面一层的镜像
虽然统一文件系统技术,将多层的镜像层整合一个统一的文件系统,为了构成一个完整的容器镜像的层提供了一个统一的视角,隐藏了多个层的复杂性,对于用户来说只存在一个文件系统,但图中的这些层也是可以在运行docke的主机上看见的
docker的容器镜像还是容器本身都存放在服务器上的/var/lib/docker下,Linux的发行版存在存储方式的不同,Ubuntu上的存储方式为AUFS,Centos发行版上的存储方式为Overlay或者Overlay2
centos系统默认docker使用的存储驱动是devicemapper,而这种存储驱动有两种模式loop-lvm和direct-lvm,可惜的是模式使用了比较低效的loop-lvm
Overlay与overlay2原理
OverlayFS将单个Linux主机上的两个目录合并成一个目录。这些目录被称为层,统一过程被称为联合挂载。
OverlayFS底层目录叫做lowerdir,高层目录叫做upperdir,合并统一视图叫做merged,分别对应容器镜像层、只读层(lmage layer)、容器层、可写层(container layer)和容器挂载(container mount)
当需要修改一个文件时,使用cow将文件只读的lower复制到可写的upper进行修改,结果也将保存在upper层
如果upper和lower有同名文件时会用
overlay2是overlay的改进版,增加了的特性,消耗更少的inode,只支持4.0以上内核添加了Multiple lower layers in overlayfs的特性,所以overlay2可以直接造成muitiple lower layers不用像overlay一样要通过硬链接的方式(最大128层) centos的话支持3.10.0-514及以上内核版本也有此特性,所以消耗更少的inode
本质区别是镜像层之间共享数据的方法不同
- overlay共享数据方式是通过硬链接,只挂载一层,其他层通过最高层通过硬链接形式共享(增加了磁盘inode的负担)
- 而overlay是通过每层的lower
查看docker默认使用的存储驱动方法
docker info
Storage Driver: overlay2
docker运行变化
/var/lib/docker/overlay2 路径下的信息在不同的阶段会有变化,了解这几个阶段中新增的数据以及容器与镜像的存
储结构的变化非常有利于我们对Docker容器以及Docker镜像的理解。
运行前
没有启动docker daemon时,不会再/var/lib/目录中添加docker目录
启动后
systemctl start docker
tree /var/lib/docker/
/var/lib/docker/
├── buildkit
│ ├── cache.db
│ ├── containerdmeta.db
│ ├── content
│ │ └── ingest
│ ├── executor
│ ├── metadata_v2.db
│ └── snapshots.db
├── containers
├── image
│ └── overlay2
│ ├── distribution
│ ├── imagedb
│ │ ├── content
│ │ │ └── sha256
│ │ └── metadata
│ │ └── sha256
│ ├── layerdb
│ └── repositories.json
├── network
│ └── files
│ └── local-kv.db
├── overlay2 #下载镜像后,存储在此目录中
│ ├── backingFsBlockDev
│ └── l
├── plugins
│ ├── storage
│ │ └── ingest
│ └── tmp
├── runtimes
├── swarm
├── tmp
├── trust
└── volumes
├── backingFsBlockDev
└── metadata.db
27 directories, 9 files
下载镜像后
[root@docker02 overlay2]# pwd
/var/lib/docker/overlay2
[root@docker02 overlay2]# ls
54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92 l
backingFsBlockDev
[root@docker02 overlay2]# ls 54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92/
diff link
[root@docker02 overlay2]# ls 54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92/diff/
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#centos镜像只有一层
[root@docker02 overlay2]# pwd
/var/lib/docker/overlay2
[root@docker02 overlay2]# ll l/
总用量 0
lrwxrwxrwx. 1 root root 72 9月 22 22:37 IQOMSQDDX3VJAKWALX534ZV5NO -> ../54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92/diff
#l目录中包含了很多多软链接,使用短名称指向了其他层,短名称用于避免mount参数时达到页面大小的限制
运行容器后
overlay2容器结构
#运行容器前
[root@docker02 overlay2]# ls
54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92 l
backingFsBlockDev
#运行容器后查看
[root@docker02 overlay2]# docker run -it centos:latest
85f2ef855ce2cf50b3b9f27b169cb9cc3b9a5227290e9cba782fb85ef4b5cdb5
[root@docker02 overlay2]# ls
54592cce402def24e5bd2bd6ff8ba38da98a3a3cad640a4c361c8378b6e3ee92
backingFsBlockDev
eca9d6dd7df092b856508a227991c0e80de53b5f8b886b91c5c14ea4df9df860
eca9d6dd7df092b856508a227991c0e80de53b5f8b886b91c5c14ea4df9df860-init
l
[root@docker02 overlay2]# ls eca9d6dd7df092b856508a227991c0e80de53b5f8b886b91c5c14ea4df9df860
diff link lower merged work
启动一个容器,也是在/var/lib/docker/overlay2目录下生成一层容器层,目录包括diff,link,lower,
merged,work。
diff记录每一层自己内容的数据;link记录该层链接目录(实际是l目录下到层的链接),比如在容器中创建目录
或在diff新增该目录;创建容器时将lower-id指向的镜像层目录以及upper目录联合挂载到merged目录;work
用来完成如copy-on_write的操作。
启动容器后,可以在docker host查看mount情况
mount |grep overlay
overlay on
/var/lib/docker/overlay2/00bd7dcc4c91f9a1a1257b8c0683fdd0b6dfe18af26597457e92b4d15c20cda0/merged type overlay
(rw,relatime,lowerdir=/var/lib/docker/overlay2/l/4GXMF7JGUPRUBLW5SM4X4FY5R2:/var/lib/docker/overlay2/l/MBRXMBFE2MYZYMO5RZLRLTMRGJ,upperdir=/var/lib/docker/overlay2/00bd7dcc4c91f9a1a1257b8c0683fdd0b6dfe18af26597457e92b4d15c20cda0/diff,workdir=/var/lib/docker/overlay2/00bd7dcc4c91f9a1a1257b8c0683fdd0b6dfe18af26597457e92b4d15c20cda0/work)
官方镜像仓库介绍
镜像仓库分类
- 公有仓库
- 私有仓库
官方镜像仓库
- 属于公有仓库
- 网址:hub.docker.com
注册一个账号
创建一个仓库
web界面登录这种就不示范了
#Linux命令行登录
docker login hub.docker.com
[root@docker01 ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: wyba
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
1、上传时需要登录
2、当有私有镜像仓库使用时需要登录
登出
docker logout
docker hub镜像上传、下载
镜像上传
上传到公有仓库必须先登录docker hub
给需要上传到公有仓库的容器镜像打上标记
[root@docker01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos-nginx v1 6d3289ba1cb9 9 hours ago 1.46GB
[root@localhost ~]# docker tag haonginx:v1.0 haojuetrace/haonginx:v1.0
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
haojuetrace/haonginx v1.0 155bafa6e7a0 34 minutes ago 141MB
haonginx v1.0 155bafa6e7a0 34 minutes ago 141MB
haonginx latest 605c77e624dd 2 months ago
把已打上标记的容器镜像上传到公有仓库
登录docker hub仓库
[root@localhost ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: haojuetrace
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@localhost ~]# docker push haojuetrace/haonginx:v1.0
The push refers to repository [docker.io/haojuetrace/haonginx]
登出docker hub仓库
上传完镜像要退出仓库 安全一点
[root@localhost ~]# docker logout
Removing login credentials for https://index.docker.io/v1/
镜像下载
docker pull wyba/nginx:v1
镜像加速器
docker中国
网址:www.docker-cn.com
以下内容是来自我两年前的配置现在有没有改变可以自己去看看
第一步:修改/usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd
第二步:在/etc/docker/daemon.json
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
第三步:重启docker daemon
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker
阿里云加速器
产品与服务-->容器镜像服务-->镜像加速器-->复制镜像地址-->修改daemon.json
[root@localhost docker]# vim daemon.json
{
"registry-mirrors": ["https://ewn7tqdy.mirror.aliyuncs.com"]
}
重启服务
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker
查看容器日志
docker logs 容器id/容器名
容器与主机交互(复制)
docker cp 要复制地址 目标地址
docker本地容器镜像仓库
作用
-
在局域网内使用
-
方便与其他系统进行集成
-
上传下载大镜像
registry实现本地非安全镜像仓库
第一步:下载registry镜像
docker pull registry
第二步:创建用于挂载至registry镜像启动的仓库中,便于容器镜像持久化保存
mkdir docker pull registry
第三步:启动容器
docker run -d -p 5000:5000 --restart=always -v /opt/dockerregistry:/var/lib/registry registry:latest
第四步:验证是否可用
[root@docker01 ~]# curl http://192.168.122.2:5000/v2/_catalog
{"repositories":[]}
第五步:在本地上传或下载本地仓库
#先配置一下才可以进入仓库
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd
vim /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.122.2:5000"]
}
#重启一下docker
systemctl daemon-reload
systemctl restart docker
[root@docker01 ~]# docker tag centos:latest 192.168.122.2:5000/centos:v1
[root@docker01 ~]# docker push 192.168.122.2:5000/centos:v1
The push refers to repository [192.168.122.2:5000/centos]
74ddd0ec08fa: Pushed
v1: digest: sha256:a1801b843b1bfaf77c501e7a6d3f709401a1e0c83863037fa3aab063a7fdb9dc size: 529
[root@docker01 ~]# ls /opt/dockerregistry/docker/registry/v2/repositories
centos
#在其他主机上使用此镜像仓库
第一步:修改/usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd
第二步:修改etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.122.2:5000"]
}
第三步:重启docker
systemctl daemon-reload
systemctl restart docker
第四步:下载容器镜像
[root@docker02 ~]# docker pull 192.168.122.2:5000/centos:v1
v1: Pulling from centos
a1d0c7532777: Pull complete
Digest: sha256:a1801b843b1bfaf77c501e7a6d3f709401a1e0c83863037fa3aab063a7fdb9dc
Status: Downloaded newer image for 192.168.122.2:5000/centos:v1
192.168.122.2:5000/centos:v1
registry实现基于用户名和密码访问的非安全镜像仓库
第一步:添加用户
mkdir -p /opt/data/auth/
docker run --entrypoint htpasswd registry:latest -Bbn wyb 123 >> /opt/data/auth/htpasswd
#上面这个命令根据registry版本与可能会报错,可以用另外的办法
yum install -y httpd-tools
mkdir /auth
htpasswd -Bbn wyb 123 > /auth/htpasswd
第二步:启动仓库
docker run -d \
> --restart=always \
> --name registry \
> -v /certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/myr.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/myr.org.key \
> -p 443:443 \
> -v /opt/registry:/var/lib/registry \
> -v /auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> registry:2.7.0
docker run -d -p 5000:5000 --restart=always \
-v /opt/data/auth/:/auth/
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e “REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd” \
-v /opt/data/docker/registry:/var/lib/registry/ registry:latest
#这个是最新版本的简单启动,这些参数最好自己多去理解而不是一味的复制黏贴
第三步:登录登出
[root@docker01 ~]# docker login 192.168.122.2:5000
Username: wyb
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@docker01 ~]# docker logout 192.168.122.2:5000
Removing login credentials for 192.168.122.2:5000
Harbor实现通过web管理本地非安全仓库
Harbor
- vmware公司开源
- 良好的中文界面
- web管理界面
- 使用广泛
安装前提
不同版本,不同的要求,具体可以到官网去查阅
https://goharbor.io/docs/2.3.0/install-config/installation-prereqs/
工具准备
- 使用docker-compose工具进行启动
- 准备安装docker-compose工具pip
- pip类似于yum,用于批量安装Python模块及解决Python模块依赖
pip工具准备
yum install -y epel-release
yum install -y python2-pip
pip install --upgrade pip
docker-compose工具准备
pip install docker-compose
最新版本的pip不支持Python2.7了可能更新的时候会遭到失败,可以使用下面的方法直接从官方下载
docker-compose version 1.29.2, build 5becea4ccurl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
[root@docker01 ~]# docker-compose --version
docker-compose version 1.29.2, build 5becea4c
获取Harbor
第一步:在GitHub上查找一下这个项目
第二步:找到项目的安装帮助
点击这个Harbor release
因为我本机是ubuntu的原因我就不演了,我直接scp或者是rsync丢到kvm的虚拟机上就行了,传上去方法很多,可以使用远程终端工具也可以curl或wget
第三步:解压
tar xf harbor-offline-installer-v2.3.3.tgz
第四步:配置(1.7版本配置的是harbor.cfg)
cd harbor
cp harbor.yml.tmpl harbor.yml
#将示例配置文件拷贝一份出来
没有HTTPS证书的这里记得注释掉
改一下这个东西就好了其他的配置可以去官方文档
https://goharbor.io/docs/2.3.0/install-config/configure-yml-file/#required-parameters
扩展:这个是我去年笔记的1.7版本修改的配置文件
cat harbor.cfg
## Configuration file of Harbor
#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
_version = 1.7.0
#The IP address or hostname to access admin UI and registry service.
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external
clients.
#DO NOT comment out this line, modify the value of "hostname" directly, or the
installation will fail.14
hostname = 192.168.122.2
#此为重点
第五步:安装
[root@docker01 harbor]# ./install.sh
第六步:访问
#密码在配置文件里设置的
[root@docker01 harbor]# cat harbor.yml |grep 'harbor_admin_password: admin'
harbor_admin_password: admin
上传镜像到harbor镜像私有仓库
第一步:在daemon.json添加此仓库地址
vim /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.122.2"]
}
systemctl restart docker
第二步:给需要上传的镜像打上标签
docker tag centos:latest 192.168.122.2/library/centos:v1
第三步:上传镜像
#上传镜像需要先登录
docker login http://192.168.122.2
docker push 192.168.122.2/library/centos:v1
在其他服务器上访问harbor
第一步:修改daemon.json文件
vim /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.122.2"]
}
systemctl restart docker
第二步:查看下载镜像的命令
第三步:拉取镜像
docker pull 192.168.122.2/library/centos@sha256:a1801b843b1bfaf77c501e7a6d3f709401a1e0c83863037fa3aab063a7fdb9dc
或
docker pull 192.168.122.2/library/centos:v1
docker容器网络
本地网络
bridge
所以容器连接到桥,就可以使用外网,使用NAT可以让容器访问外网
ip a s
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:91:87:16:ba brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:91ff:fe87:16ba/64 scope link
valid_lft forever preferred_lft forever
#所有容器都连接到这个桥,IP地址都是172.17.0.1/16
[root@docker01 ~]# brctl show
bridge name bridge id STP enabled interfaces
br-d16023d9f263 8000.02426b98007a no veth34864b0
veth92d8266
vethb009331
vethc78571e
vethd5b3956
vethe2b4502
docker0 8000.0242918716ba no veth10f6c8b
#启动docker服务后出现
[root@docker01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
651300dd3cf6 bridge bridge local
#使用--network选择完成对容器网络的选择
docker run -d --network bridge centos:latest
每一台docker host上的docker0所在网段完全一样
host
所有的容器与dockerhost在同一网络中,可以让容器访问,甚至可以让外网主机访问容器中的服务
docker network ls
4230d06cbf7a host host local
使用--network选择容器运行的网络
[root@docker01 ~]# docker run -it --network host centos:latest /bin/bash
[root@docker01 /]#
#虽然看起来是没什么变化,但是所在的的目录已经变了,其使用的是docker host的IP地址,好处在于方便访问,坏处在于多容器同步运行一种服务会出现端口冲突,仅在测试环境中使用
none
容器仅有lo网卡,不能外界连接,一般在高级应用中会使用到
docker network ls
45ce643d297f none null local
[root@docker01 ~]# docker run -it --network none centos:latest /bin/bash
[root@f68cbd3e8ec4 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
容器网络或联盟网络
容器间共享同一个网络命名空间,实现容器间的数据传输
跨主机容器间网络
实现跨主机容器间间通信工具
- Pipework
- Flannel
- Weave
- Open V Switch OVS
- Calico
Flannel工作原理
- 是Overlay网络,即覆盖型网络
- 通过etcd保存子网信息及网络分配信息
- 给每台Docker Host分配一个网段
- 通过UDP传输数据包
配置flannel
环境说明
- node1
- 安装etcd flannel docker
- node2
- 安装flannel docker
第一步:主机配置
hostnamectl set-hostname node01
hostnamectl set-hostname node02
第二步:配置/etc/hosts
vim /etc/hosts
192.168.122.100 node01
192.168.122.110 node02
192.168.122.100 etcd
第三步:安全配置
systemctl stop firewalld
systemctl disable firewalld
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
第四步:安装软件
node01
yum -y install etcd flannel
node02
yum -y install flannel
第五步:配置etc与flannel
node01:
etcd配置
vim /etc/etcd/etcd.conf
修改ETCD_LISTEN_CLIENT_URLS与ETCD_ADVERTISE_CLIENT_URLS
开启etcd服务
systemctl start etcd
systemctl enable etcd
[root@node01 ~]# lsof -i:2379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
etcd 3887 etcd 6u IPv6 26326 0t0 TCP *:2379 (LISTEN)
etcd 3887 etcd 13u IPv4 28984 0t0 TCP localhost:60178->localhost:2379 (ESTABLISHED)
etcd 3887 etcd 15u IPv6 32884 0t0 TCP localhost:2379->localhost:60178 (ESTABLISHED)
[root@node01 ~]# lsof -i:4001
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
etcd 3887 etcd 7u IPv6 26327 0t0 TCP *:newoak (LISTEN)
etcd 3887 etcd 11u IPv4 32883 0t0 TCP localhost:39062->localhost:newoak (ESTABLISHED)
etcd 3887 etcd 14u IPv6 26329 0t0 TCP localhost:newoak->localhost:39062 (ESTABLISHED)
验证etcd
#测试etcd是否存取数据
[root@node01 ~]# etcdctl set testdir/wybkey0 100
100
[root@node01 ~]# etcdctl get testdir/wybkey0
100
#检查集群是否健康
[root@node01 ~]# etcdctl -C http://etcd:4001 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://etcd:2379
cluster is healthy
[root@node01 ~]# etcdctl -C http://etcd:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://etcd:2379
cluster is healthy
flannel配置
vim /etc/sysconfig/flanneld
在etcd中添加网段
[root@node01 ~]# etcdctl mk /atomic.io/network/config '{"Network": "172.20.0.0/16"}'
{"Network": "172.20.0.0/16"}
[root@node01 ~]# etcdctl get /atomic.io/network/config '{"Network": "172.20.0.0/16"}'
{"Network": "172.20.0.0/16"}
启动flannel
systemctl enable flanneld
systemctl start flanneld
配置flannel与docker结合
1.subnet信息
[root@node01 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.20.0.0/16
FLANNEL_SUBNET=172.20.84.1/24 #这个
FLANNEL_MTU=1472 #还有这个
FLANNEL_IPMASQ=false
2.配置docker daemon
vim /etc/docker/daemon.json
{
"bip": "172.20.84.1/24",
"mtu": 1472
}
3.重启docker
systemctl restart docker
4.启动容器验证网络
[root@node01 ~]# docker run -it centos:latest /bin/bash
[root@2493382c6fb4 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP group default
link/ether 02:42:ac:14:54:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.84.2/24 brd 172.20.84.255 scope global eth0
valid_lft forever preferred_lft forever
node02:
配置flannel
vim /etc/sysconfig/flanneld
启动flannel
systemctl enable flanneld
systemctl start flanneld
验证flannel
ip a
4: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 172.20.7.0/16 scope global flannel0
valid_lft forever preferred_lft forever
inet6 fe80::7644:d23b:f39c:e132/64 scope link flags 800
valid_lft forever preferred_lft forever
配置flannel与docker结合
1.获取subnet
[root@node02 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.20.0.0/16
FLANNEL_SUBNET=172.20.7.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
2.修改配置文件
vim /etc/docker/daemon.json
{
"bip": "172.20.7.1/24",
"mtu": 1472
}
3.重启docker
systemctl restart docker
4.开启容器验证
[root@node02 ~]# docker run -it centos:latest /bin/bash
[root@33b98bc9fcd5 /]# ip a
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP group default
link/ether 02:42:ac:14:07:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.7.2/24 brd 172.20.7.255 scope global eth0
valid_lft forever preferred_lft forever
验证容器的互通
[root@33b98bc9fcd5 /]# ping 172.20.84.2
ping: 192.168.122.84.2: Name or service not known
#这里ping不通,是防火墙的问题
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -L -n
容器编排部署
编排部署作用
- 实现复杂容器应用架构之间的互联
- 减少大量容器部署的成本
编排部署工具
- docker machine
- 用于准备docker host
-
docker compose
- 通过一个文件定义复杂的容器应用之间的关系
-
docker swarm
- 用于管理docker host
- 把docker host生成一个集群
- 可以使用YAML文件实现复杂容器应用编排
-
Kubernetes
- 简称k8s
- google公司内部使用了十几年伯格系统的开源
- 归云原生计算基金会
- 能够实现复杂容器应用的编排部署
- 容器自动装箱功能
- 容器滚动更新及回滚
- 容器水平扩展
- 配置中心
- 密钥和存储管理
- 容器云平台使用kubernetes完成核心功能
- openshift
- rancher
-
mesos+marathon
- mesos集群资源管理
- marathon 容器编排部署
docker-compose
docker-compose作用
在一个文件中定义复杂的容器应用之间的关系,用一个命令即可执行
- YAML格式文件
- docker-compose使用yaml文件启动容器
- start & stop
- down & up
docker-compose的定义方法
容器分三层:
- 工程 project 一个目录
- 服务 service 用于定义容器资源(镜像、网络、依赖、容器)
- 容器 container 用于运行服务
步骤:
- 创建一个目录
- 创建一个docker-compose.yaml文件,定义服务
- 使用docker-compose命令启动服务
docker-compose工具部署
pip安装
yum install -y epel-release
yum install -y python2-pip
pip install --upgrade pip
pip install docker-compose
官网下载最新稳定版本
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
[root@node01 ~]# docker-compose --version
docker-compose version 1.29.2, build 5becea4c
使用docker-compose部署应用案例
案例一
使用haproxy实例web应用发布
第一步:创建一个工程
[root@node01 ~]# mkdir docker-haproxy
[root@node01 ~]# cd docker-haproxy/
[root@node01 docker-haproxy]#
第二步:定义web服务
[root@node01 docker-haproxy]# mkdir web
[root@node01 docker-haproxy]# cd web/
[root@node01 web]# vim Dockerfile
FROM python:2.7
WORKDIR /code
ADD . /code
EXPOSE 80
CMD python index.py
[root@node01 web]# vim index.py
#!/usr/bin/python
#date:2021-09-31
import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import socket
import fcntl
import struct
import pickle
from datetime import datetime
from collections import OrderedDict
class HandlerClass(SimpleHTTPRequestHandler):
def get_ip_address(self,ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
def log_message(self, format, *args):
if len(args) < 3 or "200" not in args[1]:
return
try:
request = pickle.load(open("pickle_data.txt","r"))
except:
request=OrderedDict()
time_now = datetime.now()
ts = time_now.strftime('%Y-%m-%d %H:%M:%S')
server = self.get_ip_address('eth0')
host=self.address_string()
addr_pair = (host,server)
if addr_pair not in request:
request[addr_pair]=[1,ts]
else:
num = request[addr_pair][0]+1
del request[addr_pair]
request[addr_pair]=[num,ts]
file=open("index.html", "w")
file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\"face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit Results</h1></center>");
for pair in request:
if pair[0] == host:
guest = "LOCAL: "+pair[0]
else:
guest = pair[0]
if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d%H:%M:%S')).seconds < 3:
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +":<font color=\"red\">"+str(request[pair][0])+ "</font> requests " + "from <<fontcolor=\"blue\">"+guest+"</font>> to WebServer <<font color=\"blue\">"+pair[1]+"</font>></p>")
else:
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +":<font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from <<fontcolor=\"navy\">"+guest+"</font>> to WebServer <<font color=\"navy\">"+pair[1]+"</font>></p>")
file.write("</body> </html>");
file.close()
pickle.dump(request,open("pickle_data.txt","w"))
if __name__ == '__main__':
try:
ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"
addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1]
port = len(sys.argv) < 3 and 80 or int(sys.argv[2])
HandlerClass.protocol_version = Protocol
httpd = ServerClass((addr, port), HandlerClass)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
except:
exit()
第三步:定义haproxy服务
[root@node01 haproxy]# cat haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen stats
bind *:70
stats enable
stats uri /
frontend balancer
bind 0.0.0.0:80
mode http
default_backend web_backends
backend web_backends
mode http
option forwardfor3
balance roundrobin
server weba weba:80 check
server webb webb:80 check
server webc webc:80 check
option httpchk GET /
http-check expect status 200
第四步:创建docker-compose.yaml文件整合以上服务
[root@node01 docker-haproxy]# vim docker-compose.yaml
weba:
build: ./web
expose:
- 80
webb:
build: ./web
expose:
- 80
webc:
build: ./web
expose:
- 80
haproxy:
image: haproxy:latest
volumes:
- ./haproxy:/haproxy-override
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- weba
- webb
- webc
ports:
- "80:80"
- "70:70"
expose:
- 80
- 70
第五步:使用docker-compose命令启动工程
[root@node01 docker-haproxy]# pwd
/root/docker-haproxy
[root@node01 docker-haproxy]# docker-compose up
案例二
创建一个Python web应用,使用flask,把用户访问的次数写入redis,通过web首页显示访问次数
第一步:创建一个工程
[root@node01 ~]# mkdir docker-python
[root@node01 ~]# cd docker-python/
第二步:创建一个应用
[root@node01 docker-python]# vim app.py
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis',port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello world! I have been seen %s time.' %redis.get('hits')
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True)
第三步:创建安装的软件需求列表
[root@node01 docker-python]# vim requirements.txt
flask
redis
第四步:创建Dockerfile文件
[root@node01 docker-python]# vim Dockerfile
FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py
第五步:创建docker-compose.yaml文件
[root@node01 docker-python]# vim docker-compose.yaml
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
depends_on:
- redis
redis:
image: redis:latest
第六步:运行
[root@node01 docker-python]# pwd
/root/docker-python
[root@node01 docker-python]# docker-compose up
第七步:访问
多刷新几次,验证一下次数会不会变多
案例三
使用容器运行一个WordPress博客
- 语言开发环境
- 数据库
第一步:创建一个工程目录
[root@haojuetrace ~]# mkdir compose_Test
[root@haojuetrace ~]# cd compose_Test/
第二步:创建一个docker-compose.yaml目录
[root@haojuetrace compose_Test]# vim docker-compose.yaml
version: '1.0'
services: #服务入口
db: # 容器名称
image: mysql:5.7 #容器镜像
volumes: #宿主机挂载到容器内目录
- "./data/db:/var/lib/mysql"
restart: always #重启策略
environment: #环境变量
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
image: wordpress:latest
restart: always
depends_on: #依赖容器
- db
links: #容器互联
- db
ports: #映射端口(容器映射到宿主机)
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- "./wordpress:/var/www/html"
volumes:
wordpress:
db:
docker的重启策略
- always 在容器退出时总是重启容器,直到正常。------下面的全部状态码的时候重启
- no 默认策略,在容器退出时不重启容器---------任何时候都不重启容器(可以理解为躺平策略)
- on-failure:3 在容器非正常退出时重启容器,最多重启3次,三次之后是什么样就什么样了。-----退出状态码非0的时候重启,直到状态码为0为止
- on-failure 在容器非正常退出时(退出状态非0),才会重启容器,------退出状态码非0的时候重启,直到状态码为0为止,不限次数的重启。
- unless-stopped 在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器,也就是说,如果docker的守护进程启动后,然后因为一些其它原因导致容器退出,将不会重启容器。----------退出状态码不是0,125,126,127的时候。
第三步:启动
[root@haojuetrace compose_Test]# pwd
/root/wordpress
[root@haojuetrace compose_Test]# docker-compose up
第四步:验证
[root@haojuetrace compose_Test]# ls -a
. .. data docker-compose.yaml wordpress
第五步:访问docker host的8080端口
可能会出现连接数据库的连接问题,那你就自己写一个Mysql配置文件ADD丢过去
docker swarm
docker swarm概述
- docker host集群管理工具
- docker官方提供的
- docker 1.12版本以后
- 用来统一集群管理的,把整个集群资源做统一调度
- 比kubernetes要轻量级
- 实现scaling 规模扩大或缩小
- 实现roling update 滚动更新或版本回退
- 实现service discovery 服务发现
- 实现load balance 负载均衡
- 实现route mesh 路由网格,服务治理
docker swarm架构
-
节点(node)就是一台docker host
-
管理节点(manager node)负责管理集群中的节点并向工作节点分配任务
-
工作节点(worker node)接收管理节点分配的任务,运行任务
-
-
服务(services)在工作节点上运行的,由多个任务共同组成的
-
任务(task)运行在工作节点上容器或容器中包含应用,是集群中调度最小管理单元
docker swarm部署环境准备
准备主机
第一步:准备三台centos7.6
第二步:修改主机名
hostnamectl set-hostname node01
hostnamectl set-hostname node02
hostnamectl set-hostname node03
第三步:修改网络配置文件
[root@node1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE="Ethernet"
BOOTPROTO="static"
NAME="eth0"
DEVICE="eth0"
ONBOOT="yes"
IPADDR="192.168.122.100"
PREFIX="24"
GATEWAY="192.168.122.1"
DNS1="119.29.29.29"
#node01为100,node02为110,node03为120
我设置的是这三个
第四步:修改主机解析文件
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.122.100 node01
192.168.122.110 node02
192.168.122.120 node03
第五步:安全准备
#ntp
yum install -y ntpdate
crontab -e
0 */1 * * * ntpdate 120.25.108.11
#firewalld
systemctl stop firewalld;systemctl disable firewalld
#selinux
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
第六步:docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd
#只修改这一行
systemctl enable docker; systemctl start docker
docker swarm集群部署
角色划分
| node1 | node2 | node3 |
| :--------------------: | :----: | :----: |
| master(manager node) | worker | worker |
第一步:集群初始化
[root@node01 ~]# docker swarm init --listen-addr 192.168.122.100:2377
Swarm initialized: current node (mcjtse0ak06gq1xnhmjp498kq) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-64i0e36sknmuti2w7ee0h6qui 192.168.122.100:2377
#添加一个新的工作节点,就在其他两个服务器执行这个命令
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
您在 /var/spool/mail/root 中有邮件
支持多master节点,不过我这次只用了一个所以这个命令只需要在node1上执行
#除了初始化的时候,也可以直接查询
[root@node01 ~] #docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-04zq3wiz3pldo98cf1bcparn6 192.168.122.100:2377
[root@node01 ~] #docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-64i0e36sknmuti2w7ee0h6qui 192.168.122.100:2377
第二步:添加工作节点到swarm集群
node2与node3
[root@node01 ~] docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-64i0e36sknmuti2w7ee0h6qui 192.168.122.100:2377
[root@node02 ~] docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-64i0e36sknmuti2w7ee0h6qui 192.168.122.100:2377
This node joined a swarm as a worker.
[root@node03 ~] docker swarm join --token SWMTKN-1-3ee5p1z1eirpjnm5tsitngtgrwxrqu1m80zgoyuwpkvcqajddy-64i0e36sknmuti2w7ee0h6qui 192.168.122.100:2377
This node joined a swarm as a worker.
[root@node01 ~] docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
mcjtse0ak06gq1xnhmjp498kq * node01 Ready Active Leader 20.10.8
pq3grvnaqrc9ir983srsgbq06 node02 Ready Active 20.10.8
zj4qikfkfxfimtht4co7h146o node03 Ready Active 20.10.8
docker swarm应用
habor部署
这一步我就直接省略了,不是必要的,上面也有具体操作,本地仓库也好,公有仓库也好,没有也行
镜像准备
v1
[root@node01 ~] mkdir docker-nginx
[root@node01 ~] cd docker-nginx/
[root@node01 docker-nginx] echo 'This is a version 1.0' > index.html
[root@node01 docker-nginx] vim Dockerfile
FROM centos:latest
MAINTAINER "wyb<2117319540@qq.com>"
RUN yum clean all && yum install -y yum-plugin-ovl && yum install -y epel-release
RUN yum install -y nginx
ADD index.html /usr/share/nginx/html/
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
CMD /usr/sbin/nginx
[root@node01 docker-nginx] docker build -t 192.168.122.100/library/centos-nginx:v1 .
[root@node01 ~] docker login http://192.168.122.100
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@node01 ~] docker push 192.168.122.100/library/centos-nginx:v1
v2
echo 'This is a version 2.0' > index.html
#就改了这一个,其他的一毛一样
docker build -t 192.168.122.100/library/centos-nginx:v2 .
docker push 192.168.122.100/library/centos-nginx:v2
发布一个服务
- 在manager node上
[root@node01 ~] docker service create --replicas 2 --publish 8090:80 --name nginxsvc 192.168.122.100/library/centos-nginx:v1
waaupquh1ne5u46drq36bwcht
overall progress: 2 out of 2 tasks
1/2: running
2/2: running
verify: Service converged
[root@node01 ~] docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
waaupquh1ne5 nginxsvc replicated 2/2 192.168.122.100/library/centos-nginx:v1 *:8090->80/tcp
[root@node01 ~] docker service ps nginxsvc
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
b2nwoi0l3apg nginxsvc.1 192.168.122.100/library/centos-nginx:v1 node02 Running Running 35 seconds ago
w5rfb5s5k3xs nginxsvc.2 192.168.122.100/library/centos-nginx:v1 node01 Running Running 35 seconds ago
可以看见运行在node1与node2上
两个运行节点都需要拥有镜像或是有连接仓库或连接master node
扩展或缩小
[root@node01 ~] docker service scale nginxsvc=3
nginxsvc scaled to 3
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
#扩展到三份
[root@node01 ~] docker service scale nginxsvc=1
nginxsvc scaled to 1
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
#这个就是缩小到一份
滚动更新或版本回滚
[root@node01 ~] docker service update --image 192.168.122.100/library/centos-nginx:v2 nginxsvc
nginxsvc
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
#更新到版本v2
[root@node01 ~] docker service update --image 192.168.122.100/library/centos-nginx:v1 nginxsvc
nginxsvc
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
#回滚到v1
间隔更新方法
docker service update --replicas 3 --image 192.168.122.100/library/centos-nginx:v2 --update-parallelism 1 --update-delay 30s nginxsvc
删除
docker service rm nginxsvc
存储卷应用
- 持久化存储使用
本地卷
[root@node01 ~] docker service create --replicas 1 --mount "type=bind,source=$PWD,target=/abc" --publish 8081:80 --name cnginxsvc 192.168.122.100/library/centos-nginx:v1
9ja1swo3axvub78szekvytsg0
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
#创建一个服务并挂载当前目录到服务的/abc目录下
[root@node01 ~]# docker exec 2b0daee4d205 ls /abc
anaconda-ks.cfg
docker-haproxy
docker-nginx
docker-python
harbor
wordpress
[root@node01 ~]# ls
anaconda-ks.cfg docker-haproxy docker-nginx docker-python harbor wordpress
因为是本地卷,所以挂在上的也会不一样
#开始测试
[root@node02 ~]# touch node02.txt
[root@node02 ~]# ls
anaconda-ks.cfg node02.txt
[root@node03 ~]# touch node03.txt
[root@node03 ~]# ls
anaconda-ks.cfg node03.txt
#创建好两个测试文件,然后将服务扩展到三份
[root@node01 ~]# docker service scale cnginxsvc=3
cnginxsvc scaled to 3
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
[root@node02 ~]# docker exec 22ea8792775e ls /abc
anaconda-ks.cfg
node02.txt
[root@node03 ~]# docker exec a941f763b6fd ls /abc
anaconda-ks.cfg
node03.txt
总结一句:优点是可以将在容器上写入的内容持久化保存,但假如说你是一个web服务,那就不是建议本地卷了,挂载本地网页文件/var/www/html/,那么你如果网页文件了发生了改动就需要改动多个运行该服务的节点,就算是由脚本来完成也是多余的工作量,建议使用网络卷
网络存储卷
- 实现跨docker host之间容器数据共享
- 持久化保存网络服务中
第一步:创建nfs服务
node3上完成nfs服务
在所有的节点安装nfs
yum install -y nfs-utils rpcbind
在node3上创建共享目录
[root@node03 ~]# mkdir /opt/dockervolume
共享
[root@node03 ~]# echo '/opt/dockervolume *(rw,sync,no_root_squash)' > /etc/exports
输出共享
[root@node03 ~]# exportfs -rv
exporting *:/opt/dockervolume
启动服务
systemctl enable rpcbind nfs-server;systemctl start rpcbind nfs-server
查看是否共享
[root@node03 ~]# cat /var/lib/nfs/etab
/opt/dockervolume *(rw,sync,wdelay,hide,nocrossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,no_root_squash,no_all_squash)
第二步:在docker swarm中创建volume
查看卷列表
[root@node01 ~]# docker volume ls
DRIVER VOLUME NAME
local 2b532afbb53d16d670369b7c99daa27a282e0e649daa0448429e165cebcb42a7
local 2bfe2f77a7ab7022c8d69f752614286ec85e5f1ae9789e866644d5083bc0c334
local 62b629aa45f0b36209142c01ec2134ae9372fdd4c93f62bf7e1c8a5c1b36bf09
local 381b16a4d8505e76edcb3dea406a69789524ad4e6c6079763083cd11d99ab755
local a2a74731f569fd0477b39d31e05c029464cf7868faf7120cca57623d73330c55
local c033ab63c52e4dd4bda1424f91a2db020b4e894362a06bef485234d50d6ad166
local c41cf8372d7ec22a739b56bacb6db11660fb161adf1c4cf2cecd3e972439e8dc
local d3d131a9871f59c55206d2f9c26de3617bdaaa9c661b159a9189f14d11fa5515
local e91b8c01a765641b7e904e9f23d96dc799143877b89ed1d005954f8394ae96d2
local e512acd2a9640e2e7e2f47f23a36c7f2df0fc87ff47abf955174e105c3646a69
local ee6ecf249b7899bb1d0df84f5603fd6d470d28d3ea1e1905b68b205d049155f6
创建卷
[root@node01 ~]# docker volume create --driver local --opt type=nfs --opt o=addr=192.168.122.120,rw --opt device=:/opt/dockervolume wybvolume1
wybvolume1
[root@node01 ~]# docker volume ls
DRIVER VOLUME NAME
local 2b532afbb53d16d670369b7c99daa27a282e0e649daa0448429e165cebcb42a7
local 2bfe2f77a7ab7022c8d69f752614286ec85e5f1ae9789e866644d5083bc0c334
local 62b629aa45f0b36209142c01ec2134ae9372fdd4c93f62bf7e1c8a5c1b36bf09
local 381b16a4d8505e76edcb3dea406a69789524ad4e6c6079763083cd11d99ab755
local a2a74731f569fd0477b39d31e05c029464cf7868faf7120cca57623d73330c55
local c033ab63c52e4dd4bda1424f91a2db020b4e894362a06bef485234d50d6ad166
local c41cf8372d7ec22a739b56bacb6db11660fb161adf1c4cf2cecd3e972439e8dc
local d3d131a9871f59c55206d2f9c26de3617bdaaa9c661b159a9189f14d11fa5515
local e91b8c01a765641b7e904e9f23d96dc799143877b89ed1d005954f8394ae96d2
local e512acd2a9640e2e7e2f47f23a36c7f2df0fc87ff47abf955174e105c3646a69
local ee6ecf249b7899bb1d0df84f5603fd6d470d28d3ea1e1905b68b205d049155f6
local wybvolume1
#最后一个就是创建出来的那个卷了
[root@node01 ~]# docker volume inspect wybvolume1
[
{
"CreatedAt": "2021-10-02T15:44:13+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/wybvolume1/_data",
"Name": "wybvolume1",
"Options": {
"device": ":/opt/dockervolume",
"o": "addr=192.168.122.120,rw",
"type": "nfs"
},
"Scope": "local"
}
]
#手动发布服务时需要在集群中的每台主机添加volume
[root@node02 ~]# docker volume create --driver local --opt type=nfs --opt o=addr=192.168.122.120,rw --opt device=:/opt/dockervolume wybvolume1
wybvolume1
[root@node03 ~]# docker volume create --driver local --opt type=nfs --opt o=addr=192.168.122.120,rw --opt device=:/opt/dockervolume wybvolume1
wybvolume1
第三步:使用docker service发布服务时使用volume
- 手动启动service时使用volume
- 前提条件是nfs服务已经挂载到本地
- 创建多副本时需要在每个容器运行时的docker host上添加volume
[root@node01 ~]# docker service create --replicas 3 --publish 81:80 --mount "type=volume,source=wybvolume1,target=/usr/share/nginx/html" --name cnginxsvc-volume 192.168.122.100/library/centos-nginx:v1
o1szuwr925isimkwpg14xcxxq
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
#只需要改变nfs共享下的内容即可将其他工作节点一起改变
[root@node03 ~]# echo "volume test" >> /opt/dockervolume/index.html
[root@node03 ~]# ls /opt/dockervolume/
404.html 50x.html index.html nginx-logo.png poweredby.png
[root@node03 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd58600f70da 192.168.122.100/library/centos-nginx:v1 "/bin/sh -c /usr/sbi…" 4 minutes ago Up 4 minutes 80/tcp cnginxsvc-volume.1.p8wcs1eoi1ohmtto4ta60is5b
a941f763b6fd 192.168.122.100/library/centos-nginx:v1 "/bin/sh -c /usr/sbi…" About an hour ago Up About an hour 80/tcp cnginxsvc.3.n988i1qq861iys5svmaywdnj5
[root@node03 ~]# docker exec bd5 cat /usr/share/nginx/html/index.html
This is a version 1.0
volume test
[root@node02 ~]# docker exec 46ee cat /usr/share/nginx/html/index.html
This is a version 1.0
volume test
[root@node01 ~]# docker exec fa74 cat /usr/share/nginx/html/index.html
This is a version 1.0
volume test
确实是改变nfs内容就会改变全部工作节点的内容
[root@node03 ~]# echo "test" > /opt/dockervolume/index.html
#再次测试
使用编排的方式使用volume
1.先删除一下上个实操所留下的volume
[root@node01 ~]# docker service rm cnginxsvc-volume
cnginxsvc-volume
[root@node01 ~]# docker volume rm wybvolume1
wybvolume1
[root@node02 ~]# docker volume rm wybvolume1
wybvolume1
[root@node03 ~]# docker volume rm wybvolume1
wybvolume1
所有的节点都要删除
第一步:编排部署文件
[root@node01 ~]# mkdir nginx-volume
[root@node01 ~]# cd nginx-volume/
[root@node01 nginx-volume]# vim nginx-volume.yaml
version: '3.3'
services:
nginxsvc:
image: 192.168.122.100/library/centos-nginx:v1
deploy:
mode: replicated
replicas: 3
restart_policy:
condition: on-failure
ports:
- "81:80"
volumes:
- "wybvolume:/usr/share/nginx/html"
volumes:
wybvolume:
driver: local
driver_opts:
type: "nfs"
o: "addr=192.168.122.100,rw"
device: ":/opt/dockervolume"
第二步:使用docker stack发布服务
[root@node01 nginx-volume]# docker stack deploy -c nginx-volume.yaml nginx-stack
Creating network nginx-stack_default
Creating service nginx-stack_nginxsvc
[root@node01 ~]# docker volume ls
DRIVER VOLUME NAME
.........
.........
local nginx-stack_wybvolume
[root@node02 ~]# docker volume ls
DRIVER VOLUME NAME
local nginx-stack_wybvolume
[root@node03 ~]# docker volume ls
DRIVER VOLUME NAME
local nginx-stack_wybvolume
[root@node03 ~]# ls /opt/dockervolume/
404.html 50x.html index.html nginx-logo.png poweredby.png
docker stack
概述
- 早期使用service发布,每次只能发布一个service
- yaml可以发布多个服务,但是使用docker-compose只能在一台主机发布
- 借助docker swarm同时发布多服务
- 是docker生态service发布的最高层次
案例
- 远程管理docker host
- 监控docker host上运行的容器
[root@node01 ~]# vim docker-compose.yaml
version: '3'
services:
nginx:
image: nginx:alpine
ports:
- "8080:80"
deploy:
mode: replicated
replicas: 4
visualizer:
image: dockersamples/visualizer
ports:
- "9001:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
portainer:
image: portainer/portainer
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
docker stack 运行多服务
[root@node01 ~]# docker stack deploy -c docker-compose.yaml stack-demo
Creating network stack-demo_default
Creating service stack-demo_visualizer
Creating service stack-demo_portainer
Creating service stack-demo_nginx
[root@node01 ~]# docker stack ls
NAME SERVICES ORCHESTRATOR
stack-demo 3 Swarm
我这个选择是本地,如果选第二个就是远程需要修改daemon.json文件0.0.0.0:2379具体的可以看看上面的远程管理怎么配,第三个是代理,第四个好像的微软的玩意(我没玩过)
进来以后无脑点点点就完事了没啥好说了
文章评论