Docker 概述
Docker 是什么
- 使用最广泛的开源容器引擎
- 一种操作系统级的虚拟化技术
- 依赖于Linux内核特性:Namespace(资源隔离)和Cgroups(资源限制)
- 一个简单的应用程序打包工具
Docker 设计目标
- 提供简单的应用程序打包工具
- 开发人员和运维人员职责逻辑分离
- 开发人员 如何使用docker部署
- 运维人员 如何管理容器
- 多环境保持一致性
- 构建:镜像产出 线上线下环境一致
- 运输:处处运行 不需要配置和修改 减少环境不一致的问题
- 构建,运输,随处运行 (Build,Ship and Run any App,Angwhere)
Docker 基本组成
- Docker Client:客户端
- Ddocker Daemon:守护进程
- Docker Images:镜像
- Docker Container:容器
- Docker Registry:镜像仓库
容器 vs 虚拟机
Docker 应用场景
- 应用程序打包和发布
- 应用程序隔离
- 持续集成
- 部署微服务
- 快速搭建测试环境
- 提供PaaS产品(平台即服务)
Docker 安装
Docker版本
- 社区版(Community Edition,CE)
- 企业版(Enterprise Edition,EE)
支持平台
CentOS7.x 安装 Docker
1 | # 官方文档 |
1 | # 关闭方后墙和selinux |
Docker 镜像管理
镜像是什么
1 | 1. 一个分层存储的文件 |
- 镜像不是一个单一的文件,而是有多层构成。
- 我们可以通过docker history <ID/NAME> 查看镜像中各层内容及大小,
- 每层对应着Dockerfile中的一条指令。
- Docker镜像默认存储在/var/lib/docker/\<storage-driver>中。
镜像仓库
- Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。
- 地址:https://hub.docker.com/explore
镜像加速器 时速云
1 | https://www.daocloud.io/mirror |
镜像与容器联系
- 容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时,
- 会先从镜像里要写的文件复制到容器自己的文件系统中(读写层)。
- 如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。所以无论多
- 少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作的,并不会修改镜像的源文件,
- 这种方式提高磁盘利用率。
- 若想持久化这些改动,可以通过docker commit 将容器保存成一个新镜像。
查看读写层
1 | [root@docker ~]# docker run -it -d --name web nginx:1.16 |
镜像常用命令
镜像离线导出和导入
1 | # 离线传镜像 导出和导入 |
查看镜像版本
1 | # 官方镜像版本查找 筛选想要找到的镜像名称,选择tags查看 |
Docker 容器管理
创建容器常用选项
1 | # 容器退出时重启策略 |
容器资源限制
1 | # OOM Killer 操作系统在cpu不够用时 会删除使用率最高的进程 |
1 | [root@docker merged]# docker run -it -d --name web05 --cpus=".5" --memory="500m" --memory-swap="600m" busybox |
管理容器常用命令
1 | # 列出最新创建的容器 |
1 | # 显示一个容器运行的进程 |
Docker 数据管理
- 容器是即行即用的
- 设计目标其中一条就是,不要轻易的进入容器,修改容器
- 容器删除后里面的数据就不会存在,不能每次都commit构建一个新的镜像吧…
- 那我们程序中经常需要变动数据 如web的根目录,或者是mysql的data目录,怎么办呢?
- 需要专门的存储方式,不能存在镜像里
- 将这些经常变动的数据目录,放在宿主机存储,删除容器数据也不会丢失,下次使用的时候挂载宿主机里面的数据即可
将数据从宿主机挂载到容器中的三种方式
- Docker提供三种方式将数据从宿主机挂载到容器中:
- volumes:
- Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
- 把数据存储在宿主机上
- bind mounts:
- 将宿主机上的任意位置的文件或者目录挂载到容器中。
- 常用于 容器想使用宿主机上的目录文件
- tmpfs:
- 挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用
- tmpfs,同时避免写入容器可写层提高性能。
Volume
1 | 注意: |
- 管理数据卷
1 | # 创建 |
- 用卷创建一个容器:
1 | docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx |
- 清理:
1 | # docker stop nginx-test |
- 使用:
1 | [root@docker merged]# docker volume create nginx_vol |
- 如果我们的某一个容器坏了,比如web2,如果不使用数据卷,里面的数据就看不到了
- 如果使用数据卷,直接挂载到nginx_vol就能看到了
- 删除容器,数据卷没有被删除掉,数据还在,除非也要删除数据卷
1 | # 停掉web02 再启动一个容器 把名字改了 端口不变 继续使用 |
Bind Mounts
1 | 注意: |
1 | 用卷创建一个容器: |
1 | # 必须先要有这个目录 |
数据管理总结
1 | Volume特点: |
1 | Bind Mounts特点: |
Docker 网络模式
- bridge
- –net=bridge
- 默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
- host
- –net=host
- 容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,
- 而是使用宿主机的。
- 容器除了网络,其他都是隔离的。
- none
- –net=none
- 获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
- container
- –net=container:Name/ID
- 与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。
- 自定义网络
- 与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。
bridge
1 | [root@docker root]# docker run --rm -it --name bridge_test busybox bash |
host
1 | # 与宿主机网络配置一致 |
none
1 | # 独立的网络命名空间,什么都不给你配置,需要自己配置 |
container
1 | # container: 让web2 与 web1 使用同一个网络命名空间 |
自定义网络
1 | # 默认创建的容器之间网络是隔离的,无法互相访问 |
自定义网段网络
- 创建网络的时候 指定网段
- 启动容器 指定IP
- 自动dns 这个解析 只对用户自定义网络有效
1 | [root@docker ~]# docker network create --subnet 172.22.16.0/24 --gateway 172.22.16.1 my-net |
把容器加入到自定义网络
1 | # 创建一个基础容器 |
容器网络访问原理
veth pair(对)
- Docker安装完成时会创建一个 命名为 docker0 的 linux bridge
- 安装网桥工具
1 | yum install bridge-utils |
- 容器的网络配置
1 | 容器有一个网卡 eth0@if65。大家可能会问了,为什么不是 veth808f338 呢? |
- veth pair 是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,
- 网卡的一头(eth0@if65)在容器中,另一头(veth808f338)挂在网桥 docker0 上,
- 其效果就是将 eth0@if65 也挂在了 docker0 上。
- eth0@if65 已经配置了 IP 172.18.0.2,为什么是这个网段呢?
1 | [root@docker ~]# docker network inspect bridge |
- Docker 提供三种 用户自定义 网络驱动:bridge, overlay 和 macvlan。
- overlay 和 macvlan 用于创建跨主机的网络,我们可通过 bridge 驱动创建类似前面默认的 bridge 网络。
1 | docker network create --subnet 172.22.16.0/24 --gateway 172.22.16.1 my-net |
数据包是怎样到达外网的
1 | # 查看iptables |
如果网桥 docker0 收到来自 172.18.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。
而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)。
- tcpdump 查看地址是如何转换的
1 | [root@docker ~]# ip r |
1 | # 监控 docker0 和 eth0 上的 icmp(ping)数据包 |
- 流程总结
1 | 1. busybox 发送 ping 包:172.18.0.2 > www.baidu.com。 |
外网是如何访问容器的
- 数据包发送给宿主机后 通过DNAT 转给容器
1 | [root@docker ~]# docker run -it -d -p 88:80 --name web6 nginx:1.16 |
Dockerfile
Dockerfile 格式
1 | FROM # 指定基础镜像FROM centos |
Build镜像
快速部署 LNMP 网站平台
- 生产上应该注意到的
1 | 1. 编译安装 (1.configure 2.make 3.make install) 还是 yum安装 (yum源) RUN |
1 | 1. 可以先自己准备一个centos环境 然后自己在上面操作一次 |
1 | 1. 让自己生成的镜像越小越好 |
1 | 1. 按照项目写dockerfile |
目录规划 和 系统基础镜像
1 | # 按项目创建目录分层 |
构建 centos:7 基础镜像
- 由于官方提供的centos镜像有很多基础命令没有安装,所有我们自己来构建一个基础base
1 | [root@docker centos]# vim Dockerfile |
1 | # 也可以下载 |
1 | # 构建镜像 game/centos:7 |
构建 Nginx 基础镜像
1 | [root@docker nginx]# mkdir -p /opt/game/runtime/nginx |
1 | [root@docker nginx]# vim Dockerfile |
1 | # 构建 |
1 | # 传个测试首页测试 构建个项目 |
构建 PHP 基础镜像
- 创建构建目录
1 | [root@docker runtime]# mkdir -p /opt/game/runtime/php/ |
- 编写php运行环境dockerfile
1 | # 提前准备好优化的配置文件 |
1 | # 编译安装 |
1 | # 编译 |
1 | # 测试 |
构建 yum版 PHP 基础镜像
1 | [root@Docker php]# vim Dockerfile |
1 | [root@Docker php]# docker build -t game/php:7.2 . |
1 | [root@Docker php]# docker images |
1 | # 添加优化配置文件 构建成可用的php镜像 |
构建 TOMCAT 基础镜像
1 | [root@docker runtime]# mkdir -p /opt/game/runtime/tomcat |
1 | # 测试 |
1 | # 测试个小项目 |
快速部署LNMP网站平台
构建 自定义网络 lnmp
1 | # 构建后在lnmp网络的容器可以互相访问 |
构建 php 容器
1 | docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwroot game/app-php:7.2 |
1 | 查看创建的 wwwroot 数据卷 |
构建 nginx 容器
1 | # yum 安装的nginx 配置文件在 conf.d/里 把里面的default.conf 覆盖下 |
测试 nginx 与 php的互通性
1 | # 访问公网88端口 |
创建 mysql 容器
1 | # 使用官方的mysql镜像 |
1 | # mysql容器的数据在数据款中 mysql_vol |
部署 wordpress php版
1 | [root@Docker _data]# cd /var/lib/docker/volumes/wwwroot/_data/ |
1 | [root@Docker wordpress]# cp wp-config-sample.php wp-config.php |
1 | # 看日志 |
镜像仓库 Harbor
介绍
- Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,
- 从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制 ,
- AD/LDAP集成以及审计日志等,足以满足基本企业需求。
1 | # github |
离线安装
1 | # 安装 docker compose 单机编排 |
1 | # 解压安装包,修改配置文件 |
1 | # 准备 |
1 | # 列出 |
免https使用
1 | [root@Docker harbor]# vim /etc/docker/daemon.json |
创建项目管理员用户
登录镜像仓库
1 | [root@Docker nginx]# docker login 172.17.70.239 |
推送镜像
1 | # 在项目中标记镜像: |
创建一个新项目
1 | # 私有项目需要认证才能下载 |
1 | # 权限演示: |
1 | # 启动一个容器 |
图形页面管理 Portainer
- shipyard 已经不提供更新
- Portainer 是一个开源、轻量级Docker管理用户界面,基于Docker API,可管理Docker主机或Swarm模式
1 | Rancher |
1 | # 数据卷 |
1 | # 访问界面 |
Prometheus 监控基础
为什么要监控
- 对系统不间断实时监控
- 实时反馈系统当前状态
- 保证业务持续性运行
监控维度
Prometheus 概述
- Prometheus(普罗米修斯)是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目,
- 拥有非常活跃的开发人员和用户社区。为强调开源及独立维护,Prometheus于2016年加入云原生云计算
- 基金会(CNCF),成为继Kubernetes之后的第二个托管项目。
1 | https://prometheus.io |
Prometheus 特点
- 多维数据模型:由度量名称和键值对标识的时间序列数据
- PromSQL:一种灵活的查询语言,可以利用多维数据完成复杂的查询
- 不依赖分布式存储,单个服务器节点可直接工作
- 基于HTTP的pull方1. 采集时间序列数据
- 推送时间序列数据通过PushGateway组件支持
- 通过服务发现或静态配置发现目标
- 多种图形模式及仪表盘支持(grafana)
Prometheus 架构
- Prometheus Server:收集指标和存储时间序列数据,并提供查询接口
- ClientLibrary:客户端库
- Push Gateway:短期存储指标数据。主要用于临时性的任务
- Exporters:采集已有的第三方服务监控指标并暴露metrics
- Alertmanager:告警
- Web UI:简单的Web控制台
实例 和 作业
- 实例:可以抓取的目标称为实例(Instances) -> 客户端
- 作业:具有相同目标的实例集合称为作业(Job) -> 实例分类
通过容器 安装部署
1 | Docker部署: https://prometheus.io/docs/prometheus/latest/installation/ |
- prometheus的监控大多数都是通过这个yml文件配置
1 | docker run -p 9090:9090 -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml \ |
- 下载镜像
1 | [root@Docker-2 ~]# docker pull prom/prometheus |
- 下载二进制包
1 | # 用里面的 prometheus.yml文件 |
- 启动容器
1 | # 数据在容器中 |
1 | # 持久化数据到宿主机上 |
1 | # 后台启动 |
cAdvisor(Container Advisor)
- 用于收集正在运行的容器资源使用和性能信息。
- cAdvisor 不具备存储 只具备采集 数据存储可持久访问的容器中
1 | https://github.com/google/cadvisor |
1 | sudo docker run \ |
1 | [root@Docker-2 opt]# docker ps |
1 | # web |
- 数据接口采集的数据,交给prometheus解析,遵循他的数据格式
- 拿这个接口 就可以告诉prometheus,我当前docker主机上的所有容器指标,他已经帮忙采集到了
Grafana
- 是一个开源的度量分析和可视化系统。
1 | https://grafana.com/grafana/download |
1 | # 容器安装 |
1 | # web |
- 添加 prometheus 数据源
1 | # 1. 如果访问不了 会提示网络连接有问题 |
修改 prometheus 数据文件
1 | # prometheus 去找 cAdvisor 拿监控docker的数据 |
1 | [root@Docker-2 opt]# docker ps |
添加 Grafana 仪表盘
1 | 1. 导入一个别人写好的 |
1 | # 再启动一个容器 |