Docker之1---介绍和安装
Docker介绍
Docker是一个开源项目,让应用程序布署在软件货柜下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。
Docker利用Linux核心中的资源分离机制(例如cgroups)及Linux核心名字空间(namespaces),来创建独立的容器(containers)。
这可以在单一Linux实体下运作,避免启动一个虚拟机造成的额外负担。
Linux核心对名字空间的支持完全隔离了工作环境中应用程序的视野,包括进程树、网络、用户ID与挂载文件系统,而核心的cgroup提供资源隔离,包括CPU、存储器、block I/O与网络。从0.9版本起,Dockers在使用抽象虚拟是经由libvirt的LXC与systemd - nspawn提供界面的基础上,开始包括libcontainer库做为以自己的方式开0始直接使用由Linux核心提供的虚拟化的设施,
Dockers是有能力打包应用程序及其虚拟容器,可以在任何Linux服务器上运行的依赖性工具,这有助于实现灵活性和便携性,应用程序在任何地方都可以运行,无论是公有云、私有云、单机等。
什么是容器
容器是一种基础工具;泛指可以容纳其他物品的工具。可以部分或者完全封闭,被用于容纳、存储、运输物品;物体可以被放置在容器中,容器可以保护内容物。
人类使用容器的历史,至少有数十万乃至百万年。例如:瓶,罐,箱,篮,桶,杯。
容器技术出现的主要目的是为了"资源隔离"。
容器技术最早出现 FreeBASE jail -----> Linux vserver
- chroot -----> 完整的根文件系统(FHS)标准的
- namespaces -----> UTS Mount IPC PID user network
- cgroup -----> 资源的分配和监控
通过比较复杂的代码开发的过程,调用以上三项技术实现容器的创建 ----> 管理 ---->销毁
LXC (LinuX Container) :对于原有的常用功能进行了封装,方便我们做容器的生命周期 -----> Docker (dotcloud)
Docker是隔离环境中运行的一个进程,如果进程结束,Docker就会停止。
Docker的隔离环境,拥有自己的ip地址,系统文件,主机名,进程管理等。
程序:代码,软件,命令
进程:正在运行的程序
容器和虚拟机
开机启动流程:
- bios(basic input output system)开机自检
- 根据bios启动项,读取硬盘第一个扇区
- 操作系统的引导程序:grub,uefi
- 选择启动的操作系统:centos7
- 加载内核,硬件驱动,完成系统的初始化
- 启动系统第一个进程:/sbin/init(centos6),systemd(centos7)
虚拟机 | 容器 |
---|---|
硬件cpu支持(vt虚拟化),模拟计算硬件,走正常的开机启动,启动时间分钟级。 | 不需要硬件cpu的支持,共用宿主机内核,启动容器的第一个进程,启动时间秒级。 |
100虚拟机 | 100容器 |
100个服务 | 100个服务 |
10宿主机 | 6宿主机 |
对比项 | Docker | 对比结果 | 虚拟化 |
---|---|---|---|
快速创建、删除 | 启动应用 | >> | 启动Guest OS + 启动应用 |
交付、部署 | 容器镜像 | == | 虚拟机镜像 |
密度 | 单Node 100~1000 | >> | 单Node 10~100 |
更新管理 | 迭代式更新,修改Dockerfile,对增量内容进行分发,存储、传输、节点启动和恢复迅速 | >> | 向虚拟机推送安装、升级应用软件补丁包 |
稳定性 | 每月更新一个版本 | << | KVM,XEN,VMware都已经很稳定 |
安全性 | Docker具有宿主机root权限 | << | 硬件隔离:Guest OS运行在非根模式 |
监控成熟度 | 还在发展过程中 | << | Host,Hypervisor,VM的监控工具在生产环境已使用多年 |
高可用性 | 通过业务本身的高可用性来保证 | << | 武器库丰富:快照,克隆,HA,动态迁移,异地容灾,异地双活 |
管理平台成熟度 | 以K8S为代表,还在快速发展过程中 | << | 以OpenStack,vCenter,汉柏OPV-Suite为代表,已经在生产环境使用多年 |
什么是docker
Docker是通过内核虚拟化技术(namespaces及cgroups、cpu、内存、磁盘io等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率。
docker是一个C/S架构的软件打包器,属于一个进程,封装成一个镜像。
Docker优缺点
Docker优势:启动快,性能高,损耗少,轻量级
-
快速部署:可以在数秒内完成启动,短时间内可以部署成百上千个应用 ,更快速交付到线上 。
-
高效虚拟化:不需要额外的hypervisor支持,直接基于linux实现应用虚拟化,相比虚拟机大幅提高性能和效率。开销更小:不需要启动单独的虚拟机占用硬件资源。
-
节省开支:提高服务器利用率,降低IT支出 。资源利用率更高:一台物理机可以运行数百个容器,但是一般只能运行数十个虚拟机 。
-
简化配置:将运行环境打包保存至容器,使用时直接启动即可。
-
快速迁移和扩展:可跨平台运行在物理机、虚拟机、公有云等环境, 良好的兼容性可以方便将应用从A 宿主机迁移到B宿主机甚至是A平台迁移到B平台 。
Docker缺点:
- 隔离性:各应用之间的隔离不如虚拟机彻底 。
Docker底层技术
-
namespaces:名称空间(内核3.8版本之后才有,centos6 内核2.6版本)
用来隔离各个容器,可解决容器之间的冲突。
-
cgroups (Control Group):控制组
控制程序对资源的占用,资源统计,优先级分配,进程控制。
Linux Namespace
Linux Namespace提供了一种内核级别隔离系统资源的方法,通过将系统的全局资源放在不同的Namespace中,来实现资源隔离的目的。不同Namespace的程序,可以享有一份独立的系统资源。目前Linux中提供了六类系统资源的隔离机制,分别是:
-
Mount
: 隔离文件系统挂载点每个容器都要有独立的根文件系统,有独立的用户空间, 以实现在容器里启动服务,并且使用容器的运行环境。但是在容器里面不能访问宿主机的资源, 宿主机使用 chroot 技术把容器锁定到一个指定的运行目录里面 。例如:
/var/lib/containerd/io.containerd.runtime.v1.linux/容器ID
-
UTS
: 隔离主机名和域名信息UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息。用于系统标识,其中包含了hostname和域名domainname,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器 。
-
IPC
: 隔离进程间通信一个容器内的进程间通信允许一个容器内的不同进程的内存、缓存等数据访问,但是不能跨容器访问其他容器的数据 。
-
PID
: 隔离进程的IDLinux系统中,有一个PID为1的进程 init/systemd是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、器内的主进程生成与回收子进程等 )。
-
Network
: 隔离网络资源每一个容器都类似于虚拟机一样有自己的网卡、 监听 端口、TCP /IP 协议栈等。Docker使用network namespace 启动一个vethX接口,这样容器将拥有它自己的桥接ip地址,通常是docker0。而docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。
-
User
: 隔离用户和用户组的ID(内核3.8版本)
namespace | 系统调用参数 | 隔离内容 | 内核版本 |
---|---|---|---|
UTS | CLONE_NEWUTS | 主机名和域名 | 2.6.19 |
IPC | CLONE_NEWIPC | 信号量、消息队列和共享内存 | 2.6.19 |
PID | CLONE_NEWPID | 进程编号 | 2.6.24 |
Network | CLONE_NEWNET | 网络设备、网络栈、端口等 | 2.6.29 |
Mount | CLONE_NEWNS | 挂载点(文件系统) | 2.4.19 |
User | CLONE_NEWUSER | 用户和用户组 | 3.8 |
Linux Control Groups
用于限制一个进程组能够使用的资源上限,包括 CPU 、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起和恢复等操作。
一个容器 ,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug 程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配。
cgroups 具体实现:
blkio :块设备 IO 限制。
cpu :使用调度程序为 cgroup 任务提供 cpu 的访问。
cpuacct :产生 cgroup 任务的 cpu 资源报告。
cpuset :如果是多核心的 cpu ,这个子系统会为 cgroup 任务分配单独的 cpu 和内存。
devices :允许或拒绝 cgroup 任务对设备的访问。
freezer :暂停和恢复 cgroup 任务。
memory :设置每个 cgroup 的内存限制以及产生内存资源报告。
net_cls :标记每个网络包以供 cgroup 方便使用。
ns :命名空间子系统。
perf_event :增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的 group 的所有线程以及运行在特定 CPU 上的线程。
容器
容器规范OCI
Open Container Initiative 是围绕 容器格式 和 runtime 建立的开放式行业标准。
OCI由Docker和其他容器行业的领导者于2015年6月建立,目前包含两个规范:运行时规范(runtime-spec)和映像规范(image-spec)。运行时规范概述了如何运行在磁盘上解压缩的“文件系统包”。在较高级别上,OCI执行下载一个OCI映像,然后将该映像解压到 OCI runtime 文件系统包 中。此时,OCI runtime 文件系统包 将由 OCI runtime 运行。
有了这两个规范,不同的容器公司开发的容器,只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。
容器runtime
runtime 是真正运行容器的地方,为了运行不同的容器, runtime 需要和操作系统内核紧密合作相互支持 ,以便为容器提供相应的运行环境 。目前主流的三种 runtime:
-
Lxc
:linux上早期的 runtime。Docker 早期就是采用 Lxc 作为runtime。 -
runc
:目前 Docker 默认的 runtime。遵守OCI规范,可以兼容 lxc 。 -
rkt
:Core OS开发的容器 runtime。符合OCI规范 ,可以运行Docker容器。
容器管理工具
管理工具连接 runtime
与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给runtime执行 。
-
Lxd
的管理工具是Lxc
。 -
Runc
的管理工具是docker engine
也就是大家经常提到的Docker
,docker engine
包含后台deamon
和cli
两部分。 -
Rkt
的管理工具是rktcli
。
容器定义工具
容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建 。
Docker image
是docker
容器的模板,runtime
依据docker image
创建容器。
Docker file
是包含N个命令的文本文件,通过docker file
创建出``docker image `。
ACI(App container image)
:与 docker image
类似。是 Core OS
开发的rkt
容器的镜像格式。
LXC到Docker
- LXC,将原来需要手工编码实现的容器技术,进行了封装。实现了更加方便、快速的容器创建及管理的技术。通过固有“模板”,安装并启动容器。将远程的程序包下载到本地,安装并创建好我们需要的容器。
- 确实,LXC已经很大程度上降低了容器管理的难度,但是依然使用一些弊端。有些时候可能需要自定制模板,以及使用LXC中自带的模板,以及大规模创建及复制依然比较麻烦。所以,很难大规模的应用。
- 所以,出现了Docker技术。Docker是在LXC基础上,使用GoLang二次开发的封装版。
Docker组成
Docker 主机 (Host):一个物理机或虚拟机,用于运行Docker服务进程和容器。
Docker 服务端 (Server): Docker 守护进程, 运行Docker容器。
Docker 客户端 (Client):客户端使用Docker命令或其他工具调用Docker API 。
Docker 仓库 (Registry):保存镜像的仓库,类似于git或svn这样的版本控制系统。
Docker 镜像 (Images):镜像可以理解为创建实例使用的模板。
Docker 容器 (Container ): 容器是从镜像生成对外提供服务的一个或一组服务 。
docker-ce
docker版本发展:
docker 1.13版本(2013):
- docker-ce 社区版 17.03-19.03
- docker-ee 企业版
docker-ce安装
- 环境准备
主机名 | 配置 | IP |
---|---|---|
docker01 | 1核2g内存 | 10.0.0.11 |
docker02 | 1核2g内存 | 10.0.0.12 |
- 要求:内核 > 3.8
- 使用Base源和epel源
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
- 下载、安装、启动、开机自启
- 阿里云源
wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 清华源
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y
systemctl enable docker
systemctl start docker
- 验证
docker version
docker info
docker 镜像加速
docker-cn加速
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF
阿里云加速器
① 注册阿里云账号,专用加速器地址获得路径:
https://cr.console.aliyun.com/#/accelerator
② 添加加速器到配置文件
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
EOF
其他镜像加速
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://registry.docker-cn.com","https://hub-mirror.c.163.com","https://daocloud.io"]
}
EOF
使用中科大镜像
# 拉取官方镜像
docker pull xxx/yyy:zz
# 拉取中科大镜像
docker pull docker.mirrors.ustc.edu.cn/xxx/yyy:zz
# 拉取google镜像
docker pull gcr.io/xxx/yyy:zzz
# 拉取中科大镜像
docker pull gcr.mirrors.ustc.edu.cn/xxx/yyy:zzz
# 拉取kubernetes google镜像
docker pull k8s.gcr.io/xxx:yyy
docker pull gcr.io/google-containers/xxx:yyy
# 拉取中科大镜像
docker pull gcr.mirrors.ustc.edu.cn/google-containers/xxx:yyy
# 拉取quay.io镜像
docker pull quay.io/xxx/yyy:zzz
# 拉取中科大镜像
docker pull quay.mirrors.ustc.edu.cn/xxx/yyy:zzz
docker image 镜像
镜像搜索
docker search nginx
优先选择:
OFFICIAL
(官方),STARS
数量多的镜像。安全不带版本号默认 latest,也就是最新版本
镜像拉取(下载)
docker pull nginx:alpine
注意版本选择,版本请到Docker Hub查看
docker pull nginx:1.18-alpine
官方镜像 docker.io/library/nginx:1.18-alpine 用户镜像 docker.io/t29617342/alpine:3.9 国内镜像 index.tenxcloud.com/system_containers/metrics-server-amd64:v0.3.1
镜像推送(上传)
docker push 镜像名
默认上传至官方仓库,需要先登录
docker login
查看镜像列表
docker images
docker image ls
# 参数解释
REPOSITORY # 镜像所属的仓库名称
TAG # 镜像版本号(标识符) 默认为 latest
IMAGE ID # 镜像唯一ID标示
CREATED # 镜像创建时间
VIRTUAL SIZE # 镜像大小
镜像导出
docker save nginx:alpine -o docker_nginx_alpine.tar.gz
docker save 3556258649b2 > ./docker_nginx_alpine.tar.gz
- -o:指定导出镜像的位置;
- 可以同时导出多个镜像为一个文件;
- 指定 .tar.gz 可以导出并压缩。
镜像导入
docker load -i docker_nginx_alpine.tar.gz
docker load < docker_nginx_alpine.tar.gz
使用import导入的镜像没有仓库和标签,需要手动指定
docker import -i docker_nginx_alpine.tar.gz
镜像删除
docker rmi nginx:alpine
docker image rm 98ab35023fd6
docker rmi -f `docker image ls -q` # 强制删除所有镜像
镜像打标
docker tag 98ab35023fd6 nginx:v1
对同一个镜像可以指定多个标签,这样删除时仅删除标签。
清除无效镜像
docker image prune
比如:没有仓库和标签的镜像。
自动构建镜像
docker build --network=host -t REPOSITORY:TAG .
--network=host # 指定构建时使用宿主机的hosts文件
-t # 指定仓库:标签
注意:容器每次启动都会挂载新生成的
/etc/host
文件
查看镜像构建历史
docker history nginx:latest
查看镜像或容器信息
docker inspect nginx:v1
docker inspect 98ab35023fd6
docker inspect -f "{{.NetworkSettings.IPAddress}}" f625e984b18d # 查看容器IP
docker inspect -f "{{.NetworkSettings.Gateway}}" f625e984b18d # 查看容器网关
docker inspect -f "{{.State.Pid}}" f625e984b18d # 查看容器PID号
docker inspect -f "{{.HostConfig.NetworkMode}}" f625e984b18d # 查看容器网络模式
docker inspect f625e984b18d | grep IPAddress
docker inspect f625e984b18d | grep Gateway
docker inspect f625e984b18d | grep Pid
docker inspect f625e984b18d | grep NetworkMode
docker inspect f625e984b18d | grep -A 1 Networks
nsenter
- 安装 nsenter
yum install util-linux -y
- 查看容器PID号
docker inspect -f "{{.State.Pid}}" f625e984b18d
- nsenter 进入容器
nsenter -t 容器PID -m -u -i -n -p # 根据容器PID号进入到容器中
- 脚本:进入容器(k8s中常用)
# vim docker_in.sh
# usage: docker_in.sh CONTAINERID
# ie: docker_in.sh 14fa729e9d46
#!/bin/bash
docker_in(){
NAME_ID=$1
PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})
nsenter -t ${PID} -m -u -i -n -p
}
docker_in $1
docker container 容器
创建并启动容器
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
docker run -d -p 80:80 --name="nginx" nginx:latest
docker run -it -d centos:7
docker run -it nginx:alpine /bin/sh
run # 创建并启动一个容器
-d # 放后台运行
-p # 端口映射,将容器内服务的端口映射在宿主机的指定端口
nginx:latest # docker镜像名称
--name # 指定容器名
--network # 指定网络类型
--dns # 指定DNS
--rm # 容器停止,自动删除
--dns 223.5.5.5 # 指定容器dns
-i # 交互式访问
-t # 分配一个交换式的终端,和-d同用放后台
-e # 设置环境变量
--privileged=true # 授予此容器扩展权限,可以修改内核参数
--restart always # docker服务启动时启动容器
--link # 单向链接正在运行的容器,hosts文件中添加主机名/别名解析
-h # 指定容器的主机名
--memory 50M # 限制内存
docker run = docker create + docker start
注:容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会秒退!
创建容器
docker create nginx:latest
docker create --name oldboy nginx:latest
根据镜像创建容器,没有镜像会去源下载,还没有会报错
启动容器
Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
- -a:附加到当前终端
- -i:交互式
docker start df06c5d211e4
docker start oldboy
docker start `docker ps -a -q` # 开启所有容器
停止容器
docker stop df06c5d211e4
docker stop oldboy
docker stop `docker ps -a -q` # 停止所有容器
重启容器
docker restart df06c5d211e4
docker restart oldboy
docker restart `docker ps -a -q` # 重启所有容器
强制停止容器
docker kill df06c5d211e4
docker kill oldboy
docker kill `docker ps -a -q` # 强制停止所有容器
查看容器列表
docker ps
docker container ls -a # -a 查看所有容器列表,默认只显示运行的容器
docker ps -a
docker ps -q # -q 只显示IMAGE ID(sha256:64位的号码,默认只截取12位)
docker ps --no-trunc # 不截断IMAGE ID输出
docker ps -f status=exited # 查看退出的状态的容器
docker ps -l # 查看最后创建的容器
重名名容器
docker rename oldboy oldboy01
删除容器
docker rm
docker rm -f `docker ps -a -q` # 强制删除所有容器
docker rm -fv `docker ps -aq -f status=exited` # 强制删除所有退出状态的容器
清除停止容器
docker container prune
进入正在运行的容器
docker exec -it 容器id/容器名字 /bin/sh(/bin/bash) # 分配一个新终端
docker exec -it centos:7 ls # 免交互执行命令
docker attach centos:7 # 使用同一个终端,将后台运行的终端调用到前台
容器想要放在后台一直运行,那么容器的初始命令,必须夯住(前台运行),否则容器就会退出.
nginx -g 'daemon off;' # 指定全局选项:关闭守护进程,在前台运行 /usr/sbin/php-fpm --nodaemonize # 在前台运行
- 退出容器:
exit
- 偷偷离开容器,容器不退出:
ctrl+q,p
查看容器日志
docker logs d9e3ab321e18
-t # 显示时间戳
-f # 跟踪日志输出
--tail N # 仅列出最新N条容器日志
注意:
ln -s /dev/stdout /var/log/nginx/access.log
查看容器进程
docker top d9e3ab321e18
更新容器选项
docker update --restart always 6d0a073d0b50
docker update --memory 50M --memory-swap 50M
提交容器为镜像
docker commit 6d0a073d0b50 test:v2
导出容器到归档文件镜像:
没有名字、标签及构建历史,所有层合并为一层,只能用import导入。
docker export 6d0a073d0b50 > docker_test.tar.gz
比较容器不同
docker diff 6d0a073d0b50
挂起容器
docker pause 6d0a073d0b50
取消挂起容器
docker unpause 6d0a073d0b50
统计容器资源
docker stats --no-stream
--no-stream # 不动,不刷新
Docker端口映射
docker run # docker 会自动添加一条iptables规则来实现端口映射
-p hostPort:containerPort # 指定宿主机端口映射容器端口
-p ip:hostPort:containerPort # 指定IP端口映射
-p containerPort # 随机端口映射
-p ip::containerPort(随机端口:32768-60999) # 指定IP随机端口映射
-p hostPort:containerPort/udp # 使用udp协议指定IP随机端口映射
-p 80:80 -p 3306:3306 # 多次复用
-p 1111-1119:1111-1119 # 端口范围映射
-P # 自动随机端口映射
查看容器端口映射
docker port 容器ID/容器名
Docker数据卷
挂载数据卷
docker run -v 宿主机绝对路径:容器绝对路径 # 挂载宿主机的路径到容器中,可复用
docker run -v 容器目录 # 创建一个随机卷,来持久化容器的目录下的数据
docker run -v 卷名:容器目录 # 创建一个固定名字的卷,来持久化容器的目录下的数据
docker run --volumes-from 指定容器 # 挂载和指定容器相同的所有卷
可用于代码上线 nginx 静态资源共享等,类似于NFS,可以实现容器间数据共享。
复制文件
在容器和本地文件系统之间复制文件/文件夹
docker cp [OPTIONS] 容器:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- 容器:DEST_PATH
查看卷列表
docker volume ls
卷存储在:
/var/lib/docker/volume
练习:只启动一个nginx容器,要求访问80端口,出现nginx默认欢迎首页;访问81端口,出现小鸟飞飞。
cat > /root/xiaoniao.conf << EOF server { listen 81; server_name localhost; location / { root /code; index index.html index.htm; } } EOF
docker run -d -p 80-81:80-81 -v /root/xiaoniaofeifei:/code -v /root/xiaoniao.conf:/etc/nginx/conf.d/xiaoniao.conf --name xiaoniao nginx:latest
验证:
- 监听端口80 81
docker ps -l -a
- 浏览器双窗口检查
docker system
docker system df # 统计docker-ce使用磁盘空间
docker system prune # 清理停止的容器,未使用的网卡,无名的镜像和构建缓存
docker system info # 查看docker-ce信息
docker system even # 查看docker-ce事件
关闭docker服务,不关闭容器
cat > /etc/docker/daemon.json <<EOF
{
"live-restore": true
}
EOF
Docker服务进程
查看docker进程,了解docker的运行及工作方式
[root@docker01 ~]# pstree -p
systemd(1)─┬─VGAuthService(816)
├─abrt-watch-log(837)
├─abrtd(832)
├─agetty(848)
├─auditd(759)───{auditd}(760)
├─containerd(1390)─┬─containerd-shim(2053)─┬─bash(2069)
│ │ ├─{containerd-shim}(2054)
│ │ ├─{containerd-shim}(2055)
│ │ ├─{containerd-shim}(2056)
│ │ ├─{containerd-shim}(2057)
│ │ ├─{containerd-shim}(2058)
│ │ ├─{containerd-shim}(2059)
│ │ ├─{containerd-shim}(2061)
│ │ └─{containerd-shim}(2087)
│ ├─{containerd}(1424)
│ ├─{containerd}(1425)
│ ├─{containerd}(1426)
│ ├─{containerd}(1433)
│ ├─{containerd}(1434)
│ ├─{containerd}(1448)
│ ├─{containerd}(1452)
│ ├─{containerd}(1946)
│ └─{containerd}(1949)
├─crond(841)
├─dbus-daemon(820)
├─dockerd(1451)─┬─{dockerd}(1519)
│ ├─{dockerd}(1520)
│ ├─{dockerd}(1521)
│ ├─{dockerd}(1533)
│ ├─{dockerd}(1537)
│ ├─{dockerd}(1538)
│ ├─{dockerd}(1543)
│ ├─{dockerd}(1559)
│ └─{dockerd}(1969)
containerd进程关系
四个进程:
- containerd:被dockerd进程调用以实现与runc交互,其父进程为宿主机的systemd守护进程 。
- dockerd:被client直接访问,其父进程为宿主机的systemd守护进程 。
- containerd-shim:真正运行容器的载体,其父进程为containerd。
- docker-proxy:实现容器通信,其父进程为dockerd。
容器的创建与管理过程
通信流程:
- dockerd通过grpc和containerd模块通信,dockerd由libcontainerd负责和containerd进行交换,dockerd和containerd通信socket文件:/run/containerd/containerd.sock 。
- containerd在dockerd启动时被启动,然后containerd启动grpc请求监听,containerd 处理grpc请求,根据请求做相应动作。
- 若是start或是exec容器,containerd拉起一个container-shim,并进行相应的操作。
- container-shim被拉起后,start/exec/create拉起runC进程,通过 exit、control 文件和containerd通信,通过父子进程关系和SIGCHLD监控容器中进程状态。
- 在整个容器生命周期中,containerd通过epoll监控容器文件,监控容器事件。
手动制作Docker镜像
基于centos7系统的nginx镜像(单服务)
- 启动一个纯净的centos:7容器并进入
docker run -it -p 80:80 centos:7
- nginx 安装 修改首页
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install nginx -y
rm -rf /usr/share/nginx/html/index.html
echo "nginx" > /usr/share/nginx/html/index.html
exit
- 把安装好服务的容器,提交为镜像
docker commit a74fae23b022 centos7_nginx:v1
- 测试镜像的功能
docker run -d -p 80:80 centos7_nginx:v1 nginx -g 'daemon off;'
curl -I 10.0.0.11
基于centos7系统的sshd镜像(单服务)
- 启动一个纯净的centos:7容器并进入
docker run -it -p 100:22 centos:7
- sshd initscripts 安装 启动
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install initscripts openssh-server -y
/usr/sbin/sshd-keygen
echo '1'|passwd --stdin root
exit
- 把安装好服务的容器,提交为镜像
docker commit c83d838df822 centos7_sshd:v1
- 测试镜像的功能
docker run -d -p 100:22 centos7_sshd:v1 /usr/sbin/sshd -D
docker ps -al
ssh 10.0.0.11 -p100
基于centos7系统的支持ssh登录的nginx镜像(多服务)
- 启动一个纯净的centos:7容器并进入
docker run -it -p 100:22 -p 80:80 centos:7
- nginx sshd initscripts 安装 启动
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum install nginx initscripts openssh-server -y
/usr/sbin/sshd-keygen
rm -rf /usr/share/nginx/html/index.html
echo "nginx" > /usr/share/nginx/html/index.html
cat > init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
nginx
/usr/sbin/sshd -D
EOF
chmod +x init.sh
exit
- 把安装好服务的容器,提交为镜像
docker commit 32364fd2b78f centos7_nginx_sshd:v1
- 测试镜像的功能
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns centos7_nginx_sshd:v1 /init.sh
docker top cns
curl -I 10.0.0.11
docker ps -al
rm -rf .ssh/known_hosts
ssh 10.0.0.11 -p100
基于centos7系统的kod网盘镜像(多服务)
- 启动一个centos7_nginx_sshd:v1 并进入
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns centos7_nginx_sshd:v1 /init.sh
docker exec -ti `docker ps -lq` /bin/bash
- 安装
cat > init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
nginx
/usr/sbin/php-fpm -D
/usr/sbin/sshd -D
EOF
chmod +x init.sh
echo "192.168.15.253 mirrors.aliyun.com" >> /etc/hosts
yum install php-fpm php-gd php-mbstring unzip -y
mkdir /code && cd /code
curl -o /code/kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip
unzip -d /code/html kodexplorer4.40.zip
chown -R nginx:nginx /code
sed -i 's/= apache/= nginx/g' /etc/php-fpm.d/www.conf
sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
cat > /etc/nginx/conf.d/kod.conf <<-EOF
server {
listen 80;
server_name kod.oldboy.com;
root /code/html;
index index.php index.html;
client_max_body_size 100m;
location / {
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
}
EOF
exit
- 把安装好服务的容器,提交为镜像
docker stop `docker ps -lq`
docker commit `docker ps -lq` kod:v1
- 测试镜像的功能
docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns kod:v1 /init.sh
基于centos7系统的LNMP架构wordpress镜像(多服务)
- 启动一个纯净的centos:7容器并进入
docker run -it -p 100:22 -p 80:80 centos:7
docker cp /opt/dockerfile/lnmp_wordpress/latest-zh_CN.tar.gz `docker ps -lq`:/root
- 安装
cat > init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
/usr/libexec/mariadb-prepare-db-dir
/usr/bin/mysqld_safe --basedir=/usr &
/opt/remi/php72/root/usr/sbin/php-fpm -D
nginx
sleep 2
mysql -e 'CREATE DATABASE wordpress;GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost" IDENTIFIED BY "1";FLUSH PRIVILEGES;'
/usr/sbin/sshd -D
EOF
chmod +x init.sh
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install nginx initscripts openssh-server php72-php-fpm php72-php-mysqlnd mariadb-server -y && yum clean all && rm -rf /var/cache/yum/*
/usr/sbin/sshd-keygen && mkdir /code && cd /code
mv /root/latest-zh_CN.tar.gz .
tar xf latest-zh_CN.tar.gz && rm -f latest-zh_CN.tar.gz && chown -R nginx:nginx /code && sed -i 's/= apache/= nginx/g' /etc/opt/remi/php72/php-fpm.d/www.conf && sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
cat > /etc/nginx/conf.d/wordpress.conf <<-EOF
server {
listen 80;
server_name wordpress.oldboy.com;
root /code/wordpress;
index index.php index.html;
client_max_body_size 100m;
location / {
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
}
EOF
exit
- 把安装好服务的容器,提交为镜像
docker stop `docker ps -lq`
docker commit `docker ps -lq` lnmp_wp:v1
- 测试镜像的功能
docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" lnmp_wp:v1 /init.sh
自动制作Docker镜像
Docker镜像:中药
dockerfile: 配方
dockerfile常用指令
FROM
:指定使用的基础镜像,制作基础镜像FROM scratch
RUN
:制作镜像过程中需要的执行命令(安装服务)CMD
:容器启动的时候执行的初始命令,容易被替换(启动服务)ENTRYPOINT
:容器启动的时候执行的初始命令,不能被替换,如果同时使用CMD和ENTRYPOINT,CMD命令将作为ENTRYPOINT命令的参数ADD
:把dockerfile当前目录下的文件拷贝到容器中(自动解压tar包),可使用URL作为源,制作基础镜像COPY
:把dockerfile当前目录下的文件拷贝到容器中(不解压tar包),支持统配符,拷贝目录,只拷贝目录下的子文件、子目录。WORKDIR
:指定容器的默认工作目录EXPOSE
:镜像监听的端口,run -P 使用VOLUME
:持久化卷ENV
:环境变量(ssh的密码,数据库的密码)STOPSIGNAL
:设置将被发送到容器退出的系统调用信号。该信号可以是内核syscall表中的有效无符号数字(例如9),也可以是SIGNAME格式的信号名称(例如SIGKILL)。HEALTHCHECK
:健康检查机制- --interval 间隔时间,每隔10秒执行一次脚本
- --timeout 脚本执行超时时间
- --retries 脚本失败次数,3次失败,即30秒之后,标记容器为unhealthy
LABEL
: 镜像的属性标签MAINTAINER
:维护者标签
自动构建镜像思路
-
手动制作docker镜像,记录历史命令
-
根据历史命令编写
dockerfile
文件 -
docker build
构建docker镜像docker build --network=host -t REPOSITORY:TAG .
-
测试镜像的功能
dockerfile单服务
mkdir -p /opt/dockerfile/centos7_nginx
cat > /opt/dockerfile/centos7_nginx/Dockerfile <<EOF
FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install nginx -y
RUN rm -rf /usr/share/nginx/html/index.html
RUN echo "nginx" > /usr/share/nginx/html/index.html
WORKDIR /root
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
EOF
docker build --network=host -t centos7_nginx:v2 /opt/dockerfile/centos7_nginx/
docker run -d -p 80:80 centos7_nginx:v2
docker ps -al
curl -I 10.0.0.11
dockerfile多服务
mkdir -p /opt/dockerfile/kod
cat > /opt/dockerfile/kod/init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
nginx
/usr/sbin/php-fpm -D
/usr/sbin/sshd -D
EOF
cat > /opt/dockerfile/kod/kod.conf <<-EOF
server {
listen 80;
server_name kod.oldboy.com;
root /code/html;
index index.php index.html;
client_max_body_size 100m;
location / {
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
}
EOF
wget -O /opt/dockerfile/kod/kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip
cat > /opt/dockerfile/kod/Dockerfile <<EOF
FROM centos7_nginx_sshd:v1
RUN yum install php-fpm php-gd php-mbstring unzip -y
RUN mkdir /code
WORKDIR /code
ADD init.sh /init.sh
ADD kod.conf /etc/nginx/conf.d/kod.conf
ADD kodexplorer4.40.zip /code/kodexplorer4.40.zip
RUN unzip -d /code/html kodexplorer4.40.zip
RUN rm -rf /code/kodexplorer4.40.zip
RUN sed -i 's/= apache/= nginx/g' /etc/php-fpm.d/www.conf
RUN sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf
RUN chown -R nginx:nginx /code
RUN chmod +x /init.sh
ENV SSH_PASS 1
EXPOSE 22 80
CMD ["/bin/bash","/init.sh"]
EOF
docker build --network=host -t kod:v2 /opt/dockerfile/kod/
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=123" --name=cns kod:v2
dockerfile基础镜像
mkdir -p /opt/dockerfile/base
wget -O /opt/dockerfile/base/rootfs.tar.xz https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/alpine/3.10/amd64/default/20201130_13%3A00/rootfs.tar.xz
cat > /opt/dockerfile/base/Dockerfile <<EOF
FROM scratch
ADD rootfs.tar.xz /
CMD ["/bin/sh"]
EOF
docker build -t alpine_base:v1 /opt/dockerfile/base/
docker run -it alpine_base:v1
dockerfile的wordpress镜像
docker run -it -p 100:22 -p 80:80 centos:7
mkdir -p /opt/dockerfile/lnmp_wordpress/repo
cd /opt/dockerfile/lnmp_wordpress/repo
wget http://mirrors.aliyun.com/repo/Centos-7.repo http://mirrors.aliyun.com/repo/epel-7.repo https://cn.wordpress.org/latest-zh_CN.tar.gz
cat > /opt/dockerfile/lnmp_wordpress/repo/MariaDB.repo <<EOF
[mariadb]
name=MariaDB
baseurl=https://mirrors.ustc.edu.cn/mariadb/yum/10.5/centos7-amd64/
gpgcheck=0
enabled=1
EOF
cat > /opt/dockerfile/lnmp_wordpress/repo/wordpress.conf <<-EOF
server {
listen 80;
server_name wordpress.oldboy.com;
root /code/wordpress;
index index.php index.html;
client_max_body_size 100m;
location / {
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
}
EOF
cat > /opt/dockerfile/lnmp_wordpress/repo/init.sh <<-EOF
#!/bin/bash
echo "\$SSH_PASS"|passwd --stdin root
/usr/libexec/mariadb-prepare-db-dir
/usr/bin/mysqld_safe --basedir=/usr &
/opt/remi/php72/root/usr/sbin/php-fpm -D
nginx
sleep 2
mysql -e 'CREATE DATABASE wordpress;GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost" IDENTIFIED BY "1";FLUSH PRIVILEGES;'
/usr/sbin/sshd -D
EOF
cat > /opt/dockerfile/lnmp_wordpress/Dockerfile <<EOF
FROM centos:7
COPY repo /etc/yum.repos.d/
RUN yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm && \
yum install nginx initscripts openssh-server php72-php-fpm php72-php-mysqlnd mariadb-server -y && \
yum clean all && \
rm -rf /var/cache/yum/* && \
/usr/sbin/sshd-keygen && \
mkdir /code && cd /code && \
mv /etc/yum.repos.d/latest-zh_CN.tar.gz . && \
tar xf latest-zh_CN.tar.gz && \
rm -f latest-zh_CN.tar.gz && \
chown -R nginx:nginx /code && \
sed -i 's/= apache/= nginx/g' /etc/opt/remi/php72/php-fpm.d/www.conf && \
sed -i '38,57s/^/#/g' /etc/nginx/nginx.conf && \
mv /etc/yum.repos.d/wordpress.conf /etc/nginx/conf.d/wordpress.conf && \
mv /etc/yum.repos.d/init.sh /init.sh && \
chmod +x init.sh
CMD ["/init.sh"]
EOF
docker build -t lnmp_wp:v1 /opt/dockerfile/lnmp_wordpress/
docker rm -f `docker ps -aq`
docker run -d -p 100:22 -p 80:80 -e "SSH_PASS=1" --name=cns lnmp_wp:v1 /init.sh
Docker镜像的分层
Dokcer镜像含有启动容器所需要的文件系统及其内容,用于创建并启动docker容器。
Dokcer镜像采用分层构建机制,最底层为Bootfs,之上为rootfs,再额外挂载"可写"层。
-
bootfs
:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载,以节约内存资源; -
rootfs
:位于bootfs之上,表现为docker容器的根文件系统;由内核挂载为“只读”模式 -
"可写"层
:通过UnionFS(联合文件系统)额外挂载的一个"可写"层;"可写"层之间通过parent文件中存放的父层sha256关联。
[root@docker01 ~]# tree /var/lib/docker/image/ /var/lib/docker/image/ `-- overlay2 # 存储驱动 |-- distribution |-- imagedb # 镜像文件 | |-- content | | `-- sha256 | | `-- aa88f087d1bcf434df7494c64931fec52782e8aa4041959bc51ee9d6bd5cdc49 | `-- metadata | `-- sha256 | |-- 7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd | | `-- parent # 父sha256 | `-- fdb81b0740bdb34e37846eb4ded59fd1a243db356d2d309ccd51e9b0a75ad56f | `-- parent |-- layerdb | |-- mounts | | `-- d1c6a7f266126296b12ddc79ef8d26ccadd4a43f15b7f54f635239ecbdf9b09d | | |-- init-id | | |-- mount-id | | `-- parent | |-- sha256 | | |-- d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854 | | | |-- cache-id | | | |-- diff | | | |-- size | | | `-- tar-split.json.gz | | `-- fe986c7da4b1268db8eccd9cce00f27565eb3c574d6353e8d4309c2cc68fa27d | | |-- cache-id | | |-- diff # 相对于父层的不同 | | |-- parent # 父层sha256 | | |-- size | | `-- tar-split.json.gz | `-- tmp `-- repositories.json [root@docker01 ~]# cat /var/lib/docker/image/overlay2/layerdb/sha256/fe986c7da4b1268db8eccd9cce00f27565eb3c574d6353e8d4309c2cc68fa27d/parent sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854 [root@docker01 ~]# cat /var/lib/docker/image/overlay2/imagedb/metadata/sha256/fdb81b0740bdb34e37846eb4ded59fd1a243db356d2d309ccd51e9b0a75ad56f/parent sha256:7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd [root@docker01 ~]# cat /var/lib/docker/image/overlay2/imagedb/metadata/sha256/7bad8e5e960f912d37ab8f7c910cbbd228129da3b0489ec885cafbd7b28ad6dd/parent sha256:aa88f087d1bcf434df7494c64931fec52782e8aa4041959bc51ee9d6bd5cdc49
docker image layer
- 位于下层的镜像成为父镜像,最底层的成为基础镜像
- 最上层为可读写层,其下的均为只读层;
镜像构建过程
新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
Docker镜像的分层实现了资源共享,节省占用空间。
Docker存储驱动
-
Docker默认存储驱动为
overlay2
,需要磁盘分区支持d_type
文件分层功能 ,因此需要系统磁盘的额外支持。官方文档/var/lib/docker/overlay2
-
Docker官方推荐首选存储驱动为overlay2,其次为devicemapper。但是devicemapper存在使用空间方面的一些限制, 虽然可以通过后期配置解决,但是官方依然推荐使用overlay2。
注意:
如果docker数据目录是一块单独的xfs格式的磁盘分区,那么需要在格式化时加上参数
-n ftype=1
,否则后期在启动容器的时候会报错不支持d_type
。centos7.2 版本后默认
ftype=1
[root@docker01 ~]# xfs_info / meta-data=/dev/mapper/centos-root isize=512 agcount=4, agsize=1232128 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=4928512, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
dockerfile的优化
优化原则:构建速度尽可能快,镜像体积尽可能小
-
使用小体积镜像:alpine > debian > ubuntu > centos
-
尽量减少中间图层(仅RUN,COPY和ADD指令创建图层)
FROM ubuntu:18.04 COPY . /app RUN make /app CMD python /app/app.py
-
利用构建缓存:修改dockerfile时,尽可能把修改的内容放在最后
-
使用
.dockerignore
文件,构建docker镜像时,排除当前目录下不需要的文件cat > .dockerignore <<-EOF filename EOF
容器间的互联
即在同一个宿主机上的容器之间,可以通过自定义的容器名称相互访问 。
docker run --link 容器名:容器别名(单向指定,正在运行)
zabbix容器部署
https://www.zabbix.com/documentation/4.0/zh/manual/installation/containers
docker run --name mysql-server -it \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-d mysql:5.7 \
--character-set-server=utf8 --collation-server=utf8_bin
docker run --name zabbix-java-gateway -t \
-d zabbix/zabbix-java-gateway:latest
docker run --name zabbix-server-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
--link mysql-server:mysql \
--link zabbix-java-gateway:zabbix-java-gateway \
-p 10051:10051 \
-d zabbix/zabbix-server-mysql:latest
docker run --name zabbix-web-nginx-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
--link mysql-server:mysql \
--link zabbix-server-mysql:zabbix-server \
-p 80:80 \
-d zabbix/zabbix-web-nginx-mysql:latest
wordpress容器部署
docker run --name mysql-server-wp -it \
-e MYSQL_DATABASE="wordpress" \
-e MYSQL_USER="wordpress" \
-e MYSQL_PASSWORD="1" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-d mysql:5.7 \
--character-set-server=utf8 --collation-server=utf8_bin
docker run --name wordpress -p 81:80 \
--link mysql-server-wp:mysql \
-e WORDPRESS_DB_NAME=wordpress \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_PASSWORD=1 \
-d wordpress:latest
docker-compose 单机版容器编排
Compose是一个用于定义和运行多容器Docker应用程序的工具。使用Compose,您可以使用Compose文件来配置应用程序的服务。然后,使用单个命令,您可以从配置中创建并启动所有服务。
Compose非常适合开发,测试和登台环境以及CI工作流程。
(1)使用Compose基本上是一个三步过程
- 定义您的应用程序环境 Dockerfile,以便可以在任何地方进行复制。
- 定义构成应用程序的服务 docker-compose.yml,以便它们可以在隔离环境中一起运行。
- 最后,运行docker-compose up,Compose将启动并运行整个应用程序。
(2)docker-compose.yml 示例: Compose文件参考
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: redis
(3)Compose具有管理应用程序整个生命周期的命令:
- 启动,停止和重建服务
- 查看正在运行的服务的状态
- 流式传输运行服务的日志输出
- 在服务上运行一次性命令
(4)Docker Compose 升级
如果从Compose 1.2或更早版本升级,请在升级Compose后删除或迁移现有容器。因为从1.3版本开始,Compose使用Docker标签来跟踪容器,并且需要重新创建容器以添加标签。
如果Compose检测到没有标签创建的容器,它将拒绝运行,您最终不会使用两组。如果要继续使用现有容器(例如,因为它们具有要保留的数据卷),可以使用Compose 1.5.x使用以下命令迁移它们:
docker-compose migrate-to-labels
或者,如果您不担心保留它们,可以将它们删除。撰写只是创建新的。
docker container rm -f -v myapp_web_1 myapp_db_1 ...
安装
- Docker Compose 依靠 Docker Engine 工作。
要以非root用户身份运行Compose,请参阅以非root用户身份管理Docker。
- yum安装依赖epel源
yum install docker-compose -y
批量创建并启动
docker-compose up -d
-d # 后台启动
以目录分隔组,只读取当前目录下的 docker-compose.yml、docker-compose.yaml 文件
批量停止并删除
docker-compose down
批量启动
docker-compose start
批量停止
docker-compose stop
批量重启
docker-compose restart
指定批量规模
docker-compose scale zabbix-java-gateway=2
zabbix容器批量部署yml
mkdir -p /opt/docker-compose/zabbix && cd /opt/docker-compose/zabbix
cat > /opt/docker-compose/zabbix/docker-compose.yml <<EOF
version: '3'
services:
mysql-server:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_pwd
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_pwd
command: --character-set-server=utf8 --collation-server=utf8_bin
zabbix-java-gateway:
image: zabbix/zabbix-java-gateway:latest
restart: always
zabbix-server:
depends_on:
- mysql-server
image: zabbix/zabbix-server-mysql:latest
restart: always
environment:
DB_SERVER_HOST: mysql-server
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_pwd
MYSQL_ROOT_PASSWORD: root_pwd
ZBX_JAVAGATEWAY: zabbix-java-gateway
ports:
- "10051:10051"
zabbix-web-nginx-mysql:
depends_on:
- zabbix-server
image: zabbix/zabbix-web-nginx-mysql:latest
ports:
- "80:80"
restart: always
environment:
DB_SERVER_HOST: mysql-server
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_pwd
MYSQL_ROOT_PASSWORD: root_pwd
EOF
wordpress容器批量部署yml
mkdir -p /opt/docker-compose/wordpress && cd /opt/docker-compose/wordpress
cat > /opt/docker-compose/wordpress/docker-compose.yml <<EOF
version: '3'
services:
mysql:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_pwd
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: 1
command: --character-set-server=utf8 --collation-server=utf8_bin
wordpress:
depends_on:
- mysql
image: wordpress:latest
volumes:
- wordpress_files:/var/www/html
ports:
- "81:80"
restart: always
environment:
DB_SERVER_HOST: mysql
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: 1
volumes:
wordpress_files:
db_data:
EOF
registry 私有仓库
启动私有仓库
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry
上传镜像
docker 解析镜像名指定上传路径,所以首先必须指定标签
docker tag alpine:3.9 10.0.0.11:5000/alpine:3.9
docker push 10.0.0.11:5000/alpine:3.9
注意:
默认使用https协议上传,若使用http协议会报错,修改配置文件,指定信任地址,重启docker服务。
cat > /etc/docker/daemon.json <<EOF { "registry-mirrors": ["https://registry.docker-cn.com"], "insecure-registries": ["10.0.0.11:5000"] } EOF systemctl restart docker
下载镜像
docker pull 10.0.0.11:5000/alpine:3.9
私有仓库操作
查看私有仓库镜像列表:http://10.0.0.11:5000/v2/_catalog
查看私有仓库镜像版本:http://10.0.0.11:5000/v2/alpine/tags/list
删除私有仓库镜像
- 进入docker registry容器中
docker exec -it registry /bin/sh
- 删除私有仓库镜像目录
rm -fr /var/lib/registry/docker/registry/v2/repositories/alpine
- 清除无用私有仓库镜像blob
registry garbage-collect /etc/docker/registry/config.yml
使用安全认证
- 生成密码
yum install httpd-tools -y
mkdir /opt/registry-auth/ -p
htpasswd -Bbn oldguo 123 > /opt/registry-auth/htpasswd
- 重新启动带有秘钥功能的registry容器
docker rm -f `docker ps -aq`
docker run -d -p 5000:5000 -v /opt/registry-auth/:/auth/ -v /opt/registry:/var/lib/registry --name register-auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry
- 上传下载镜像,需要先login
[root@docker02 ~]# docker login 10.0.0.100:5000
Username: oldguo
Password:
harbor 企业级私有仓库
Harbor介绍
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器, 由vmware中国分公司开源,其通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。Harbor提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。 Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry 中,确保数据和知识产权在公司内部网络中管控。
- Harbor是一个开源的可信云本机注册表项目,用于存储,签名和扫描内容。Harbor通过添加用户通常需要的功能(如安全性,身份和管理)来扩展开源Docker Distribution。
- Harbor Gitlab由Cloud Native Computing Foundation(CNCF)托管。
Harbor功能
-
基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。
-
基于策略的镜像复制:可以基于具有多个过滤器(存储库,标记和标签)的策略在多个注册表实例之间复制(同步)映像。如果遇到任何错误,Harbor将自动重试进行复制。非常适合负载平衡,高可用性,多数据中心,混合和多云场景。
-
图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker 镜像仓库,管理项目和命名空间。
-
AD/LDAP支持:Harbor与现有企业LDAP / AD集成以进行用户身份验证和管理,并支持将LDAP组导入Harbor并为其分配适当的项目角色。
-
审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
-
国际化:已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。
-
RESTful API :提供给管理员对于 Harbor 更多的操控 , 使得与其它管理软件集成变得更容易。
-
部署简单:提供在线和离线两种安装工具,也可以安装到vSphere平台(OVA方式)虚拟设备。
-
云本机注册表:Harbour 支持容器映像和Helm图表,可用作云本机环境(如容器运行时和业务流程平台)的注册表。
-
漏洞扫描:Harbor定期扫描图像并警告用户漏洞。
-
镜像删除和垃圾收集:可以删除镜像,并可以回收它们的空间。
-
公证:可以确保图像的真实性。
安装
cd /opt
wget https://github.com/goharbor/harbor/releases/download/v1.10.6/harbor-offline-installer-v1.10.6.tgz
- 解压
tar xf harbor-offline-installer-*.tgz
- 安装依赖
docker-ce
17.06.0 +docker-compose
1.18.0+
yum install docker-ce docker-compose -y
- 创建并修改配置文件,设置主机IP和密码,注释https
cp /opt/harbor/harbor.yml.tmpl /opt/harbor/harbor.yml
vim /opt/harbor/harbor.yml
hostname: 10.0.0.12
... ...
#https:
# # https port for harbor, default is 443
# port: 443
# # The path of cert and key files for nginx
# certificate: /your/certificate/path
# private_key: /your/private/key/path
... ...
harbor_admin_password: 123456
- 执行安装脚本
- 执行前80端口不能被占用!!!
harbor/install.sh
- 注意:管理使用docker-compose
cd /opt/harbor
docker-compose stop
docker-compose start
- 设置开机启动
cat >> /etc/rc.d/rc.local <<EOF
cd /opt/harbor && docker-compose start
EOF
chmod +x /etc/rc.d/rc.local
http上传镜像
- 设置http信任,重启docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"insecure-registries": ["10.0.0.12"]
}
EOF
systemctl restart docker
- 登录harbor,用户名:admin,密码:123456
docker login 10.0.0.12
密码保存在
/root/.docker/config.json
文件中
- 指定标签,上传镜像
docker tag alpine:3.9 10.0.0.12/library/alpine:3.9
docker push 10.0.0.12/library/alpine:3.9
- 登录网页http://10.0.0.12查看
使用https
- 修改配置文件:使用域名,指定https证书的公钥和私钥
vim /opt/harbor/harbor.yml
hostname: blog.oldqiang.com
... ...
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /opt/cert/Nginx/1_blog.oldqiang.com_bundle.crt
private_key: /opt/cert/Nginx/2_blog.oldqiang.com.key
使用自签名证书:
Step1:创建证书存放目录
mkdir -p /data/cert && cd /data/cert
Step2:创建自己的CA证书(不使用第三方权威机构的CA来认证)
openssl genrsa -out ca.key 2048 # 生成根证书私钥(无加密)
Step3:生成自签名证书(使用已有私钥ca.key自行签发根证书)
openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj "/CN=Harbor-ca" req # 产生证书签发申请命令 -x509 # 签发X.509格式证书命令。X.509是最通用的一种签名证书格式。 -new # 生成证书请求 -key # 指定私钥文件 -nodes # 表示私钥不加密 -out # 输出 -subj # 指定用户信息 -days # 有效期
Step4:生成服务器端私钥和CSR签名请求
openssl req -newkey rsa:4096 -nodes -sha256 -keyout server.key -out server.csr
Step5:签发服务器证书
echo subjectAltName = IP:10.0.0.12 > extfile.cnf openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extfile extfile.cnf -out server.crt x509 # 签发X.509格式证书命令。 -req # 表示证书输入请求。 -days # 表示有效天数 -extensions # 表示按OpenSSL配置文件v3_req项添加扩展。 -CA # 表示CA证书,这里为ca.crt -CAkey # 表示CA证书密钥,这里为ca.key -CAcreateserial # 表示创建CA证书序列号 -extfile # 指定文件
Step6:客户端设置docker证书
# 如果如下目录不存在,请创建,如果有域名请按此格式依次创建 mkdir -p /etc/docker/certs.d/10.0.0.12 # mkdir -p /etc/docker/certs.d/[IP2] # mkdir -p /etc/docker/certs.d/[example1.com] # 如果端口为443,则不需要指定。如果为自定义端口,请指定端口 # /etc/docker/certs.d/yourdomain.com:port # 将ca根证书依次复制到上述创建的目录中 cp ca.crt /etc/docker/certs.d/10.0.0.12/
Step7:为harbor生成配置文件
./prepare
- 注释安装脚本中的导入镜像步骤
sed -i 's/docker load/#&/' /opt/harbor/install.sh
- 执行安装脚本
/opt/harbor/install.sh
- windows配置hosts解析
C:\Windows\System32\drivers\etc\hosts
10.0.0.12 blog.oldqiang.com
- 登录网页https://blog.oldqiang.com查看
- docker01配置hosts解析
cat >> /etc/hosts <<EOF
10.0.0.12 blog.oldqiang.com
EOF
- docker01删除http信任,重启docker
rm -rf /etc/docker/daemon.json
systemctl restart docker
- docker01登录harbor,用户名:admin,密码:123456
docker login blog.oldqiang.com
- docker01上传镜像
docker tag nginx:latest blog.oldqiang.com/library/nginx:latest
docker push blog.oldqiang.com/library/nginx:latest
Harbor配置参数
位于harbor.cfg
文件中。
- required参数:需要在配置文件中设置这些参数。如果用户更新它们harbor.cfg并运行install.sh脚本以重新安装Harbor,它们将生效。
- 可选参数:用户可以将它们保留为默认值,并在启动Harbour后在Web Portal上更新它们。如果它们已经启用harbor.cfg,它们只会在首次启动Harbour时生效。harbor.cfg将忽略对这些参数的后续更新。
注意:
至少需要更改hostname属性。
如果您选择通过Portal设置这些参数,请务必在Harbour启动后立即执行此操作。特别是,您必须在Harbour中注册或创建任何新用户之前设置所需的auth_mode。当系统中有用户时(除默认管理员用户外), 无法更改auth_mode。
必需参数
hostname
:目标主机的主机名,用于访问Portal和注册表服务。它应该是目标计算机的IP地址或完全限定的域名(FQDN),例如,192.168.1.10或reg.yourdomain.com。不要使用localhost或127.0.0.1作为主机名 - 外部客户端需要访问注册表服务!ui_url_protocol
😦 http或https。默认为http)用于访问Portal和令牌/通知服务的协议。如果启用了公证,则此参数必须为https。默认情况下,这是http。要设置https协议,请参阅使用HTTPS访问配置Harbor。db_password
:用于db_auth的PostgreSQL数据库的root密码。更改此密码以用于任何生产用途!max_job_workers
:(默认值为10)作业服务中的最大复制工作者数。对于每个映像复制作业,工作程序将存储库的所有标记同步到远程目标。增加此数量可以在系统中实现更多并发复制作业。但是,由于每个工作者都消耗一定量的网络/ CPU / IO资源**,请根据主机的硬件资源仔细选择该属性的值。customize_crt
:(on or off. Default is on),如果此属性on,在准备脚本创建注册表的令牌生成/验证私钥和根证书。当外部源提供密钥和根证书时,将此属性设置为off。有关详细信息,请参阅自定义密钥和港口令牌服务证书。ssl_cert
:SSL证书的路径,仅在协议设置为https时应用。ssl_cert_key
:SSL密钥的路径,仅在协议设置为https时应用。secretkey_path
:用于加密或解密复制策略中远程注册表密码的密钥路径。log_rotate_count
:日志文件在被删除之前会被轮换log_rotate_count次。如果count为0,则删除旧版本而不是旋转。log_rotate_size
:仅当日志文件大于log_rotate_size字节时才会轮换日志文件。如果大小后跟k,则假定大小以千字节为单位。如果使用M,则大小以兆字节为单位,如果使用G,则大小为千兆字节。尺寸100,尺寸100k,尺寸100M和尺寸100G都是有效的。http_proxy
:为Clair配置http代理,例如http://my.proxy.com:3128。https_proxy
:为Clair配置https代理,例如http://my.proxy.com:3128。no_proxy
:为Clair配置无代理,例如127.0.0.1,localhost,core,registry。
可选参数
-
harbor_admin_password
:管理员的初始密码。仅在Harbor首次启动时生效。之后,将忽略此设置,并且应在Portal中设置管理员密码。默认:admin / Harbor12345 -
auth_mode
:使用的身份验证类型。默认db_auth,即凭据存储在数据库中。对于LDAP身份验证,请将其设置为ldap_auth。重要信息:从现有Harbor实例升级时,必须确保在启动新版本的Harbor之前auth_mode相同harbor.cfg。否则,用户可能无法在升级后登录。 -
ldap_url
:LDAP端点URL(例如ldaps://ldap.mydomain.com)。 仅在auth_mode设置为ldap_auth时使用。 -
ldap_searchdn
:具有搜索LDAP / AD服务器权限的用户的DN(例如uid=admin,ou=people,dc=mydomain,dc=com)。 -
ldap_search_pwd:ldap_searchdn
:指定的用户密码。 -
ldap_basedn
:查找用户的基本DN,例如ou=people,dc=mydomain,dc=com。 仅在auth_mode设置为ldap_auth时使用。 -
ldap_filter
:用于查找用户的搜索过滤器,例如(objectClass=person)。 -
ldap_uid
:用于在LDAP搜索期间匹配用户的属性,它可以是uid,cn,email或其他属性。 -
ldap_scope
:搜索用户的范围,0-LDAP_SCOPE_BASE,1-LDAP_SCOPE_ONELEVEL,2-LDAP_SCOPE_SUBTREE。默认值为2。 -
ldap_timeout
:连接LDAP服务器时超时(以秒为单位)。默认值为5。 -
ldap_verify_cert
:验证来自LDAP服务器的证书。默认为true。 -
ldap_group_basedn
:在LDAP / AD中查找组的基本dn,例如ou=group,dc=mydomain,dc=com。 -
ldap_group_filter
:搜索LDAP / AD组的过滤器,例如objectclass=group。 -
ldap_group_gid
:用于命名LDAP / AD组的属性,它可以是cn,name。 -
ldap_group_scope
:搜索ldap组的范围。0-LDAP_SCOPE_BASE,1-LDAP_SCOPE_ONELEVEL,2-LDAP_SCOPE_SUBTREE。默认值为2。 -
self_registration
:( 打开或关闭。默认打开)启用/禁用用户注册他/她自己的能力。禁用时,新用户只能由管理员用户创建,只有管理员用户可以在Harbor中创建新用户。 注意:当auth_mode设置为ldap_auth时,始终禁用自注册功能,并忽略此标志。 -
token_expiration
:令牌服务创建的令牌的到期时间(以分钟为单位),默认为30分钟。 -
project_creation_restriction
:用于控制用户有权创建项目的标志。默认情况下,每个人都可以创建一个项目,设置为“adminonly”,这样只有管理员才能创建项目。
电子邮件设置
Harbor需要这些参数才能向用户发送“密码重置”电子邮件。
如果你的SMTP服务器需要SSL,但不支持STARTTLS,那么你应该通过设置启用SSL email_ssl = TRUE(默认false)。
如果电子邮件服务器使用自签名证书或不受信任证书,则设置email_insecure = true
email_server
= smtp.mydomain.comemail_server_port
= 25email_identity
=email_username
= sample_admin@mydomain.comemail_password
= abcemail_from
= admin sample_admin@mydomain.comemail_ssl
= falseemail_insecure
= false
配置存储后端
默认情况下,Harbor将图像存储在本地文件系统中。在生产环境中,您可以考虑使用其他存储后端而不是本地文件系统,如S3,OpenStack Swift,Ceph等。这些参数是注册表的配置。
registry_storage_provider_name
:注册表的存储提供程序名称,可以是filesystem,s3,gcs,azure等。默认为filesystem。registry_storage_provider_config
:存储提供程序配置的逗号分隔“key:value”对,例如“key1:value,key2:value2”。默认为空字符串。registry_custom_ca_bundle
:自定义根ca证书的路径,它将注入到注册表和图表存储库容器的信任库中。当用户使用自签名证书托管内部存储时,通常需要这样做。
例如,如果使用Openstack Swift作为存储后端,则参数可能如下所示:
registry_storage_provider_name = swift
registry_storage_provider_config = "username:admin,password:ADMIN_PASS,authurl:http://keystone_addr:35357/v3/aut"
Docker网络
本地网络类型
四种本地网络类型(--network
):
-
Bridge
contauner:NAT模式。默认类型当Docker进程启动时,会在主机上创建一个虚拟网桥(docker0),此主机上启动的Docker容器会连接到这个虚拟网桥上,所以有默认172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以ethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
docker实际使用iptables的DNAT规则,实现端口转发功能,可以使用iptables -t nat -vnL查看。
-
Host
(open) container:host类型。和宿主机共用 Network Namespace,网络性能最高--network host
新创建的容器不会创建自己的虚拟网卡(Network Namespace),而是直接使用宿主机的网卡和IP地址(Network Namespace),因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器的其他资源:文件系统、系统进程等还是和宿主机保持隔离。此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。
-
Container
(join) container:容器类型。和其他容器共用 Network Namespace,k8s中使用这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
-
None
(Close) container:没有网络,上不了外网Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息,只有lo网络接口。不参与网络通信,运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中,例如:备份、进程诊断及各种离线任务等,此模式极少使用。
查看网络类型列表
docker network ls
创建自定义网络类型(bridge)
docker network create -d bridge --subnet 172.18.0.0/16 --gateway 172.18.0.1 b18
使用自定义网络类型
docker run -d --network b18 --ip=172.18.0.100 nginx:alpine
跨宿主机容器间通讯之macvlan
macvlan会共享物理网卡
所链接的外部网络
,实现的效果类似于虚拟机的桥接网络,各宿主机都要创建网络,启动时需要手动指定IP。
macvlan是网卡虚拟化方案:将一张物理网卡设置多个mac地址(虚拟网卡)。注意: 需要物理网卡,打开混杂模式。
macvlan工作模式
-
Bridge
:属于同一个parent接口的macvlan接口之间挂到同一个bridge上,可以二层互通(经过测试,发现这些macvlan接口都无法与parent 接口互通)。 -
VPEA
:所有接口的流量都需要到外部switch才能够到达其他接口。 -
Private
:接口只接受发送给自己MAC地址的报文。
各宿主机创建网络
docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.254 -o parent=eth0 macvlan_1
各宿主机启动容器
docker run -it --network macvlan_1 --ip 10.0.0.101 alpine:3.9
docker run -it --network macvlan_1 --ip 10.0.0.102 alpine:3.9
跨宿主机容器间通讯之overlay
consul服务存储ip地址的分配,提供DNS服务,全局网络:一台宿主机创建,会同步到其他宿主机。
搭建consul集群
- docker03:启动consul服务
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
- docker01:修改配置文件,并重启docker服务
cat > /etc/docker/daemon.json <<EOF
{
"cluster-store": "consul://10.0.0.13:8500",
"cluster-advertise": "10.0.0.11:2376"
}
EOF
systemctl restart docker.service
- docker02:修改配置文件,并重启docker服务
cat > /etc/docker/daemon.json <<EOF
{
"cluster-store": "consul://10.0.0.13:8500",
"cluster-advertise": "10.0.0.12:2376"
}
EOF
systemctl restart docker.service
- 登录管理页面查看
查看 KEY/VALUE --> docker --> nodes/ ,docker01和docker02配好后会有两个节点
创建overlay网络
docker network create -d overlay --subnet 172.26.0.0/16 --gateway 172.26.0.1 ol1
启动容器测试
docker01:
docker run -d -it --network ol1 --name oldboy01 alpine:3.9
docker run -d -it --network ol1 --name oldboy02 alpine:3.9
ifconfig docker_gwbridge
docker02:
docker run -d -it --network ol1 --name oldboy03 alpine:3.9
docker run -d -it --network ol1 --name oldboy04 alpine:3.9
ifconfig docker_gwbridge
每个容器有两块网卡:
- eth0实现容器间的通讯:DNS服务(使用 --name 指定的名字作为主机名)实现网络互通
- eth1实现容器访问外网:NAT模式,端口映射互通
zabbix容器overlay网络下部署
- 使用overlay网络
- 将
--name
改为--link
指定的名称 - 删除
--link
docker run --network ol1 --name mysql-server -it \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-d mysql:5.7 \
--character-set-server=utf8 --collation-server=utf8_bin
docker run --network ol1 --name zabbix-java-gateway -t \
-d zabbix/zabbix-java-gateway:latest
docker run --network ol1 --name zabbix-server -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
-p 10051:10051 \
-d zabbix/zabbix-server-mysql:latest
docker run --network ol1 --name zabbix-web-nginx-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-p 80:80 \
-d zabbix/zabbix-web-nginx-mysql:latest
Prometheus 容器监控
Prometheus(数据中心) + cAdvisor(信息采集) + Grafana(图形界面) 容器监控方案
官方文档:Prometheus-book
Prometheus
Prometheus是由SoundCloud开发的开源监控系统的开源版本。2016年,由Google发起的云原生基金会CNCF (Cloud Native Computing Foundation) 将其纳入为其第二大开源项目(第一大开源项目是Kubernetes)。Prometheus提供了一整套的包括监控数据搜集、存储、处理、可视化和告警的完整解决方案。
Prometheus官网地址:https://prometheus.io/
Prometheus GitHub:https://github.com/prometheus/prometheus/
-
尺寸数据
Prometheus实现了高维数据模型。时间序列由指标名称和一-组键值对标识。
-
强大的查询
PromQL允许对收集的时间序列数据进行切片和切块,以生成临时图形,表格和警报。
-
出色的可视化
Prometheus具有多种用于可视化数据的模式:内置表达式浏览器,Grafana集 成和控制台模板语言。
-
高效存储
Prometheus以有 效的自定义格式将时间序列存储在内存中和本地磁盘上。通过功能性分片和联合来实现缩放。
-
操作简单
每个服务器的可靠性都是独立的,仅依赖于本地存储。用Go语言编写的所有二进制文件都是静态链接的,易于部署。
-
精确警报
警报是基于Prometheus灵活的PromQL定义的,并维护尺寸信息。警报管理器处理通知和沉默。
-
许多客户端库
客户端库使服务的检测变得容易。已经支持十多种语言,并且自定义库易于实现。.
-
许多整合
现有的出口商允许将第三方数据桥接到Prometheus中。示例:系统统计信息,以及Docker, HAProxy, StatsD和JMX指标。
Prometheus架构
(1)Prometheus Server:负责从Exporter中拉取和存储监控数据,并提供一套查询语言(PromQL)供用户使用。
(2)Exporter:负责收集目标对象(如Host或Container)的性能数据,并通过HTTP接口供Prometheus Server获取。
(3)Grafana:获取Prometheus Server提供的监控数据并通过Web UI的方式完美展现数据。
(4)AlertManager:负责根据告警规则和预定义的告警方式发出例如Email、Webhook之类的告警。
(5)Pushgetway:负责接受短暂的工作手动推送的信息,一般不使用。
Prometheus数据模型
Prometheus 内置数据库 PromQL 中存储的数据为时间序列,是由 metric 的名字和一系列的标签(键值对)唯一标识的,不同的标签则代表不同的时间序列。
- metric 名字:该名字应该具有语义,一般用于表示 metric 的功能,例如:http_requests_total, 表示 http 请求的总数。其中,metric 名字由 ASCII 字符,数字,下划线,以及冒号组成,且必须满足正则表达式 a-zA-Z_😗。
- 标签:使同一个时间序列有了不同维度的识别。例如 http_requests_total{method="Get"} 表示所有 http 请求中的 Get 请求。当 method="post" 时,则为新的一个 metric。标签中的键由 ASCII 字符,数字,以及下划线组成,且必须满足正则表达式 a-zA-Z_😗。
- 样本:实际的时间序列,每个序列包括一个 float64 的值和一个毫秒级的时间戳。
时间序列格式:
<metric name>{<label name>=<label value>, ...}
示例:
api_http_requests_total{method="POST", handler="/messages"}
另一个时序数据库InfluxDB,它也是一个不错的时序数据库,经常用来作为监控数据的存储。
cAdvisor
cAdvisor是谷歌开发的,用于分析运行中容器的资源占用和性能指标的开源工具。cAdvisor是一个运行时的守护进程,负责收集、聚合、处理和输出运行中容器的信息。
cAdvisor GitHub:https://github.com/google/cadvisor
Grafana
Grafana是一个跨平台的开源的度量分析和可视化工具,可以通过将采集的数据查询然后可视化的展示,并及时通知。
-
展示方式:快速灵活的客户端图表,面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件,比如热图、折线图、图表等多种展示方式;
-
数据源:Graphite,InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch和KairosDB等;
-
通知提醒:以可视方式定义最重要指标的警报规则,Grafana将不断计算并发送通知,在数据达到阈值时通过Slack、PagerDuty等获得通知;
-
混合展示:在同一图表中混合使用不同的数据源,可以基于每个查询指定数据源,甚至自定义数据源;
-
注释:使用来自不同数据源的丰富事件注释图表,将鼠标悬停在事件上会显示完整的事件元数据和标记;
-
过滤器:Ad-hoc过滤器允许动态创建新的键/值过滤器,这些过滤器会自动应用于使用该数据源的所有查询。
官方地址:https://grafana.com/
官方模板下载地址:https://grafana.com/dashboards
容器监控搭建
环境准备
主机名 | 角色 | IP |
---|---|---|
docker01 | exporter(CAdvisor,node-exporter) | 10.0.0.11 |
docker02 | exporter(CAdvisor,node-exporter) | 10.0.0.12 |
docker03 | Prometheus(Prometheus,AlertManager,Grafana) | 10.0.0.13 |
Prometheus部署
- 下载(linux-amd64)
cd /opt
wget https://github.com/prometheus/prometheus/releases/download/v2.23.0/prometheus-2.23.0.linux-amd64.tar.gz
- 解压
tar xf prometheus-2.23.0.linux-amd64.tar.gz
- 配置
cp /opt/prometheus-2.23.0.linux-amd64/prometheus.yml{,.bak}
cat >> /opt/prometheus-2.23.0.linux-amd64/prometheus.yml <<EOF
- job_name: 'node-exporter'
static_configs:
- targets: ['10.0.0.11:9100','10.0.0.12:9100']
EOF
# my global config global: scrape_interval: 15s # 将 scrape 间隔设置为每15秒一次。默认为每1分钟一次 evaluation_interval: 15s # 每隔15秒评估一次规则。默认值为每1分钟一次 # scrape_timeout is set to the global default (10s). # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093 # 加载一次规则,并根据全局“evaluation_interval”定期评估它们。 rule_files: # - "first_rules.yml" # - "second_rules.yml" # A scrape configuration: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: 'prometheus' # metrics_path defaults to '/metrics' # scheme defaults to 'http'. static_configs: - targets: ['localhost:9090']
- 启动
cd /opt/prometheus-2.23.0.linux-amd64/
./prometheus --config.file="prometheus.yml" &
-
访问 Status --> Targets:http://10.0.0.13:9090/classic/targets
可以看到两个节点和Prometheus本身。
Exporter部署
# 启动node-exporter
docker run -d -p 9100:9100 -v "/:/host:ro,rslave" --name=node_exporter quay.io/prometheus/node-exporter --path.rootfs /host
# 启动cadvisor
docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor:latest
Prometheus自动发现
- 关闭Prometheus
pkill prometheus
- 修改配置文件
cat >> /opt/prometheus-2.23.0.linux-amd64/prometheus.yml <<EOF
- job_name: 'cadvisor'
file_sd_configs:
- files:
- job/server.json
refresh_interval: 10s
EOF
mkdir /opt/prometheus-2.23.0.linux-amd64/job
cat > /opt/prometheus-2.23.0.linux-amd64/job/server.json <<EOF
[
{
"targets": ["10.0.0.11:8080"]
}
]
EOF
- 启动Prometheus
cd /opt/prometheus-2.23.0.linux-amd64/
./prometheus --config.file="prometheus.yml" &
-
访问 Status --> Targets:http://10.0.0.13:9090/classic/targets
新增一个节点。
-
修改server.json
cat > /opt/prometheus-2.23.0.linux-amd64/job/server.json <<EOF
[
{
"targets": ["10.0.0.11:8080","10.0.0.12:8080"]
}
]
EOF
-
访问 Status --> Targets:http://10.0.0.13:9090/classic/targets
等待10s,刷新,新增一个节点。
AlertManager部署
- 下载(linux-amd64)
cd /opt
wget https://github.com/prometheus/alertmanager/releases/download/v0.21.0/alertmanager-0.21.0.linux-amd64.tar.gz
- 解压
tar xf alertmanager-0.21.0.linux-amd64.tar.gz
- 修改alertmanager配置文件:邮件报警
mv /opt/alertmanager-0.21.0.linux-amd64/alertmanager.yml{,.bak}
cat > /opt/alertmanager-0.21.0.linux-amd64/alertmanager.yml <<EOF
global:
resolve_timeout: 5m
smtp_from: '296917342@qq.com'
smtp_smarthost: 'smtp.qq.com:465'
smtp_auth_username: '296917342@qq.com'
smtp_auth_password: 'xxxxxxxxxxxxxxx'
smtp_require_tls: false
smtp_hello: 'qq.com'
route:
group_by: ['alertname']
group_wait: 5s
group_interval: 5s
repeat_interval: 5m
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: '296917342@qq.com'
send_resolved: true
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
EOF
- 启动alertmanager
cd /opt/alertmanager-0.21.0.linux-amd64/
./alertmanager --config.file="alertmanager.yml" &
- 修改prometheus配置文件:指定Alertmanager和rule
cat > /opt/prometheus-2.23.0.linux-amd64/prometheus.yml <<EOF
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- 10.0.0.13:9093
rule_files:
- "node_down.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['10.0.0.11:9100','10.0.0.12:9100']
- job_name: 'cadvisor'
file_sd_configs:
- files:
- job/server.json
refresh_interval: 10s
EOF
- 创建rule配置文件
cat > /opt/prometheus-2.23.0.linux-amd64/node_down.yml <<EOF
groups:
- name: node-up
rules:
- alert: node-up
expr: up{job="node-exporter"} == 0
for: 15s
labels:
severity: 1
team: node
annotations:
summary: "{{ $labels.instance }} 已停止运行超过 15s!"
EOF
- 重启prometheus
pkill prometheus
cd /opt/prometheus-2.23.0.linux-amd64/
./prometheus --config.file="prometheus.yml" &
- 访问:http://10.0.0.13:9093
- 关闭node测试
shutdown -h now
Grafana部署
- 安装
cat > /etc/yum.repos.d/grafana.repo <<EOF
[grafana]
name=grafana
baseurl=https://mirrors.tuna.tsinghua.edu.cn/grafana/yum/rpm
repo_gpgcheck=0
enabled=1
gpgcheck=0
EOF
yum makecache && yum install grafana -y
- 启动并加入开机启动
systemctl start grafana-server.service
systemctl enable grafana-server.service
-
访问grafana:http://10.0.0.13:3000,默认账号:admin:admin
-
新建数据源:
设置-preferences-Data Sources-Add data source-Prometheus-select-URL:http://10.0.0.13:9090 - Save&Test
-
下载dashboard模板:
-
导入dashboard模板:
创建-Import-Upload JSON file-选择josn模板文件-Prometheus-Import