docker学习文档

目录

一:Docker简介及基础: 7

1.1:docker简介: 7

1.1.1:Docker是什么: 7

1.1.2:docker的组成: 7

1.1.3:Docker对比虚拟机: 8

1.1.4:Docker的优势: 8

1.1.5:Docker的缺点: 8

1.2:Docker安装及基础命令介绍: 8

1.2.1:更改本机yum源: 8

1.2.2:安装并启动docker: 9

1.2.3:验证docker0网卡: 9

1.3:更改阿里云 docker 镜像源: 9

1.3.1:获取加速地址: 9

1.3.2:生成配置文件: 10

1.3.3:重启docke服务: 10

1.4:Docker 镜像基础命令: 11

1.4.1:搜索镜像: 11

1.4.2:下载镜像: 11

1.4.3:查看本地镜像: 11

1.4.4:镜像导出: 12

1.4.5:镜像导入: 12

1.4.6:删除镜像: 13

1.5:容器操作基础命令: 14

1.5.1:从镜像启动一个容器: 14

1.5.2:显示正在运行的容器,及包括关闭和不关闭的 14

1.5.3:显示所有容器: 14

1.5.4:删除运行中的容器: 14

1.5.5:随机映射端口: 14

1.5.6:指定端口映射: 15

1.5.7:查看容器已经映射的端口: 16

1.5.8:自定义容器名称: 16

1.5.9:后台启动容器: 16

1.5.10:单次运行: 16

1.5.11:容器的启动和关闭: 16

1.5.12:创建并进入容器: 16

1.5.13:进入到正在运行的容器: 17

1.5.14: 查看容器内部的hosts文件: 18

1.5.15:查看容器的详细信息: 19

1.5.16:批量关闭正在运行的容器: 19

1.5.17:批量强制关闭正在运行的容器: 19

1.5.18:批量删除已退出容器: 19

1.5.19:批量删除所有容器: 19

二:Docker 镜像制作: 21

2.1:手动制作yum版nginx镜像: 21

2.1.1:下载镜像并初始化系统: 21

2.1.2:yum安装并配置nginx: 21

2.1.3:关闭nginx后台运行: 21

2.1.4:自定义web页面: 21

2.1.5:提交为镜像: 21

2.1.6:带tag的镜像提交: 22

2.1.7:从自己镜像启动容器: 22

2.1.8:访问测试: 22

2.2:DockerFile制作yum版nginx镜像: 22

2.2.1:下载镜像并初始化系统: 22

2.2.2:编写Dockerfile: 23

2.2.3:准备源码包与配置文件: 24

2.2.4:执行镜像构建: 24

2.2.5:构建完成: 24

2.2.6:查看是否生成本地镜像: 25

2.2.7:从镜像启动容器: 25

2.2.8:访问web界面: 26

2.2.9:编译过程中使用过的镜像: 26

2.3:手动制作编译版本nginx 镜像: 26

2.3.1:下载镜像并初始化系统: 26

2.3.2:编译安装nginx: 26

2.3.3:关闭nginx后台运行: 26

2.3.4:创建用户及授权: 27

2.3.5:自定义web界面: 27

2.3.6:提交为镜像: 27

2.3.:7:从自己的镜像启动容器: 27

2.3.8:访问测试: 27

2.3.9:查看Nginx访问日志: 28

2.4:自定义tomcat镜像: 28

2.4.1:构建JDK镜像: 28

2.4.2:从JDK镜像构建tomcat镜像: 30

2.5:构建haproxy镜像: 33

2.5.1:准备基础文件: 33

2.5.2:编辑Dockerfile: 34

2.5.3:构建镜像: 34

2.5.4:测试镜像启动容器: 35

2.5.5:web访问验证: 35

2.6:本地镜像上传至官方docker 仓库: 35

2.6.1:准备账户: 35

2.6.2:填写账户基本信息: 36

2.6.3:在虚拟机使用自己的账号登录: 36

2.6.4:查看认证信息: 36

2.6.5:给镜像做tag并开始上传: 36

2.6.6:上传完成 37

2.6.7:到docker官网验证: 37

2.6.8:更换到其他docker服务器下载镜像: 37

2.6.9:从镜像启动一个容器: 37

三:Docker 数据管理: 38

3.1:数据类型: 38

3.1.1:数据卷的特点及使用: 38

3.1.2:文件挂载: 39

3.1.3:数据卷容器: 41

四:网络部分: 43

4.1:docker结合负载实现网站高可用: 43

4.1.1:整体规划图: 43

4.1.2:安装并配置keepalived: 43

4.1.3:安装并配置haproxy: 44

4.1.4:服务器启动nginx容器并验证: 47

4.2:容器之间的互联: 49

4.2.1:通过容器名称互联: 49

4.2.2:通过自定义容器别名互联: 50

4.2.3:通过网络夸宿主机互联: 51

五:Docker仓库之单机Docker Registry: 59

5.1:下载docker registry镜像: 59

5.2:搭建单机仓库: 59

5.2.1:创建授权使用目录: 59

5.2.2:创建用户: 59

5.2.3:验证用户名密码: 59

5.2.4:启动docker registry: 59

5.2.5:验证端口和容器: 60

5.2.6:测试登录仓库: 60

5.2.7:在Server1登录后上传镜像: 61

5.2.8:Server 2下载镜像并启动容器: 61

六:docker仓库之分布式 Harbor 63

6.1:Harbor功能官方介绍: 63

6.2:安装Harbor: 63

6.2.1:服务器1安装docker: 63

6.2.2:服务器2安装docker: 63

6.2.3:下载Harbor安装包: 64

6.3:配置Harbor: 64

6.3.1:解压并编辑harbor.cfg: 64

6.3.2:更新harbor配置: 65

6.3.3:官方方式启动Harbor: 66

6.3.4:非官方方式启动: 68

6.4:配置docker 使用harbor仓库上传下载镜像: 70

6.4.1:编辑docker配置文件: 70

6.4.2:重启docker服务: 70

6.4.3:验证能否登录harbor: 70

6.4.4:测试上传和下载镜像: 70

6.4.5:验证从harbor服务器下载镜像并启动容器: 72

6.4.6:从镜像启动容器并验证: 73

6.5:实现harbor高可用: 74

6.5.1:新部署一台harbor服务器: 74

6.5.2:验证从harbor登录: 76

6.5.3:创建一个nginx项目: 76

6.5.4:在主harbor服务器配置同步测试: 76

6.5.5:点击复制规则: 77

6.5.6:主harbor编辑同步策略: 77

6.5.7:主harbor查看镜像同步状态: 78

6.5.8:从harbor查看镜像: 78

6.5.9:测试从harbor镜像下载和容器启动: 78

6.6.:实现harbor 双向同步: 80

6.6.1:在docker客户端导入centos基础镜像: 80

6.6.2:镜像打tag: 80

6.6.3:上传到从harbor: 80

6.6.4:从harbor界面验证: 80

6.6.5:从harbor创建同步规则: 80

6.6.6:到主harbor验证镜像: 81

6.6.7:docker镜像端测试: 81

七:单机编排之Docker Compose: 83

7.1:基础环境准备: 83

7.1.1:安装python环境及pip命令: 83

7.1.2:安装docker compose: 83

7.1.3:验证版本: 83

7.1.4:查看帮助: 84

7.2:从 docker compose启动单个容器: 84

7.2.1:一个容器的docker compose文件: 84

7.2.2:启动容器: 84

7.2.3:启动完成: 85

7.2.4:web访问测试: 85

7.2.5:后台启动服务: 85

7.2.6:自定义容器名称: 85

7.2.7:验证容器: 86

7.2.8:查看容器进程: 86

7.3:从docker compose启动多个容器: 86

7.3.1:编辑docker-compose文件: 86

7.3.2:重新启动容器: 86

7.3.3:web访问测试: 87

7.4:定义数据卷挂载: 87

7.4.1:创建数据目录和文件: 87

7.4.2:编辑compose配置文件: 87

7.4.3:重启容器: 88

7.4.4:验证web访问: 88

7.4.5:其他常用命令: 88

7.5:实现单机版的HA+Nginx+Tomcat: 90

7.5.1:制作Haproxy镜像: 90

7.5.2:准备nginx镜像: 92

7.5.3:准备tomcat镜像: 92

7.5.4:编辑docker compose文件及环境准备: 92

7.5.6:验证容器启动成功: 96

7.5.7:查看启动日志: 96

7.5.8:访问haroxy 管理界面: 96

7.5.9:访问Nginx静态页面: 96

7.5.10:访问tomcat静态页面: 97

7.5.11:访问tomcat动态页面: 97

目录

一:简介:

前言

统称来说,容器是一种工具,指的是可以装下其它物品的工具,以方便人类归纳放置物品、存储和异地运输,具体来说比如人类使用的衣柜、行李箱、背包等可以成为容器,但今天我们所说的容器是一种IT技术。

容器技术是虚拟化、云计算、大数据之后的一门新兴的并且是炙手可热的新技术,容器技术提高了硬件资源利用率、方便了企业的业务快速横向扩容、实现了业务宕机自愈功能,因此未来数年会是一个容器愈发流行的时代,这是一个对于IT行业来说非常有影响和价值的技术,而对于IT行业的从业者来说,熟练掌握容器技术无疑是一个很有前景的的行业工作机会。

1.1:docker简介:

1.1.1:Docker是什么:

首先Docker是一个在2013年开源的应用程序并且是一个基于go语言编写是一个开源的pass服务(Platform as a Service,平台即服务的缩写),go语言是由google开发,docker公司最早叫dotCloud后由于Docker开源后大受欢迎就将公司改名为 Docker Inc,总部位于美国加州的旧金山,Docker是基于linux 内核实现,Docker最早采用LXC技术(LinuX Container的简写,LXC是Linux 原生支持的容器技术,可以提供轻量级的虚拟化,可以说 docker 就是基于 LXC 发展起来的,提供 LXC 的高级封装,发展标准的配置方法),而虚拟化技术KVM(Kernel-based Virtual Machine) 基于模块实现,Docker后改为自己研发并开源的runc技术运行容器。

Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程API来管理和创建Docker容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是build(构建)、ship(运输)、 run(运行),Docker遵从aoache 2.0协议,并通过(namespace及cgroup等)来提供容器的资源隔离与安全保障等,所以Docke容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机.类似于VM但是在原理和应用上和VM的差别还是很大的,并且docker的专业叫法是应用容器(Application Container)。

IDC/IAAS/PAAS/SAAS 对比

1.1.2:docker的组成:

Docker 客户端(Client):客户端使用docker 命令或其他工具调用docker API。

Docker 服务端(Server):Docker守护进程,运行docker容器。

Docker 镜像(Images):镜像可以理解为创建实例使用的模板。

Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。

Docker 仓库(Registry): 保存镜像的仓库,类似于git或svn这样的版本控制系统,官方仓库: https://hub.docker.com/

Docker 主机(Host):一个物理机或虚拟机,用于运行Docker服务进程和容器。

1.1.3:Docker对比虚拟机:

资源利用率更高:一台物理机可以运行数百个容器,但是一般只能运行数十个虚拟机。

开销更小:不需要启动单独的虚拟机占用硬件资源。

启动速度更快:可以在数秒内完成启动。

使用虚拟机是为了更好的实现服务运行环境隔离,但是一个虚拟机只运行一个服务,很明显资源利用率比较低。

1.1.4:Docker的优势:

快速部署:短时间内可以部署成百上千个应用,更快速交付到线上。

高效虚拟化:不需要额外的hypervisor支持,直接基于linux 实现应用虚拟化,相比虚拟机大幅提高性能和效率。

节省开支:提高服务器利用率,降低IT 支出。

简化配置:将运行环境打包保存至容器,使用时直接启动即可。

快速迁移和扩展:可夸平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台。

1.1.5:Docker的缺点:

隔离性:各应用之间的隔离不如虚拟机。

1.1.6:docker(容器)的核心技术:

容器规范:

除了docker之外的docker技术,还有coreOS的rkt,还有阿里的Pouch,为了保证容器生态的标志性和健康可持续发展,包括Google、Docker等公司共同成立了一个叫open container(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了两个规范,分别是runtime spec和image format spec,有了这两个规范,不通的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。

容器runtime:

runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境。

目前主流的三种runtime:

Lxc:linux上早期的runtime,Docker早期就是采用lxc作为runtime。

runc:目前Docker默认的runtime,runc遵守OCI规范,因此可以兼容lxc。

rkt:是CoreOS开发的容器runtime,也符合OCI规范,所以使用rktruntime也可以运行Docker容器。

容器管理工具:

管理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给runtime执行。

Lxd是lxc的管理工具。

Runc的管理工具是docker engine,docker engine包含后台deamon和cli两部分,大家经常提到的Docker就是指的docker engine。

Rkt的管理工具是rkt cli。

容器定义工具:

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。

Docker image:是docker 容器的模板,runtime依据docker image创建容器。

Dockerfile:包含N个命令的文本文件,通过dockerfile创建出docker image。

ACI(App container image):与docker image类似,是CoreOS开发的rkt容器的镜像格式。

Registry:

统一保存共享镜像的地方,叫做镜像仓库。

Image registry:docker 官方提供的私有仓库部署工具。

Docker hub:docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用。

Harbor:vmware 提供的自带web的镜像仓库,目前有很多公司使用。

编排工具:

当多个容器在多个主机运行的时候,单独管理每个容器是相当负载而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎。

容器编排通常包括容器管理、调度、集群定义和服务发现等功能。

Docker swarm:docker 开发的容器编排引擎。

Kubernetes:google领导开发的容器编排引擎,内部项目为Borg,且其同时支持docker和CoreOS。

Mesos+Marathon:通用的集群组员调度平台,mesos与marathon一起提供容器编排引擎功能。

1.1.7:docker(容器)的依赖技术:

容器网络

docker自带的网络docker network仅支持管理单机上的容器网络,当多主机运行的时候需要使用第三方开源网络,例如calico、flannel等。

服务发现:

容器的动态扩容特性决定了容器IP也会随之变化,因此需要有一种机制开源自动识别并将用户请求动态转发到新创建的容器上,kubernetes自带服务发现功能,需要结合kube-dns服务解析内部域名。

容器监控:

可以通过原生命令docker ps/top/stats 查看容器运行状态,另外也可以使heapster/ Prometheus等第三方监控工具监控容器的运行状态。

数据管理:

容器的动态迁移会导致其在不通的Host之间迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决。

日志收集:

docker 原生的日志查看工具docker logs,但是容器内部的日志需要通过ELK等专门的日志收集分析和展示工具进行处理。

1.2:Docker安装及基础命令介绍:

官方网址:https://www.docker.com/

系统版本选择:

Docker 目前已经支持多种操作系统的安装运行,比如Ubuntu、CentOS、Redhat、Debian、Fedora,甚至是还支持了Mac和Windows,在linux系统上需要内核版本在3.10或以上,docker版本号之前一直是0.X版本或1.X版本,但是从2017年3月1号开始改为每个季度发布一次稳版,其版本号规则也统一变更为YY.MM,例如17.09表示是2017年9月份发布的,本次演示的操作系统使用Centos 7.5为例。

Docker版本选择:

Docker之前没有区分版本,但是2017年推出(将docker更名为)新的项目Moby,github地址:https://github.com/moby/moby,Moby项目属于Docker项目的全新上游,Docker将是一个隶属于的Moby的子产品,而且之后的版本之后开始区分为CE版本(社区版本)和EE(企业收费版),CE社区版本和EE企业版本都是每个季度发布一个新版本,但是EE版本提供后期安全维护1年,而CE版本是4个月,本次演示的Docker版本为18.03,以下为官方原文:

https://blog.docker.com/2017/03/docker-enterprise-edition/

Docker CE and EE are released quarterly, and CE also has a monthly “Edge” option. Each Docker EE release is supported and maintained for one year and receives security and critical bugfixes during that period. We are also improving Docker CE maintainability by maintaining each quarterly CE release for 4 months. That gets Docker CE users a new 1-month window to update from one version to the next.

1.2.1:下载rpm包安装:

官方rpm包下载地址: https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

阿里镜像下载地址:

https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/

1.2.2:通过修改yum源安装:

[root@docker-server1 ~]# rm -rf /etc/yum.repos.d/*

[root@docker-server1 ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

[root@docker-server1 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

[root@docker-server1 ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

[root@docker-server1 ~]# yum install docker-ce

1.2:3:启动并验证docker服务:

[root@docker-server1 ~]# systemctl start docker

[root@docker-server1 ~]# systemctl enable docker

1.2.4:验证docker版本:

1.2.5:验证docker0网卡:

在docker安装启动之后,默认会生成一个名称为docker0的网卡并且默认IP地址为172.17.0.1的网卡。

1.2.6:验证docker 信息:

1.2.7:docker存储引擎:

目前docker的默认存储引擎为overlay2,需要磁盘分区支持d-type文件分层功能,因此需要系统磁盘的额外支持。

官方文档关于存储引擎的选择文档:

https://docs.docker.com/storage/storagedriver/select-storage-driver/

Docker官方推荐首选存储引擎为overlay2其次为devicemapper,但是devicemapper存在使用空间方面的一些限制,虽然可以通过后期配置解决,但是官方依然推荐使用overlay2,以下是网上查到的部分资料:

https://www.cnblogs.com/youruncloud/p/5736718.html

如果docker数据目录是一块单独的磁盘分区而且是xfs格式的,那么需要在格式化的时候加上参数-n ftype=1,否则后期在启动容器的时候会报错不支持d-type。

报错界面:

1.3:docker 镜像加速配置:

国内下载国外的镜像有时候会很慢,因此可以更改docker配置文件添加一个加速器,可以通过加速器达到加速下载镜像的目的。

1.3.1:获取加速地址:

浏览器打开http://cr.console.aliyun.com,注册或登录阿里云账号,点击左侧的镜像加速器,将会得到一个专属的加速地址,而且下面有使用配置说明:

1.3.2:生成配置文件:

[root@docker-server1 ~]# mkdir -p /etc/docker

[root@docker-server1 ~]# sudo tee /etc/docker/daemon.json <<-'EOF'

> {

> "registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]

> }

> EOF

{

"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]

}

[root@docker-server1 ~]# cat /etc/docker/daemon.json

{

"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"]

}

1.3.3:重启docke服务:

[root@docker-server1 ~]# systemctl daemon-reload

[root@docker-server1 ~]# sudo systemctl restart docker

1.4:Docker 镜像基础命令:

docker 命令是最常使用的命令,其后面可以加不同的参数以实现响应的功能,常用的命令如下:

1.4.1:搜索镜像:

在官方的docker 仓库中搜索指定名称的docker镜像,也会有很多三方镜像。

[root@docker-server1 ~]# docker search centos:7.2.1511 #带指定版本号

[root@docker-server1 ~]# docker search centos #不带版本号默认latest

1.4.2:下载镜像:

从docker 仓库将镜像下载到本地。

[root@docker-server1 ~]# docker pull alpine

[root@docker-server1 ~]# docker pull nginx

[root@docker-server1 ~]# docker pull hello-world

[root@docker-server1 ~]# docker pull centos

#下载中

#下载完成

1.4.3:查看本地镜像:

#下载完成的镜像比下载的大,因为下载完成后会解压

[root@docker-server1 ~]# docker images

REPOSITORY #镜像所属的仓库名称

TAG #镜像版本号(标识符),默认为latest

IMAGE ID #镜像唯一ID标示

CREATED #镜像创建时间

VIRTUAL SIZE #镜像的大小

1.4.4:镜像导出:

可以将镜像从本地导出问为一个压缩文件,然后复制到其他服务器进行导入使用。

#导出方法1:

[root@docker-server1 ~]# docker save -o /opt/centos.tar.gz centos

[root@docker-server1 ~]# ll /opt/centos.tar.gz

-rw------- 1 root root 205225472 Nov 1 03:52 /opt/centos.tar.gz

#导出方法2:

[root@docker-server1 ~]# docker save centos > /opt/centos-1.tar.gz

[root@docker-server1 ~]# ll /opt/centos-1.tar.gz

-rw-r--r-- 1 root root 205225472 Nov 1 03:52 /opt/centos-1.tar.gz

#查看镜像内容:

[root@docker-server1 ~]# cd /opt/

[root@docker-server1 opt]# tar xvf centos.tar.gz

[root@docker-server1 opt]# cat manifest.json #包含了镜像的相关配置,配置文件、分层

[{"Config":"196e0ce0c9fbb31da595b893dd39bc9fd4aa78a474bbdc21459a3ebe855b7768.json","RepoTags":["docker.io/centos:latest"],"Layers":["892ebb5d1299cbf459f67aa070f29fdc6d83f40

25c58c090e9a69bd4f7af436b/layer.tar"]}]

#分层为了方便文件的共用,即相同的文件可以共用[{"Config":"配置文件.json","RepoTags":["docker.io/nginx:latest"],"Layers":["分层1/layer.tar","分层2 /layer.tar","分层3 /layer.tar"]}]

1.4.5:镜像导入:

将镜像导入到docker

[root@docker-server1 ~]# scp /opt/centos.tar.gz 192.168.10.206:/opt/

[root@docker-server2 ~]# docker load < /opt/centos.tar.gz

验证镜像:

1.4.6:删除镜像:

[root@docker-server1 opt]# docker rmi centos

#获取运行参数帮助

[root@linux-docker opt]# docker daemon –help

总结:企业使用镜像及常见操作:

搜索、下载、导出、导入、删除

命令总结:

# docker load -i centos-latest.tar.xz #导入本地镜像

# docker save -o /opt/centos.tar #centos #导出镜像

# docker rmi 镜像ID/镜像名称 #删除指定ID的镜像,通过镜像启动容器的时候镜像不能被删除,除非将容器全部关闭

# docker rm 容器ID/容器名称 #删除容器

# docker rm 容器ID/容器名-f #强制删除正在运行的容器

1.5:容器操作基础命令:

命令格式:

# docker run [选项] [镜像名] [shell命令] [参数]

# docker run [参数选项] [镜像名称,必须在所有选项的后面] [/bin/echo 'hello wold'] #单次执行,没有自定义容器名称

# docker run centos /bin/echo 'hello wold' #启动的容器在执行完shel命令就退出了

1.5.1:从镜像启动一个容器:

会直接进入到容器,并随机生成容器ID和名称

[root@docker-server1 ~]# docker run -it docker.io/centos bash

[root@11445b3a84d3 /]#

#退出容器不注销

ctrl+p+q

1.5.2:显示正在运行的容器:

[root@linux-docker ~]# docker ps

1.5.3:显示所有容器:

包括当前正在运行以及已经关闭的所有容器:

[root@linux-docker ~]# docker ps -a

1.5.4:删除运行中的容器:

即使容正在运行当中,也会被强制删除掉

[root@docker-server1 ~]# docker rm -f 11445b3a84d3

1.5.5:随机映射端口:

[root@docker-server1 ~]# docker pull nginx #下载nginx 镜像

[root@docker-server1 ~]# docker run -P docker.io/nginx #前台启动并随机映射本地端口到容器的80

#前台启动的会话窗口无法进行其他操作,除非退出,但是退出后容器也会退出

#随机端口映射,其实是默认从32768开始

#访问端口:

1.5.6:指定端口映射:

方式1:本地端口81映射到容器80端口:

# docker run -p 81:80 --name nginx-test-port1 nginx

方式2:本地IP:本地端口:容器端口

# docker run -p 192.168.10.205:82:80 --name nginx-test-port2 docker.io/nginx

方式3:本地IP:本地随机端口:容器端口

# docker run -p 192.168.10.205::80 --name nginx-test-port3 docker.io/nginx

方式4:本机ip:本地端口:容器端口/协议,默认为tcp协议

# docker run -p 192.168.10.205:83:80/udp --name nginx-test-port4 docker.io/nginx

方式5:一次性映射多个端口+协议:

# docker run -p 86:80/tcp -p 443:443/tcp -p 53:53/udp --name nginx-test-port5 docker.io/nginx

#命令截图

#查看运行的容器:

#查看Nginx 容器访问日志:

[root@docker-server1 ~]# docker logs nginx-test-port3 #一次查看

[root@docker-server1 ~]# docker logs -f nginx-test-port3 #持续查看

1.5.7:查看容器已经映射的端口:

[root@docker-server1 ~]# docker port nginx-test-port5

1.5.8:自定义容器名称:

[root@docker-server1 ~]# docker run -it --name nginx-test nginx

1.5.9:后台启动容器:

[root@docker-server1 ~]# docker run -d -P --name nginx-test1 docker.io/nginx

9aaad776850bc06f516a770d42698e3b8f4ccce30d4b142f102ed3cb34399b31

1.5.10:创建并进入容器:

[root@docker-server1 ~]# docker run -t -i --name test-centos2 docker.io/centos /bin/bash

[root@a8fb69e71c73 /]# #创建容器后直接进入,执行exit退出后容器关闭

[root@docker-server1 ~]# docker run -d --name centos-test1 docker.io/centos

2cbbec43ba939476d798a5e1c454dd62d4d893ee12a09b587556ba6395353152

1.5.11:单次运行:

容器退出后自动删除:

[root@linux-docker opt]# docker run -it --rm --name nginx-delete-test docker.io/nginx

1.5.12:传递运行命令:

容器需要有一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令。

[root@docker-server1 ~]# docker run -d centos /usr/bin/tail -f '/etc/hosts'

1.5.13:容器的启动和关闭:

[root@docker-server1 ~]# docker stop f821d0cd5a99

[root@docker-server1 ~]# docker start f821d0cd5a99

1.5.14:进入到正在运行的容器:

1.5.14.1:使用attach命令:

#使用方式为docker attach 容器名,attach 类似于vnc,操作会在各个容器界面显示,所有使用此方式进入容器的操作都是同步显示的且exit后容器将被关闭,且使用exit退出后容器关闭,不推荐使用,

1.5.14.2:使用exec命令:

执行单次命令与进入容器,不是很推荐此方式,虽然exit退出容器还在运行

1.5.14.3:使用nsenter命令:

推荐使用此方式,nsenter命令需要通过PID进入到容器内部,不过可以使用docker inspect获取到容器的PID:

[root@docker-server1 ~]# yum install util-linux #安装nsenter命令

[root@docker-server1 ~]# docker inspect -f "{{.NetworkSettings.IPAddress}}" 91fc190cb538

172.17.0.2

[root@docker-server1 ~]# docker inspect -f "{{.State.Pid}}" mydocker #获取到某个docker容器的PID,可以通过PID进入到容器内

[root@docker-server1 ~]# docker inspect -f "{{.State.Pid}}" centos-test3

5892

[root@docker-server1 ~]# nsenter -t 5892 -m -u -i -n -p

[root@66f511bb15af /]# ls

1.5.14.4:脚本方式:

将nsenter命令写入到脚本进行调用,如下:

[root@docker-server1 ~]# cat docker-in.sh

#!/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

#测试脚本是否可以正常进入到容器且退出后仍然正常运行:

[root@docker-server1 ~]# chmod a+x docker-in.sh

[root@docker-server1 ~]# ./docker-in.sh centos-test3

[root@66f511bb15af /]# pwd

/

[root@66f511bb15af /]# exit

logout

[root@docker-server1 ~]# ./docker-in.sh centos-test3

[root@66f511bb15af /]# exit

Logout

1.5.15: 查看容器内部的hosts文件:

[root@docker-server1 ~]# docker run -i -t --name test-centos3 docker.io/centos /bin/bash

[root@056bb4928b64 /]# cat /etc/hosts

127.0.0.1 localhost

::1 localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.4 056bb4928b64 #默认会将实例的ID 添加到自己的hosts文件

#ping 容器ID:

1.5.16:批量关闭正在运行的容器:

[root@docker-server1 ~]# docker stop $(docker ps -a -q) #正常关闭所有运行中的容器

1.5.17:批量强制关闭正在运行的容器:

[root@docker-server1 ~]# docker kill $(docker ps -a -q) #强制关闭所有运行中的容器

1.5.18:批量删除已退出容器:

[root@docker-server1 ~]# docker rm -f `docker ps -aq -f status=exited`

1.5.19:批量删除所有容器:

[root@docker-server1 ~]# docker rm -f $(docker ps -a -q)

1.5.20:指定容器DNS:

Dns服务,默认采用宿主机的dns 地址

一是将dns地址配置在宿主机

二是将参数配置在docker 启动脚本里面 –dns=1.1.1.1

[root@docker-server1 ~]# docker run -it --rm --dns 223.6.6.6 centos bash

[root@afeb628bf074 /]# cat /etc/resolv.conf

nameserver 223.6.6.6

二:Docker 镜像与制作:

Docker 镜像有没有内核?

从镜像大小上面来说,一个比较小的镜像只有十几MB,而内核文件需要一百多兆, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核,而镜像本身则只提供相应的rootfs,即系统正常运行所必须的用户空间的文件系统,比如/dev/,/proc,/bin,/etc等目录,所以容器当中基本是没有/boot目录的,而/boot当中保存的就是与内核相关的文件和目录。

为什么没有内核?

由于容器启动和运行过程中是直接使用了宿主机的内核,所以没有直接调用过物理硬件,所以也不会涉及到硬件驱动,因此也用不上内核和驱动,另外有内核的那是虚拟机。

2.1:手动制作yum版nginx镜像:

Docker制作类似于虚拟机的镜像制作,即按照公司的实际业务务求将需要安装的软件、相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生产实例,这样可以极大的简化相同环境的部署工作,Docker的镜像制作分为手动制作和自动制作(基于DockerFile),其中手动制作镜像步骤具体如下:

2.1.1:下载镜像并初始化系统:

基于某个基础镜像之上重新制作,因此需要先有一个基础镜像,本次使用官方提供的centos镜像为基础:

[root@docker-server1 ~]# docker pull centos

[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash

[root@37220e5c8410 /]# yum install wget -y

[root@37220e5c8410 /]# cd /etc/yum.repos.d/

[root@37220e5c8410 yum.repos.d]# rm -rf ./* #更改yum 源

[root@37220e5c8410 yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

[root@37220e5c8410 yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

2.1.2:yum安装并配置nginx:

[root@37220e5c8410 yum.repos.d]# yum install nginx –y #yum安装nginx

[root@37220e5c8410 yum.repos.d]# yum install -y vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop #安装常用命令

2.1.3:关闭nginx后台运行:

[root@37220e5c8410 yum.repos.d]# vim /etc/nginx/nginx.conf #关闭nginx后台运行

user nginx;

worker_processes auto;

error_log /var/log/nginx/error.log;

pid /run/nginx.pid;

daemon off; #关闭后台运行

2.1.4:自定义web页面:

[root@37220e5c8410 yum.repos.d]# vim /usr/share/nginx/html/index.html

[root@37220e5c8410 yum.repos.d]# cat /usr/share/nginx/html/index.html

Docker Yum Nginx #自定义web界面

2.1.5:提交为镜像:

在宿主机基于容器ID 提交为镜像

[root@docker-server1 ~]# docker commit -m "nginx image" f5f8c13d0f9f jack/centos-nginx

sha256:7680544414220f6ff01e58ffc6bd59ff626af5dbbce4914ceb18e20f4ae0276a

2.1.6:带tag的镜像提交:

提交的时候标记tag号:

#标记tag号,生产当中比较长用,后期可以根据tag标记启动不同版本启动image启动

[root@docker-server1 ~]# docker commit -m "nginx image" f5f8c13d0f9f jack/centos-nginx:v1

sha256:ab9759679eb586f06e315971d28b88f0cd3e0895d2e162524ee21786b98b24e8

2.1.7:从自己镜像启动容器:

[root@docker-server1 ~]# docker run -d -p 80:80 --name my-centos-nginx jack/centos-nginx /usr/sbin/nginx

ce4ee8732a0c4c6a10b85f5463396b27ba3ed120b27f2f19670fdff3bf5cdb62

2.1.8:访问测试:

2.2:DockerFile制作yum版nginx镜像:

DockerFile可以说是一种可以被Docker程序解释的脚本,DockerFile是由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docke镜像,避免了重复手动制作镜像的麻烦,具体如下:

2.2.1:下载镜像并初始化系统:

[root@docker-server1 ~]# docker pull centos

[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash

[root@docker-server1 ~]# cd /opt/ #创建目录环境

[root@docker-server1 opt]# mkdir dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} -pv

#目录结构按照业务类型或系统类型等方式划分,方便后期镜像比较多的时候进行分类。

[root@docker-server1 opt]# cd dockerfile/web/nginx/

[root@docker-server1 nginx]# pwd

/opt/dockerfile/web/nginx

2.2.2:编写Dockerfile:

[root@docker-server1 nginx]# vim ./Dockerfile #生成的镜像的时候会在执行命令的当前目录查找Dockerfile文件,所以名称不可写错,而且D必须大写

#My Dockerfile

#"#"为注释,等于shell脚本的中#

#除了注释行之外的第一行,必须是From xxx (xxx是基础镜像)

From centos #第一行先定义基础镜像,后面的本地有效的镜像名,如果本地没有会从远程仓库下载,第一行很重要

#镜像维护者的信息

MAINTAINER Jack.Zhang 123456@qq.com

###########################其他可选参数##################################################

#USER #指定该容器运行时的用户名和UID,后续的RUN命令也会使用这面指定的用户执行

#WORKDIR /a

#WORKDIR b #指定工作目录,最终为/a/b

#VOLUME 设置主机挂载卷

#########################################################################################

#执行的命令,将编译安装nginx的步骤执行一遍

RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm

RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop

ADD nginx-1.10.3.tar.gz /usr/local/src/ #自动解压压缩包

RUN cd /usr/local/src/nginx-1.10.3 && ./configure --prefix=/usr/local/nginx --with-http_sub_module && make && make install

RUN cd /usr/local/nginx/

ADD nginx.conf /usr/local/nginx/conf/nginx.conf

RUN useradd nginx -s /sbin/nologin

RUN ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx

RUN echo "test nginx page" > /usr/local/nginx/html/index.html

EXPOSE 80 443 #向外开放的端口,多个端口用空格做间隔,启动容器时候-p需要使用此端向外映射,如: -p 8081:80,则80就是这里的80

CMD ["nginx"] #运行的命令,每个Dockerfile只能有一条,如果有多条则只有最后一条被执行

#如果在从该镜像启动容器的时候也指定了命令,那么指定的命令会覆盖Dockerfile构建的镜像里面的CMD命令,即指定的命令优先级更高,Dockerfile的优先级较低一些

2.2.3:准备源码包与配置文件:

[root@docker-server1 nginx]# cp /usr/local/nginx/conf/nginx.conf . #配置文件关闭后台运行

[root@docker-server1 nginx]# cp /usr/local/src/nginx-1.10.3.tar.gz . #nginx源码包

2.2.4:执行镜像构建:

[root@docker-server1 nginx]# docker build –t jack/nginx-1.10.3:v1 /opt/dockerfile/web/nginx/

2.2.5:构建完成:

可以清晰看到各个步骤执行的具体操作

 

2.2.6:查看是否生成本地镜像:

2.2.7:从镜像启动容器:

[root@docker-server1 nginx]# docker run -d -p 80:80 --name yum-nginx jack/nginx-1.10.3:v1 /usr/sbin/nginx

2.2.8:访问web界面:

2.2.9:编译过程中使用过的镜像:

2.3:手动制作编译版本nginx 镜像:

过程为在centos 基础镜像之上手动编译安装nginx,然后再提交为镜像。

2.3.1:下载镜像并初始化系统:

[root@docker-server1 ~]# docker pull centos

[root@docker-server1 ~]# docker run -it docker.io/centos /bin/bash

[root@86a48908bb97 /]# yum install wget -y

[root@86a48908bb97 /]# cd /etc/yum.repos.d/

[root@86a48908bb97 yum.repos.d]# rm -rf ./* #更改yum 源

[root@86a48908bb97 yum.repos.d]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

[root@86a48908bb97 yum.repos.d]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

2.3.2:编译安装nginx:

[root@86a48908bb97 yum.repos.d]# yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop #安装基础包

[root@86a48908bb97 yum.repos.d]# cd /usr/local/src/

[root@86a48908bb97 src]# wet http://nginx.org/download/nginx-1.10.3.tar.gz

[root@86a48908bb97 src]# tar xvf nginx-1.10.3.tar.gz

[root@86a48908bb97 src]# cd nginx-1.10.3

[root@86a48908bb97 nginx-1.10.3]# ./configure --prefix=/usr/local/nginx --with-http_sub_module

[root@86a48908bb97 nginx-1.10.3]# make && make install

[root@86a48908bb97 nginx-1.10.3]# cd /usr/local/nginx/

2.3.3:关闭nginx后台运行:

[root@86a48908bb97 nginx]# vim conf/nginx.conf

user nginx;

worker_processes auto;

daemon off;

[root@86a48908bb97 nginx]# ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx #创建软连

2.3.4:创建用户及授权:

[root@86a48908bb97 nginx]# useradd nginx -s /sbin/nologin

[root@86a48908bb97 nginx]# chown nginx.nginx /usr/local/nginx/ -R

2.3.5:自定义web界面:

[root@86a48908bb97 nginx]# echo "My Nginx Test Page" > /usr/local/nginx/html/index.html

2.3.6:提交为镜像:

[root@docker-server1 ~]# docker commit -m "test nginx" 86a48908bb97 jack/nginx-test-image

sha256:fce6e69410e58b8e508c7ffd2c5ff91e59a1144847613f691fa5e80bb68efbfa

[root@docker-server1 ~]# docker commit -m "test nginx" 86a48908bb97 jack/nginx-test-image:v1

sha256:474cad22f28b1e6b17898d87f040dc8d1f3882e2f4425c5f21599849a3d3c6a2

2.3.:7:从自己的镜像启动容器:

[root@docker-server1 ~]# docker run -d -p 80:80 --name my-centos-nginx jack/nginx-test-image:v1 /usr/sbin/nginx

8042aedec1d6412a79ac226c9289305087fc062b0087955a3a0a609c891e1122

备注: -name是指定容器的名称,-d是后台运行,-p是端口映射,jack/nginx-test-image是xx仓库下的xx镜像的xx版本,可以不加版本,不加版本默认是使用latest,最后面的nginx是运行的命令,即镜像里面要运行一个nginx命令,所以才有了前面将/usr/local/nginx/sbin/nginx软连接到/usr/sbin/nginx,目的就是为了让系统可以执行此命令。

2.3.8:访问测试:

2.3.9:查看Nginx访问日志:

2.4:自定义tomcat镜像:

基于官方提供的centos 7.2.1511基础镜像构建JDK和tomcat镜像,先构建JDK镜像,然后再基于JDK镜像构建tomcat镜像。

2.4.1:构建JDK镜像:

2.4.1.1:下载基础镜像Centos:

[root@docker-server1 ~]# docker pull centos

2.4.1.2:执行构建JDK 镜像:

[root@docker-server1 ~]# mkdir /opt/dockerfile/{web/{nginx,tomcat,jdk,apache},system/{centos,ubuntu,redhat}} -pv

[root@docker-server1 ~]# cd /opt/dockerfile/web/jdk/

[root@docker-server1 jdk]# vim Dockerfile

#JDK Base Image

FROM centos-7.5-base:latest

MAINTAINER zhangshijie "zhangshijie@300.cn"

ADD jdk-8u162-linux-x64.tar.gz /usr/local/src/

RUN ln -sv /usr/local/src/jdk1.8.0_162 /usr/local/jdk

ADD profile /etc/profile

ENV JAVA_HOME /usr/local/jdk

ENV JRE_HOME $JAVA_HOME/jre

ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/

ENV PATH $PATH:$JAVA_HOME/bin

RUN rm -rf /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone

2.4.1.3:上传JDK压缩包和profile文件:

将JDK 压缩包上传到Dockerfile当前目录,然后执行构建:

2.4.1.4:执行构建镜像:

2.4.1.4.1:通过脚本构建:

[root@docker-server1 jdk]# cat build-command.sh

#!/bin/bash

docker build -t centos-7.5-jdk:v1 .

2.4.1.4.2:执行构建:

2.4.1.5:镜像构建完成:

2.4.1.6:从镜像启动容器:

[root@docker-server1 jdk]# docker run -it jack/ceontos-jdk bash

2.4.1.7:将镜像上传到harbor:

[root@docker-server1 jdk]# docker push 192.168.10.205/centos/centos-7.2.1511-jdk1.7.0.79

2.4.1.8:镜像仓库验证:

2.4.1.9:从其他docker客户端下载镜像并启动JDK容器:

#启动的时候本地没有镜像,会从仓库下载,然后从镜像启动容器

2.4.2:从JDK镜像构建tomcat 8 Base镜像:

2.4.2.1:编辑Dockerfile:

[root@docker-server1 tomcat8-base]# pwd

/opt/dockerfile/system/centos/tomcat8-base

[root@docker-server1 tomcat8-base]# cat Dockerfile

#Tomcat Base Image

FROM centos-7.5-jdk:v1

RUN useradd www -u 2000

#ADD del_tomcatlog.sh /root/script

#RUN echo "0 2 * * * /bin/bash /root/script/del_tomcatlog.sh &> /dev/null" >> /var/spool/cron/root

#env settinf

ENV TZ "Asia/Shanghai"

ENV LANG en_US.UTF-8

ENV TERM xterm

ENV TOMCAT_MAJOR_VERSION 8

ENV TOMCAT_MINOR_VERSION 8.0.49

ENV CATALINA_HOME /apps/tomcat

ENV APP_DIR ${CATALINA_HOME}/webapps

#tomcat settinf

RUN mkdir /apps

ADD apache-tomcat-8.0.49.tar.gz /apps

RUN ln -sv /apps/apache-tomcat-8.0.49 /apps/tomcat

2.4.2.2:上传tomcat 压缩包:

[root@docker-server1 tomcat8-base]# ll apache-tomcat-8.0.49.tar.gz

-rw-r--r-- 1 root root 9413703 Jul 2 10:06 apache-tomcat-8.0.49.tar.gz

2.4.2.3:通过脚本构建tomcat 基础镜像:

[root@docker-server1 tomcat8-base]# cat build-command.sh

#!/bin/bash

docker build -t tomcat-base:v1 .

#执行构建:

2.4.2.4:验证镜像构建完成:

2.4.3:构建业务镜像1:

创建tomcat-app1和tomcat-app2两个目录,代表不同的两个基于tomcat的业务。

2.4.3.1:准备Dockerfile:

[root@docker-server1 tomcat-app1]# pwd

/opt/dockerfile/system/centos/tomcat-app1

[root@docker-server1 tomcat-app1]# cat Dockerfile

#Tomcat Web Image

FROM tomcat-base:v1

ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

ADD myapp/* /apps/tomcat/webapps/myapp/

RUN chown www.www /apps/ -R

CMD ["/apps/tomcat/bin/run_tomcat.sh"]

EXPOSE 8080 8009

2.4.3.2:准备自定义myapp页面:

[root@docker-server1 tomcat-app1]# mkdir myapp

[root@docker-server1 tomcat-app1]# echo "Tomcat Web Page1" > myapp/index.html

[root@docker-server1 tomcat-app1]# cat myapp/index.html

Tomcat Web Page1

2.4.3.3:准备容器启动执行脚本:

[root@docker-server1 tomcat-app1]# cat run_tomcat.sh

#!/bin/bash

echo "1.1.1.1 abc.test.com" >> /etc/hosts

echo "nameserver 223.5.5.5" > /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"

su - www -c "tail -f /etc/hosts"

2.4.3.4:准备构建脚本:

[root@docker-server1 tomcat-app1]# cat build-command.sh

#!/bin/bash

docker build -t tomcat-web:app1 .

2.4.3.5:执行构建:

2.4.3.6:从镜像启动容器测试:

[root@docker-server1 tomcat-app1]# docker run -it -d -p 8888:8080 tomcat-web:app1

d03fd22cce891a29b590715bde9bd6fc314dd5ae3af178e8f48b215aeb878d9f

2.4.3.7:访问测试:

2.4.4.:构建业务镜像2:

2.4.4.1:准备Dockerfile:

[root@docker-server1 tomcat-app2]# pwd

/opt/dockerfile/system/centos/tomcat-app2

[root@docker-server1 tomcat-app2]# cat Dockerfile

#Tomcat Web2 Image

FROM tomcat-base:v1

ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh

ADD myapp/* /apps/tomcat/webapps/myapp/

RUN chown www.www /apps/ -R

CMD ["/apps/tomcat/bin/run_tomcat.sh"]

EXPOSE 8080 8009

2.4.4.2:准备自定义页面:

[root@docker-server1 tomcat-app2]# mkdir myapp

[root@docker-server1 tomcat-app2]# echo "Tomcat Web Page2" > myapp/index.html

[root@docker-server1 tomcat-app2]# cat myapp/index.html

Tomcat Web Page2

2.4.4.3:准备容器启动脚本:

[root@docker-server1 tomcat-app2]# cat run_tomcat.sh

#!/bin/bash

echo "1.1.1.1 abc.test.com" >> /etc/hosts

echo "nameserver 223.5.5.5" > /etc/resolv.conf

su - www -c "/apps/tomcat/bin/catalina.sh start"

su - www -c "tail -f /etc/hosts"

2.4.4.4:准备构建脚本:

[root@docker-server1 tomcat-app2]# cat build-command.sh

#!/bin/bash

docker build -t tomcat-web:app2 .

2.4.4.5:执行构建:

2.4.4.6:从镜像启动容器:

[root@docker-server1 tomcat-app2]# docker run -it -d -p 8889:8080 tomcat-web:app2

4846126780f6bdb374f7d4a7a91a16c4af211a9a01b11db629751a597dc55e08

2.4.4.7:访问测试:

2.5:构建haproxy镜像:

2.5.1:准备Dockerfile:

[root@docker-server1 haproxy]# pwd

/opt/dockerfile/system/centos/haproxy

[root@docker-server1 haproxy]# cat Dockerfile

#Haproxy Base Image

FROM centos-7.5-base:latest

MAINTAINER zhangshijie "zhangshijie@300.cn"

RUN yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools vim iotop bc zip unzip zlib-devel lrzsz tree screen lsof tcpd

ump wget ntpdate -yADD haproxy-1.8.12.tar.gz /usr/local/src/

RUN cd /usr/local/src/haproxy-1.8.12 && make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy

&& make install PREFIX=/usr/local/haproxy && cp haproxy /usr/sbin/ && mkdir /usr/local/haproxy/runADD haproxy.cfg /etc/haproxy/

ADD run_haproxy.sh /usr/bin

EXPOSE 80 9999

CMD ["/usr/bin/run_haproxy.sh"]

2.5.2:准备haproxy源码文件:

[root@docker-server1 haproxy]# ll haproxy-1.8.12.tar.gz

-rw-r--r-- 1 root root 2059925 Jun 30 23:32 haproxy-1.8.12.tar.gz

2.5.3:准备haproxy配置文件:

[root@docker-server1 haproxy]# cat haproxy.cfg

global

chroot /usr/local/haproxy

#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin

uid 99

gid 99

daemon

nbproc 1

pidfile /usr/local/haproxy/run/haproxy.pid

log 127.0.0.1 local3 info

defaults

option http-keep-alive

option forwardfor

mode http

timeout connect 300000ms

timeout client 300000ms

timeout server 300000ms

listen stats

mode http

bind 0.0.0.0:9999

stats enable

log global

stats uri /haproxy-status

stats auth haadmin:q1w2e3r4ys

listen web_port

bind 0.0.0.0:80

mode http

log global

balance roundrobin

server web1 192.168.100.101:8888 check inter 3000 fall 2 rise 5

server web2 192.168.100.101:8889 check inter 3000 fall 2 rise 5

2.5.4:准备构建脚本:

[root@docker-server1 haproxy]# cat build-command.sh

#!/bin/bash

docker build -t centos-haproxy-base:7.5-1.8.12 .

2.5.5:执行构建haproxy镜像:

2.5.6:从镜像启动容器:

[root@docker-server1 haproxy]# docker run -it -d -p80:80 -p9999:9999 centos-haproxy-base:7.5-1.8.12

0b9bfdf14beee6008b259efc2d9d4fe74edee957af67da055f1dd18c5a44b4fb

2.5.7:web访问验证:

2.5.8:访问haproxy控制端:

2.6:本地镜像上传至官方docker 仓库:

#将自制的镜像上传至docker仓库;https://hub.docker.com/

2.6.1:准备账户:

登录到docker hub创建官网创建账户,登录后点击settings完善账户信息:

2.6.2:填写账户基本信息:

2.6.3:在虚拟机使用自己的账号登录:

[root@linux-docker ~]# docker login https://hub.docker.com/

2.6.4:查看认证信息:

#登录成功之后会在当前目录生成一个隐藏文件用于保存登录认证信息

2.6.5:给镜像做tag并开始上传:

[root@linux-docker ~]# docker images #查看镜像ID

#为镜像做标记

[root@linux-docker ~]# docker tag 678e2f074b0d docker.io/zhangshijie/centos-nginx

#上传至仓库

[root@linux-docker ~]# docker login #默认即登录到docker 官方网站

[root@linux-docker ~]# docker push docker.io/zhangshijie/centos-nginx

#上传过程中

2.6.6:上传完成

2.6.7:到docker官网验证:

2.6.8:更换到其他docker服务器下载镜像:

2.6.9:从镜像启动一个容器:

三:Docker 数据管理:

3.1:数据类型:

Docker的镜像是分层设计的,底层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中,如果要将写入的数据永久生效,需要将其提交为一个镜像然后通过这个镜像在启动实例,然后就会给这个启动的实例添加一层可读写的文件系统,目前Docker的数据类型分为两种,一是数据卷,二是数据容器,数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上

3.1.1:什么是数据卷(data volume):

数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中使用。

3.1.1.1:创建APP目录并生成web页面:

[root@docker-server1 ~]# mkdir testapp

[root@docker-server1 ~]# echo "Test App Page" > testapp/index.html

[root@docker-server1 ~]# cat testapp/index.html

Test App Page

3.1.1.2:启动容器并验证数据:

#注意使用-v参数,将宿主机目录映射到容器内部,web2的ro标示在容器内对该目录只读,默认是可读写的:

[root@docker-server1 ~]# docker run -d --name web1 -v /root/testapp/:/apps/tomcat/webapps/testapp -p 8811:8080 tomcat-web:app1

d982cbb2524680f20f6edef7347abf5fbc1ac587b6de1a37b99ddc91fc26be76

[root@docker-server1 ~]# docker run -d --name web2 -v /root/testapp/:/apps/tomcat/webapps/testapp:ro -p 8812:8080 tomcat-web:app2

46698f391a1c2ebf6e4f959ee0f9277ff2a301afb4b5ec3b61dbdd5717f33364

3.1.1.3:进入到容器内测试写入数据:

3.1.1.4:宿主机验证:

3.1.1.5:web界面访问:

3.1.1.6:在宿主机修改数据:

[root@docker-server1 ~]# echo "1111" >> testapp/index.html

[root@docker-server1 ~]# cat testapp/index.html

Test App Page

docker

1111

3.1.1.7:web端访问验证数据:

3.1.1.8:删除容器:

#创建容器的时候指定参数-v,可以删除/var/lib/docker/containers/的容器数据目录,默认不删除,但是不能删除数据卷的内容,如下:

3.1.1.9:验证宿主机的数据:

3.1.1.10:数据卷的特点及使用:

1、数据卷是目录或者文件,并且可以在多个容器之间共同使用。

2、对数据卷更改数据容器里面会立即更新。

3、数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。

4、在容器里面的写入数据不会影响到镜像本身。

3.1.2:文件挂载:

文件挂载用于很少更改文件内容的场景,比如nginx 的配置文件、tomcat的配置文件等。

3.1.2.1:创建容器并挂载文件:

[root@docker-server1 ~]# ll testapp/catalina.sh

-rwxr-xr-x 1 root root 23705 Jul 3 14:06 testapp/catalina.sh

#自定义JAVA 选项:

JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"

[root@docker-server1 ~]# docker run -d --name web1 -v /root/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -p 8811:8080 tomcat-web:app1

ef0de0f5628f2137eca7dfb69fe86947029586beb517cd6077086f8feda2c40d

3.1.2.2:验证参数生效:

3.1.2.3:进入容器测试文件读写:

3.1.2.3:如何一次挂载多个目录:

多个目录要位于不同的目录下

[root@docker-server1 ~]# docker run -d --name web1 -v /root/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /root/testapp:/apps/tomcat/webapps/testapp -p 8811:8080 t

omcat-web:app19c7a503888f07a880db7a1ffe39044176a3bf0a32286c28f1aee9c3bd9ca567e

[root@docker-server1 ~]#

[root@docker-server1 ~]# docker run -d --name web2 -v /root/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /root/testapp:/apps/tomcat/webapps/testapp -p 8812:8080

tomcat-web:app2f63effc2a4e9b4869f1c8e8267dd1717cf846e6d672b68f474bf4b569aed2cfb

3.1.2.4:数据卷使用场景:

1、日志输出

2、静态web页面

3、应用配置文件

4、多容器间目录或文件共享

3.1.3:数据卷容器:

数据卷容器最大的功能是可以让数据在多个docker容器之间共享,即可以让B容器访问A容器的内容,而容器C也可以访问A容器的内容,即先要创建一个后台运行的容器作为Server,用于卷提供,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为client端:

3.1.3.1:启动一个卷容器Server:

先启动一个容器,并挂载宿主机的数据目录:

[root@docker-server1 ~]# docker run -d --name volume-docker -v /root/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /root/testapp:/apps/tomcat/webapps/testapp tomcat-web:app2

aa56f415c4d27bdd68f5f88d5dd2e8ac499177a606cdd1dccc09079b59ee9a72

3.1.3.2:启动端容器Client:

[root@docker-server1 ~]# docker run -d --name web1 -p 8801:8080 --volumes-from volume-docker tomcat-web:app1

241e9559f2bc7a8453a0917c1be25d6649c30bf2d6ce929fd7e03b0dc4215543

[root@docker-server1 ~]#

[root@docker-server1 ~]# docker run -d --name web2 -p 8802:8080 --volumes-from volume-docker tomcat-web:app2

82b728184355dfb9f9be6dfad51ebfa9d3429ba1133e708cb56273fb1a9b9794

3.1.3.3:进入容器测试读写:

读写权限依赖于源数据卷Server容器

3.1.3.4:关闭卷容器Server测试能否启动新容器:

[root@docker-server1 ~]# docker stop volume-docker

volume-docker

[root@docker-server1 ~]# docker run -d --name web3 -p 8803:8080 --volumes-from volume-docker tomcat-web:app2

#可以创建新容器

3.1.3.6:测试删除源卷容器Server创建容器:

[root@docker-server1 ~]# docker rm -fv volume-docker

volume-docker

[root@docker-server1 ~]# docker run -d --name web4 -p 8804:8080 --volumes-from volume-docker tomcat-web:app2

docker: Error response from daemon: No such container: volume-docker.

See 'docker run --help'.

3.1.3.7:测试之前的容器是否正常:

已经运行的容器不受任何影响

3.1.3.8:重新创建容器卷Server:

[root@docker-server1 ~]# docker run -d --name volume-docker -v /root/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v /root/testapp:/apps/tomcat/webapps/testapp tomcat

-web:app2f0b578c60ad3a2550ad4ca937a8abd778e9dceab3f5af71739ef1e72051f2626

[root@docker-server1 ~]# docker run -d --name web4 -p 8804:8080 --volumes-from volume-docker tomcat-web:app2

f9e118640f7baeb3bf6619af3f145955194594ce99eb6d7edfa93f5d5d652439

#在当前环境下,即使把提供卷的容器Server删除,已经运行的容器Client依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器Server创建后即可正常创建卷容器Client,此方式可以用于线上数据库、共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用

#数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于NFS共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性。

四:网络部分:

主要介绍docker 网络相关知识。

4.1:docker结合负载实现网站高可用:

4.1.1:整体规划图:

下图为一个小型的网络架构图,其中nginx 使用docker 运行。

4.1.2:安装并配置keepalived:

4.1.2.1: Server1 安装并配置:

[root@docker-server1 ~]# yum install keepalived –y

[root@docker-server1 ~]# cat /etc/keepalived/keepalived.conf

vrrp_instance MAKE_VIP_INT {

state MASTER

interface eth0

virtual_router_id 1

priority 100

advert_int 1

unicast_src_ip 192.168.10.205

unicast_peer {

192.168.10.206

}

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.10.100/24 dev eth0 label eth0:1

}

}

[root@docker-server1~]# systemctl restart keepalived && systemctl enable keepalived

4.1.2.2:Server2 安装并配置:

[root@docker-server2 ~]# yum install keepalived –y

[root@docker-server2 ~]# cat /etc/keepalived/keepalived.conf

vrrp_instance MAKE_VIP_INT {

state BACKUP

interface eth0

virtual_router_id 1

priority 50

advert_int 1

unicast_src_ip 192.168.10.206

unicast_peer {

192.168.10.205

}

authentication {

auth_type PASS

auth_pass 1111

}

virtual_ipaddress {

192.168.10.100/24 dev eth0 label eth0:1

}

}

[root@docker-server2 ~]# systemctl restart keepalived && systemctl enable keepalived

4.1.3:安装并配置haproxy:

4.1.3.1.:各服务器配置内核参数:

[root@docker-server1 ~]# sysctl -w net.ipv4.ip_nonlocal_bind=1

[root@docker-server2 ~]# sysctl -w net.ipv4.ip_nonlocal_bind=1

4.1.3.2:Server1安装并配置haproxy:

[root@docker-server1 ~]# yum install haproxy –y

[root@docker-server1 ~]# cat /etc/haproxy/haproxy.cfg

global

maxconn 100000

uid 99

gid 99

daemon

nbproc 1

log 127.0.0.1 local0 info

defaults

option http-keep-alive

#option forwardfor

maxconn 100000

mode tcp

timeout connect 500000ms

timeout client 500000ms

timeout server 500000ms

listen stats

mode http

bind 0.0.0.0:9999

stats enable

log global

stats uri /haproxy-status

stats auth haadmin:q1w2e3r4ys

#================================================================

frontend docker_nginx_web

bind 192.168.10.100:80

mode http

default_backend docker_nginx_hosts

backend docker_nginx_hosts

mode http

#balance source

balance roundrobin

server 192.168.10.205 192.168.10.205:81 check inter 2000 fall 3 rise 5

server 192.168.10.206 192.168.10.206:81 check inter 2000 fall 3 rise 5

4.1.3.3:Server2安装并配置haproxy:

[root@docker-server2 ~]# yum install haproxy –y

[root@docker-server2 ~]# cat /etc/haproxy/haproxy.cfg

global

maxconn 100000

uid 99

gid 99

daemon

nbproc 1

log 127.0.0.1 local0 info

defaults

option http-keep-alive

#option forwardfor

maxconn 100000

mode tcp

timeout connect 500000ms

timeout client 500000ms

timeout server 500000ms

listen stats

mode http

bind 0.0.0.0:9999

stats enable

log global

stats uri /haproxy-status

stats auth haadmin:q1w2e3r4ys

#================================================================

frontend docker_nginx_web

bind 192.168.10.100:80

mode http

default_backend docker_nginx_hosts

backend docker_nginx_hosts

mode http

#balance source

balance roundrobin

server 192.168.10.205 192.168.10.205:81 check inter 2000 fall 3 rise 5

server 192.168.10.206 192.168.10.206:81 check inter 2000 fall 3 rise 5

4.1.3.4:各服务器别分启动haproxy:

[root@docker-server1 ~]# systemctl enable haproxy

Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service.

[root@docker-server1 ~]# systemctl restart haproxy

[root@docker-server2 ~]# systemctl enable haproxy

Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service.

[root@docker-server2 ~]# systemctl restart haproxy

4.1.4:服务器启动nginx容器并验证:

4.1.4.1:Server1 启动Nginx 容器:

从本地Nginx 镜像启动一个容器,并指定端口,默认协议是tcp方式

[root@docker-server1 ~]# docker rm -f `docker ps -a -q` #先删除之前所有的容器

[root@docker-server1 ~]# docker run --name nginx-web1 -d -p 81:80 jack/nginx-1.10.3:v1 nginx

5410e4042f731d2abe100519269f9241a7db2b3a188c6747b28423b5a584d020

4.1.4.2:验证端口:

4.1.4.3:验证web访问:

4.1.4.3:Server2 启动nginx 容器:

[root@docker-server2 ~]# docker run --name nginx-web1 -d -p 81:80 jack/nginx-1.10.3:v1 nginx

84f2376242e38d7c8ba7fabf3134ac0610ab26358de0100b151df6a231a2b56a

4.1.4.4:验证端口:

4.1.4.5:验证web访问:

4.1.4.6:访问VIP:

4.1.4.7:Server1 haproxy状态页面:

4.1.4.8:Server2 haproxy状态页面:

日志可以在nginx 里面通过syslog传递给elk收集

指定IP、协议和端口:

[root@linux-docker ~]# docker run --name nginx-web -d -p 192.168.10.22:80:80/tcp jack/centos-nginx nginx

[root@linux-docker ~]# docker run --name nginx-web-udp -d -p 192.168.10.22:54:53/udp jack/centos-nginx nginx

4.2:容器之间的互联:

4.2.1:通过容器名称互联:

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如一个业务前端静态页面是使用nginx,动态页面使用的是tomcat,由于容器在启动的时候其内部IP地址是DHCP 随机分配的,所以如果通过内部访问的话,自定义名称是相对比较固定的,因此比较适用于此场景。

#此方式最少需要两个容器之间操作:

#

4.2.1.1:先创建第一个容器,后续会使用到这个容器的名称:

[root@docker-server1 ~]# docker run --name nginx-1 -d -p 8801:80 jack/nginx-1.10.3:v1 nginx

c045c82e85bd620eb9444275b135634a9248760e2061505a1c8b4167e9b24b3d

4.2.1.2:查看当前hosts文件内容:

[root@c045c82e85bd /]# cat /etc/hosts

127.0.0.1 localhost

::1 localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.2 c045c82e85bd

4.2.1.3:创建第二个容器:

[root@docker-server1 ~]# docker run -d --name nginx-2 --link nginx-1 -p 8802:80 jack/centos-nginx nginx

23813883ed977d4cc1e50355adaf37564832fc90b4b8b307866c1c99c8256c57

4.2.1.4:查看第二个容器的hosts文件内容:

[root@23813883ed97 /]# cat /etc/hosts

127.0.0.1 localhost

::1 localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.2 nginx-1 c045c82e85bd #第一个容器的名称和ID,只会添加到本地不会添加到对方

172.17.0.3 23813883ed97

4.2.1.5:检测通信:

4.2.2:通过自定义容器别名互联:

上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更,只要不更改别名即可,具体如下:

命令格式:

docker run -d --name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell命令

4.2.2.1:启动第三个容器:

[root@docker-server1 ~]# docker run -d --name nginx-3 --link nginx-1:custom_vm_name -p 8803:80 jack/centos-nginx /usr/sbin/nginx

2ed3016f90fd735c66ae79e039481c1576dd63f67a7861358f2825b234806b0c

4.2.2.2:查看当前容器的hosts文件:

[root@docker-server1 ~]# ./docker-in.sh nginx-3

[root@2ed3016f90fd /]# cat /etc/hosts

127.0.0.1 localhost

::1 localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

172.17.0.2 custom_vm_name c045c82e85bd nginx-1

172.17.0.4 2ed3016f90fd

4.2.2.3:检查自定义别名通信:

#查看当前docke的网卡信息:

[root@linux-docker ~]# docker network list

NETWORK ID NAME DRIVER SCOPE

b34d891b24aa bridge bridge local #桥接,使用自定义IP

cf400b2de47a host host local #不获取IP直接使用物理机IP,并监听物理机IP监听端口

697beb7f9a6b none null local #

#host网络使用方式

[root@linux-docker ~]# docker run -it -d --name nginx-host-test --net=host jack/centos-nginx nginx

#验证端口

#web访问验证:

4.2.3:通过网络夸宿主机互联:

同一个宿主机之间的各容器之间是可以直接通信的,但是如果访问到另外一台宿主机的容器呢?

4.2.3.1:docker网络类型:

Docker 的网络有四种类型,下面将介绍每一种类型的具体工作方式:

Bridge模式,使用参数 –net=bridge 指定,不指定默认就是bridge模式。

4.2.3.1.1:Host 模式:

Host 模式,使用参数 –net=host 指定。

启动的容器如果指定了使用host模式,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器的其他资源们必须文件系统、系统进程等还是和宿主机保持隔离。

此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。

为避免端口冲突,先删除所有的容器:

先确认宿主机端口没有占用80端口:

#启动一个新容器,并指定网络模式为host

[root@docker-server1 ~]# docker run -d --name net_host --net=host jack/centos-nginx nginx

abdc7c9c1e984278bc9344393edf493c3cb09929afb83e34bcd21179d226b61a

#验证网络信息:

#访问宿主机验证:

4.2.3.1.2:none模式:

None模式,使用参数 –net=none 指定

在使用none 模式后,Docker 容器不会进行任何网络配置,其没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用,

命令使用方式:

[root@docker-server1 ~]# docker run -d --name net_none --net=none jack/centos-nginx nginx

143ce15733c1961bf6e23989cbd7d76fc9f9297dc7f11e610ae30c418c21297c

4.2.3.1.3:Container模式:

Container模式,使用参数 –net=container:名称或ID 指定。

使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个已经存在的被指定的容器东西IP和端口范围,因此这个容器的端口不能和被指定的端口冲突,除了网络之外的文件系统、进程信息等仍然保持 相互隔离,两个容器的进程可以通过lo网卡社保通信。

[root@docker-server1 ~]# docker run -d --name nginx-web1 jack/nginx-1.10.3:v1 nginx

95d22a5d36c18544af47373cc227a1679f239e790f86907d310d13ef4eb85d5e

[root@docker-server1 ~]# docker run -it --name net_container --net=container:nginx-web1 jack/centos-nginx bash #直接使用对方的网络,较少使用

4.2.3.1.4:bridge模式:

docker的默认模式即不指定任何模式就是bridge模式,也是使用比较多的模式,此模式创建的容器会为每一个容器分配自己的网络 IP等信息,并将容器连接到一个虚拟网桥与外界通信。

[root@docker-server1 ~]# docker run -d --name net_bridge jack/nginx-1.10.3:v1 /usr/sbin/nginx

58e251cdb17fc309ee364c332549b434f4d51019b793702e81b5edb1ff701a7c

4.2.3.2:docker夸主机互联之简单实现:

夸主机互联是说A宿主机的容器可以访问B主机上的容器,但是前提是保证各宿主机之间的网络是可以相互通信的,然后各容器才可以通过宿主机访问到对方的容器,实现原理是在宿主机做一个网络路由就可以实现A宿主机的容器访问B主机的容器的目的,复杂的网络或者大型的网络可以使用google开源的k8s进行互联。

4.2.3.2.1:修改各宿主机网段:

Docker的默认网段是172.17.0.x/24,而且每个宿主机都是一样的,因此要做路由的前提就是各个主机的网络不能一致,具体如下:

问避免影响,先在各服务器删除之前穿件的所有容器。

# docker rm -f `docker ps -a -q`

4.2.3.2.2:服务器A更改网段:

[root@linux-docker1 ~]# vim /usr/lib/systemd/system/docker.service

18 ExecStart=/usr/bin/dockerd-current --bip=172.16.10.1/24 \

4.2.3.2.3:重启docker服务并验证网卡:

[root@linux-docker1 ~]# systemctl daemon-reload

[root@linux-docker1 ~]# systemctl restart docker

验证网卡:

4.2.3.2.4:服务器B更改网段:

[root@linux-docker2 ~]# vim /usr/lib/systemd/system/docker.service

18 ExecStart=/usr/bin/dockerd-current --bip=172.16.20.1/24 \

[root@linux-docker2 ~]# systemctl daemon-reload

[root@linux-docker2 ~]# systemctl restart docker

4.2.3.2.5:验证网卡:

4.2.3.3:在两个宿主机分别启动一个实例:

#Server1:

[root@docker-server1 ~]# docker run -d --name test-net-vm jack/nginx-1.10.3:v1 nginx

5d625a868718656737d452d6e57cd23a8a9a1cc9d2e8f76057f1977da2b52a60

#Server2:

[root@docker-server2 ~]# docker run -d --name test-net-vm jack/nginx-1.10.3:v1 nginx

ce8fbe4c1d6b5515136ac280f87e6c03884daa35996e996f124ac7056f609e0c

4.2.3.4:添加静态路由:

在各宿主机添加静态路由,网关指向对方的IP:

3.2.3.4.1: Server1 添加静态路由:

[root@docker-server1 ~]# iptables -A FORWARD -s 192.168.10.0/24 -j ACCEPT

[root@docker-server1 ~]# route add -net 172.16.20.0/24 gw 192.168.10.206 #ping对方容器IP

4.2.3.4.2:server2 添加静态路由:

[root@docker-server2 ~]# iptables -A FORWARD -s 192.168.10.0/24 -j ACCEPT

[root@docker-server2 ~]# route add -net 172.16.10.0/24 gw 192.168.10.205 #ping对方容器IP

4.2.3.4.3:抓包分析

[root@linux-docker2 ~]# tcpdump -i eth0 -vnn icmp

4.2.3.5:测试容器间互联:

4.2.3.5.1:宿主机A到宿主机B容器测试:

4.2.3.5.2:宿主机B到宿主机A容器测试:

五:Docker仓库之单机Docker Registry:

Docker Registry作为Docker的核心组件之一负责镜像内容的存储与分发,客户端的docker pull以及push命令都将直接与registry进行交互,最初版本的registry 由Python实现,由于设计初期在安全性,性能以及API的设计上有着诸多的缺陷,该版本在0.9之后停止了开发,由新的项目distribution(新的docker register被称为Distribution)来重新设计并开发下一代registry,新的项目由go语言开发,所有的API,底层存储方式,系统架构都进行了全面的重新设计已解决上一代registry中存在的问题,2016年4月份rgistry 2.0正式发布,docker 1.6版本开始支持registry 2.0,而八月份随着docker 1.8 发布,docker hub正式启用2.1版本registry全面替代之前版本 registry,新版registry对镜像存储格式进行了重新设计并和旧版不兼容,docker 1.5和之前的版本无法读取2.0的镜像,另外,Registry 2.4版本之后支持了回收站机制,也就是可以删除镜像了,在2.4版本之前是无法支持删除镜像的,所以如果你要使用最好是大于Registry 2.4版本的。

本部分将介绍通过官方提供的docker registry镜像来简单搭建一套本地私有仓库环境。

5.1:下载docker registry镜像:

[root@docker-server1 ~]# docker pull registry

5.2:搭建单机仓库:

5.2.1:创建授权使用目录:

[root@docker-server1 ~]# mkdir /docker/auth #创建一个授权使用目录

5.2.2:创建用户:

[root@docker-server1 ~]# cd /docker

[root@docker-server1 docker]# docker run --entrypoint htpasswd registry -Bbn jack 123456 > auth/htpasswd #创建一个用户并生成密码

5.2.3:验证用户名密码:

[root@docker-server1 docker]# cat auth/htpasswd

jack:$2y$05$8W2aO/2RXMrMzw/0M5pig..QXwUh/m/XPoW5H/XxloLLRDTepVGP6

5.2.4:启动docker registry:

[root@docker-server1 docker]# docker run -d -p 5000:5000 --restart=always --name registry1 -v /docker/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registryce659e85018bea3342045f839c43b66de1237ce5413c0b6b72c0887bece5325a

5.2.5:验证端口和容器:

5.2.6:测试登录仓库:

5.2.6.1:报错如下:

5.2.6.2:解决方法:

编辑各docker 服务器/etc/sysconfig/docker 配置文件如下:

[root@docker-server1 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald'

9 ADD_REGISTRY='--add-registry 192.168.10.205:5000'

10 INSECURE_REGISTRY='--insecure-registry 192.168.10.205:5000'

[root@docker-server1 ~]# systemctl restart docker

[root@docker-server2 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald'

5 if [ -z "${DOCKER_CERT_PATH}" ]; then

6 DOCKER_CERT_PATH=/etc/docker

7 fi

8

9 ADD_REGISTRY='--add-registry 192.168.10.205:5000'

10 INSECURE_REGISTRY='--insecure-registry 192.168.10.205:5000'

[root@docker-server2 ~]# systemctl restart docker

5.2.6.3:验证各docker 服务器登录:

#server1:

#server2:

5.2.7:在Server1登录后上传镜像:

5.2.7.1:镜像打tag:

[root@docker-server1 ~]# docker tag jack/nginx-1.10.3:v1 192.168.10.205:5000/jack/nginx-1.10.3:v1

5.2.7.2:上传镜像:

5.2.8:Server 2下载镜像并启动容器:

5.2.8.1:登录并从docker registry下载镜像:

[root@docker-server2 ~]# docker images

REPOSITORY TAG MAGE ID CREATED SIZE

[root@docker-server2 ~]# docker login 192.168.10.205:5000

Username (jack): jack

Password:

Login Succeeded

[root@docker-server2 ~]# docker pull 192.168.10.205:5000/jack/nginx-1.10.3:v1

5.2.8.2:验证镜像下载成功:

5.2.8.3:从下载的镜像启动容器:

[root@docker-server2 ~]# docker run -d --name docker-registry -p 80:80 192.168.10.205:5000/jack/nginx-1.10.3:v1 nginx

2ba24f28362e1b039fbebda94a332111c2882aa06987463ae033c630f5c9927c

5.2.8.4:访问测试:

六:docker仓库之分布式 Harbor

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由vmware开源,其通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry中, 确保数据和知识产权在公司内部网络中管控,另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等,官网地址:https://vmware.github.io/harbor/cn/,官方github地址:https://github.com/vmware/harbor

6.1:Harbor功能官方介绍:

基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。

镜像复制:镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。

图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。

AD/LDAP 支:Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。

审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。

国际化:已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。

RESTful API - RESTful API :提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。

部署简单:提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备。

6.2:安装Harbor:

下载地址:https://github.com/vmware/harbor/releases

安装文档:https://github.com/vmware/harbor/blob/master/docs/installation_guide.md

6.2.1:服务器1安装docker:

本次使用当前harbor最新的稳定版本1.2.2离线安装包,具体名称为harbor-offline-installer-v1.2.2.tgz

[root@docker-server1 ~]# yum install docker -y

[root@docker-server1 ~]# systemctl satrt docker

[root@docker-server1 ~]# systemctl enable docker

Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

6.2.2:服务器2安装docker:

[root@docker-server2 ~]# yum install docker -y

[root@docker-server2 ~]# systemctl start docker

[root@docker-server2 ~]# systemctl enable docker

Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

6.2.3:下载Harbor安装包:

6.2.3.1:下载离线完整安装包:

#推荐使用离线完整安装包

[root@docker-server2 ~]# cd /usr/local/src/

[root@docker-server2 src]# wget https://github.com/vmware/harbor/releases/download/v1.2.2/harbor-offline-installer-v1.2.2.tgz

6.2.3.2:下载在线安装包

#不是很推荐此方式

[root@docker-server2 src]# wget https://github.com/vmware/harbor/releases/download/v1.2.2/harbor-online-installer-v1.2.2.tgz

6.3:配置Harbor:

6.3.1:解压并编辑harbor.cfg:

[root@docker-server1 src]# tar xvf harbor-offline-installer-v1.2.2.tgz

[root@docker-server1 src]# ln -sv /usr/local/src/harbor /usr/local/

‘/usr/local/harbor’ -> ‘/usr/local/src/harbor’

[root@docker-server1 harbor]# cd /usr/local/harbor/

[root@docker-server1 harbor]# yum install python-pip –y

[root@docker-server1 harbor]# docker-compose start

[root@docker-server1 harbor]# vim harbor.cfg

[root@docker-server1 harbor]# grep "^[a-Z]" harbor.cfg

hostname = 192.168.10.205

ui_url_protocol = http

db_password = root123

max_job_workers = 3

customize_crt = on

ssl_cert = /data/cert/server.crt

ssl_cert_key = /data/cert/server.key

secretkey_path = /data

admiral_url = NA

clair_db_password = password

email_identity = harbor

email_server = smtp.163.com

email_server_port = 25

email_username = rooroot@163.com

email_password = zhang@123

email_from = admin <rooroot@163.com>

email_ssl = false

harbor_admin_password = zhang@123

auth_mode = db_auth

ldap_url = ldaps://ldap.mydomain.com

ldap_basedn = ou=people,dc=mydomain,dc=com

ldap_uid = uid

ldap_scope = 3

ldap_timeout = 5

self_registration = on

token_expiration = 30

project_creation_restriction = everyone

verify_remote_cert = on

6.3.2:更新harbor配置:

6.3.2.1:首次部署harbor更新:

[root@docker-server1 harbor]# pwd

/usr/local/harbor #在harbor当前目录执行

[root@docker-server1 harbor]# ./prepare #更新配置

#执行完毕后会在当前目录生成一个docker-compose.yml文件,用于配置数据目录等配置信息:

6.3.2.2:后期修改配置:

如果harbor运行一段时间之后需要更改配置,则步骤如下:

6.3.2.2.1:停止harbor:

[root@docker-server1 harbor]# pwd

/usr/local/harbor #harbor的当前目录

[root@docker-server1 harbor]# docker-compose stop

6.3.2.2.2:编辑harbor.cfg进行相关配置:

[root@docker-server1 harbor]# vim harbor.cfg

6.3.2.2.3:更新配置:

[root@docker-server1 harbor]# ./prepare

6.3.2.2.3:启动harbor服务:

[root@docker-server1 harbor]# docker-compose start

6.3.3:官方方式启动Harbor:

6.3.3.1:官方方式安装并启动harbor:

[root@docker-server1 harbor]# yum install python-pip

[root@docker-server1 harbor]# pip install --upgrade pip

[root@docker-server1 harbor]# pip install docker-compose

[root@docker-server1 harbor]# ./install.sh #官方构建harbor和启动方式,推荐此方法,会下载官方的docker 镜像:

6.3.3.2:部署过程中:

6.3.3.3:部署完成:

6.3.3.4:查看本地的镜像:

6.3.3.5:查看本地端口:

6.3.3.6:web访问Harbor管理界面:

6.3.3.7:登录成功后的界面:

6.3.4:非官方方式启动:

6.3.4.1:非官方方式启动harbor:

[root@docker-server2 harbor]# ./prepare

[root@docker-server2 harbor]# yum install python-pip -y

[root@docker-server2 harbor]# pip install --upgrade pip #升级pip为最新版本

[root@docker-server2 harbor]# pip install docker-compose #安装docker-compose命令

6.3.4.2:启动harbor:

[root@docker-server2 harbor]# docker-compose up –d #非官方方式构建容器,此步骤会从官网下载镜像,需要相当长的时间

#执行过程如下:

6.3.4.3:查看本地镜像:

6.3.4.4:验证本地端口:

6.3.4.5:web访问Harbor界面:

6.4:配置docker 使用harbor仓库上传下载镜像:

6.4.1:编辑docker配置文件:

注意:如果我们配置的是https的话,本地docker就不需要有任何操作就可以访问harbor了

[root@docker-server1 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry 192.168.10.205'

#其中192.168.10.205是我们部署Harbor的地址,即hostname配置项值。配置完后需要重启docker服务。

6.4.2:重启docker服务:

[root@docker-server1 ~]# systemctl stop docker

[root@docker-server1 ~]# systemctl start docker

6.4.3:验证能否登录harbor:

[root@docker-server1 harbor]# docker login 192.168.10.205

6.4.4:测试上传和下载镜像:

将之前单机仓库构构建的Nginx镜像上传到harbor服务器用于测试

6.4.4.1:导入镜像:

[root@docker-server1 harbor]# docker load < /opt/nginx-1.10.3_docker.tar.gz

6.4.4.2:验证镜像导入成功:

6.4.4.3:镜像打tag:

#修改images的名称,不修改成指定格式无法将镜像上传到harbor仓库,格式为: HarborIP/项目名/image名字:版本号:

[root@docker-server1 harbor]# docker tag 192.168.10.205:5000/jack/nginx-1.10.3:v1 192.168.10.205/nginx/nginx_1.10.3:v1

[root@docker-server1 harbor]# docker images

6.4.4.4:在harbor管理界面创建项目:

6.4.4.4:将镜像push到harbor:

#格式为:docker push 镜像名:版本

6.4.4.5:push 完成:

6.4.4.6:harbor 界面验证镜像上传成功:

6.4.4.7:验证镜像信息:

6.4.5:验证从harbor服务器下载镜像并启动容器:

6.4.5.1:更改docker配置文件:

目前凡是需要从harbor镜像服务器下载image的docker服务都要更改,不更改的话无法下载:

[root@docker-server2 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry 192.168.10.205'

6.4.5.2:重启docker:

[root@docker-server2 ~]# systemctl stop docker

[root@docker-server2 ~]# systemctl start docker

6.4.5.3:验证从harbor下载镜像:

6.4.5.5.1:查看下载命令:

#harbor上的每个镜像里面自带pull 命令

6.4.5.5.2:执行下载:

[root@docker-server2 ~]# docker pull 192.168.10.205/nginx/nginx_1.10.3:v1

6.4.5.5.3:验证镜像下载完成:

6.4.6:从镜像启动容器并验证:

6.4.6.1:启动容器:

[root@docker-server2 ~]# docker run -d -p 80:80 -p 443:443 192.168.10.205/nginx/nginx_1.10.3:v1 nginx

89901f9badf74809f6abccc352fc7479f1490f0ebe6d6e3b36d689e73c3f9027

6.4.6.2:验证端口:

6.4.6.3:验证web访问:

6.5:实现harbor高可用:

Harbor支持基于策略的Docker镜像复制功能,这类似于MySQL的主从同步,其可以实现不同的数据中心、不同的运行环境之间同步镜像,并提供友好的管理界面,大大简化了实际运维中的镜像管理工作,已经有用很多互联网公司使用harbor搭建内网docker仓库的案例,并且还有实现了双向复制的案列,本文将实现单向复制的部署:

6.5.1:新部署一台harbor服务器:

[root@docker-server2 ~]# cd /usr/local/src/

[root@docker-server2 src]# tar xf harbor-offline-installer-v1.2.2.tgz

[root@docker-server2 src]# ln -sv /usr/local/src/harbor /usr/local/

‘/usr/local/harbor’ -> ‘/usr/local/src/harbor’

[root@docker-server2 src]# cd /usr/local/harbor/

[root@docker-server2 harbor]# grep "^[a-Z]" harbor.cfg

hostname = 192.168.10.206

ui_url_protocol = http

db_password = root123

max_job_workers = 3

customize_crt = on

ssl_cert = /data/cert/server.crt

ssl_cert_key = /data/cert/server.key

secretkey_path = /data

admiral_url = NA

clair_db_password = password

email_identity = harbor-1.2.2

email_server = smtp.163.com

email_server_port = 25

email_username = rooroot@163.com

email_password = zhang@123

email_from = admin <rooroot@163.com>

email_ssl = false

harbor_admin_password = zhang@123

auth_mode = db_auth

ldap_url = ldaps://ldap.mydomain.com

ldap_basedn = ou=people,dc=mydomain,dc=com

ldap_uid = uid

ldap_scope = 3

ldap_timeout = 5

self_registration = on

token_expiration = 30

project_creation_restriction = everyone

verify_remote_cert = on

[root@docker-server2 harbor]# yum install python-pip -y

[root@docker-server2 harbor]# pip install --upgrade pip

[root@docker-server2 harbor]# pip install docker-compose

[root@docker-server2 harbor]# ./install.sh

6.5.2:验证从harbor登录:

6.5.3:创建一个nginx项目:

#与主harbor 项目名称保持一致:

6.5.4:在主harbor服务器配置同步测试:

6.5.5:点击复制规则:

6.5.6:主harbor编辑同步策略:

6.5.7:主harbor查看镜像同步状态:

6.5.8:从harbor查看镜像:

6.5.9:测试从harbor镜像下载和容器启动:

6.5.9.1:docker客户端配置使用harbor:

#本次新部署了一台docker 客户端,IP地址为192.168.10.207

[root@docker-server3 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry 192.168.10.206'

6.5.9.2:重启docker服务:

[root@docker-server3 ~]# systemctl restart docker

6.5.9.3:从harbor项目设置为公开:

6.5.9.4:设置项目为公开访问:

6.5.9.5:docker客户端下载镜像:

6.5.9.6:docker 客户端从镜像启动容器:

[root@docker-server3 ~]# docker run -d -p 80:80 -p443:443 192.168.10.206/nginx/nginx_1.10.3:v1 nginx

0b496bc81035291b80062d1fba7d4065079ab911c2a550417cf9e593d353c20b

6.5.9.7:验证web访问:

#至此,高可用模式的harbor仓库部署完毕

6.6.:实现harbor 双向同步:

6.6.1:在docker客户端导入centos基础镜像:

[root@docker-server3 ~]# docker load -i /opt/centos.tar.gz

[root@docker-server3 ~]# vim /etc/sysconfig/docker

4 OPTIONS='--selinux-enabled --log-driver=journald --insecure-registry 192.168.10.206'

6.6.2:镜像打tag:

[root@docker-server3 ~]# docker tag docker.io/centos 192.168.10.206/nginx/centos_base

6.6.3:上传到从harbor:

[root@docker-server3 ~]# docker push 192.168.10.206/nginx/centos_base

6.6.4:从harbor界面验证:

6.6.5:从harbor创建同步规则:

规则方式与主harbor相同,写对方的IP+用户名密码,然后点测试连接,确认可以测试连接通过。

6.6.6:到主harbor验证镜像:

6.6.7:docker镜像端测试:

6.6.7.1:下载centos 基础镜像:

[root@docker-server1 harbor]# docker pull 192.168.10.205/nginx/centos_base

Using default tag: latest

Trying to pull repository 192.168.10.205/nginx/centos_base ...

sha256:822de5245dc5b659df56dd32795b08ae42db4cc901f3462fc509e91e97132dc0: Pulling from 192.168.10.205/nginx/centos_base

Digest: sha256:822de5245dc5b659df56dd32795b08ae42db4cc901f3462fc509e91e97132dc0

6.6.7.2:从镜像启动容器:

[root@docker-server1 ~]# docker run -it --name centos_base 192.168.10.205/nginx/centos_base bash

[root@771f5aa0d089 /]#

七:单机编排之Docker Compose:

当在宿主机启动较多的容器时候,如果都是手动操作会觉得比较麻烦而且容器出错,这个时候推荐使用docker 单机编排工具docker compose,Docker Compose 是docker容器的一种编排服务,docker compose是一个管理多个容器的工具,比如可以解决容器之间的依赖关系,就像启动一个web就必须得先把数据库服务先启动一样,docker compose 完全可以替代docker run启动容器。

#github 地址https://github.com/docker/compose

7.1:基础环境准备:

7.1.1:安装python环境及pip命令:

[root@docker-server3 ~]# yum install https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm -y

[root@docker-server3 ~]# yum install python-pip -y

[root@docker-server3 ~]# pip install --upgrade pip

7.1.2:安装docker compose:

[root@docker-server3 ~]# pip install docker-compose

7.1.3:验证版本:

[root@docker-server3 ~]# docker-compose version

7.1.4:查看帮助:

[root@docker-server3 ~]# docker-compose --help

7.2:从 docker compose启动单个容器:

目录可以在任意目录,推荐放在有意义的位置。

[root@docker-server3 ~]# mkdir docker-compose

[root@docker-server3 ~]# cd docker-compose/

7.2.1:一个容器的docker compose文件:

设置一个yml格式的配置文件,因此要注意前后的缩进。

[root@docker-server3 docker-compose]# cat docker-compose.yml

web1:

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

ports:

- "80:80"

- "443:443"

7.2.2:启动容器:

必须要在docker compose文件所在的目录执行:

[root@docker-server3 docker-compose]# docker-compose up #前台启动

7.2.3:启动完成:

7.2.4:web访问测试:

7.2.5:后台启动服务:

#容器的在启动的时候,会给容器自定义一个名称

[root@docker-server3 docker-compose]# docker-compose up -d

7.2.6:自定义容器名称:

[root@docker-server3 docker-compose]# cat docker-compose.yml

web1:

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web1 #自定义容器名称

ports:

- "80:80"

- "443:443"

7.2.7:验证容器:

7.2.8:查看容器进程:

[root@docker-server3 docker-compose]# docker-compose ps

7.3:从docker compose启动多个容器:

7.3.1:编辑docker-compose文件:

[root@docker-server3 docker-compose]# cat docker-compose.yml

web1:

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web1

ports:

- "80:80"

- "443:443"

web2: #每一个容器一个ID

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web2

ports:

- "81:80"

- "444:443"

7.3.2:重新启动容器:

[root@docker-server3 docker-compose]# docker-compose stop

[root@docker-server3 docker-compose]# docker-compose up –d

7.3.3:web访问测试:

7.4:定义数据卷挂载:

7.4.1:创建数据目录和文件:

[root@docker-server3 ~]# mkdir -p /data/nginx

[root@docker-server3 ~]# echo "Test Nginx Volume" > /data/nginx/index.html

7.4.2:编辑compose配置文件:

[root@docker-server3 docker-compose]# vim docker-compose.yml

web1:

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web1

volumes:

- /data/nginx:/usr/local/nginx/html

ports:

- "80:80"

- "443:443"

web2:

image: 192.168.10.206/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web2

ports:

- "81:80"

- "444:443"

7.4.3:重启容器:

[root@docker-server3 docker-compose]# docker-compose stop

[root@docker-server3 docker-compose]# docker-compose up -d

7.4.4:验证web访问:

#可以发现,同一个文件,数据卷的优先级比镜像内的文件优先级高

7.4.5:其他常用命令:

7.4.5.1:重启单个指定容器:

[root@docker-server3 docker-compose]# docker-compose restart web1

Restarting nginx-web1 ... done

7.4.5.2:重启所以容器:

[root@docker-server3 docker-compose]# docker-compose restart

7.4.5.3:停止和启动单个容器:

[root@docker-server3 docker-compose]# docker-compose stop web1

[root@docker-server3 docker-compose]# docker-compose start web1

7.4.5.4:停止和启动所有容器:

[root@docker-server3 docker-compose]# docker-compose stop

[root@docker-server3 docker-compose]# docker-compose start

7.5:实现单机版的HA+Nginx+Tomcat:

7.5.1:制作Haproxy镜像:

[root@docker-server1 haproxy]# pwd

/opt/dockerfile/web/haproxy

7.5.1.1:编辑Dockerfile文件:

[root@docker-server1 haproxy]# cat Dockerfile

#My Dockerfile

From docker.io/centos:7.2.1511

MAINTAINER zhangshijie "zhangshijie@300.cn"

#Yum Setting

ADD epel.repo /etc/yum.repos.d/epel.repo

ADD CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo

RUN yum install gcc gcc-c++ pcre pcre-devel openssl openssl-devel -y

ADD haproxy-1.7.9.tar.gz /usr/local/src

RUN cd /usr/local/src/haproxy-1.7.9 && make TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 PREFIX=/usr/local/haproxy && make install PREFIX=/usr/local/haproxy

RUN cp /usr/local/src/haproxy-1.7.9/haproxy-systemd-wrapper /usr/sbin/haproxy-systemd-wrapper

RUN cp /usr/local/src/haproxy-1.7.9/haproxy /usr/sbin/haproxy

ADD haproxy.service /usr/lib/systemd/system/haproxy.service

ADD haproxy /etc/sysconfig/haproxy

ADD run_haproxy.sh /root/script/run_haproxy.sh

RUN chmod a+x /root/script/run_haproxy.sh

CMD ["/root/script/run_haproxy.sh"]

EXPOSE 80 9999

7.5.1.2:准备服务启动脚本:

[root@docker-server1 haproxy]# cat haproxy.service

[Unit]

Description=HAProxy Load Balancer

After=syslog.target network.target

[Service]

EnvironmentFile=/etc/sysconfig/haproxy

ExecStart=/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid $OPTIONS

ExecReload=/bin/kill -USR2 $MAINPID

[Install]

WantedBy=multi-user.target

7.5.1.3:前台启动脚本:

[root@docker-server1 haproxy]# cat run_haproxy.sh

#!/bin/bash

/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid

7.5.1.4:haproxy参数文件:

[root@docker-server1 haproxy]# cat haproxy

# Add extra options to the haproxy daemon here. This can be useful for

# specifying multiple configuration files with multiple -f options.

# See haproxy(1) for a complete list of options.

OPTIONS=""

7.5.1.5:准备压缩包及其他文件:

7.5.1.6:执行构建镜像:

[root@docker-server1 haproxy]# docker build -t 192.168.10.205/centos/centos_7.2.1511_haproxy_1.7.9 /opt/dockerfile/web/haproxy/

7.5.1.7:经镜像上传到harbor仓库:

7.5.1.8:harbor仓库验证:

7.5.2:准备nginx镜像:

参考2.3

7.5.3:准备tomcat镜像:

参考2.4

7.5.4:编辑docker compose文件及环境准备:

7.5.4.1:编辑docker compose文件:

[root@docker-server3 docker-compose]# pwd

/root/docker-compose

[root@docker-server3 docker-compose]# cat docker-compose.yml

nginx-web1:

image: 192.168.10.205/nginx/nginx_1.10.3

expose:

- 80

- 443

container_name: nginx-web1

volumes:

- /data/nginx:/usr/local/nginx/html

- /usr/local/nginx/conf/nginx.conf:/usr/local/nginx/conf/nginx.conf

links:

- tomcat-web1

- tomcat-web2

nginx-web2:

image: 192.168.10.205/nginx/nginx_1.10.3

volumes:

- /usr/local/nginx/conf/nginx.conf:/usr/local/nginx/conf/nginx.conf

expose:

- 80

- 443

container_name: nginx-web2

links:

- tomcat-web1

- tomcat-web2

tomcat-web1:

container_name: tomcat-web1

image: 192.168.10.205/centos/jdk1.7.0.79_tomcat1.7.0.69

user: www

command: /apps/tomcat/bin/run_tomcat.sh

volumes:

- /apps/tomcat/webapps/SalesManager:/apps/tomcat/webapps/SalesManager

expose:

- 8080

- 8443

tomcat-web2:

container_name: tomcat-web2

image: 192.168.10.205/centos/jdk1.7.0.79_tomcat1.7.0.69

user: www

command: /apps/tomcat/bin/run_tomcat.sh

volumes:

- /apps/tomcat/webapps/SalesManager:/apps/tomcat/webapps/SalesManager

expose:

- 8080

- 8443

haproxy:

container_name: haproxy-web1

image: 192.168.10.205/centos/centos_7.2.1511_haproxy_1.7.9

command: /root/script/run_haproxy.sh

volumes:

- /etc/haproxy/haproxy.cfg:/etc/haproxy/haproxy.cfg

ports:

- "9999:9999"

- "80:80"

links:

- nginx-web1

- nginx-web2

7.5.4.2:准备nginx静态文件:

[root@docker-server3 docker-compose]# cat /data/nginx/index.html

Test Nginx Volume

7.5.4.3:准备nginx配置文件:

#本地路径和nginx路径都是 /usr/local/nginx/conf/nginx.conf

[root@docker-server3 docker-compose]# grep -v "#" /usr/local/nginx/conf/nginx.conf | grep -v "^$"

user nginx;

worker_processes auto;

daemon off;

events {

worker_connections 1024;

}

http {

include mime.types;

default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

upstream tomcat_webserver {

server tomcat-web1:8080;

server tomcat-web2:8080;

}

server {

listen 80;

server_name localhost;

location / {

root html;

index index.html index.htm;

}

location /SalesManager {

proxy_pass http://tomcat_webserver;

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Real-IP $remote_addr;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

}

7.5.4.4:准备tomcat页面文件:

[root@docker-server3 docker-compose]# ll /apps/tomcat/webapps/SalesManager

total 8

-rw-r--r-- 1 www www 15 Dec 21 05:01 index.html

-rw-r--r-- 1 www www 696 Dec 21 05:01 showhost.jsp

[root@docker-server3 docker-compose]# cat /apps/tomcat/webapps/SalesManager/showhost.jsp

<%@page import="java.util.Enumeration"%>

<br />

host: <%try{out.println(""+java.net.InetAddress.getLocalHost().getHostName());}catch(Exception e){}%>

<br />

remoteAddr: <%=request.getRemoteAddr()%>

<br />

remoteHost: <%=request.getRemoteHost()%>

<br />

sessionId: <%=request.getSession().getId()%>

<br />

serverName:<%=request.getServerName()%>

<br />

scheme:<%=request.getScheme()%>

<br />

<%request.getSession().setAttribute("t1","t2");%>

<%

Enumeration en = request.getHeaderNames();

while(en.hasMoreElements()){

String hd = en.nextElement().toString();

out.println(hd+" : "+request.getHeader(hd));

out.println("<br />");

}

%>

7.5.5:启动容器:

[root@docker-server3 docker-compose]# pwd

/root/docker-compose

[root@docker-server3 docker-compose]# docker-compose up –d

7.5.6:验证容器启动成功:

7.5.7:查看启动日志:

[root@docker-server3 docker-compose]# docker-compose logs –f

7.5.8:访问haroxy 管理界面:

192.168.10.207:9999/haproxy-status

7.5.9:访问Nginx静态页面:

Web1:

#web2:

7.5.10:访问tomcat静态页面:

7.5.11:访问tomcat动态页面:

服务器技术交流群请加微信 YJZyjz