目录
1.docker简介
1.1 docker的出现
docker之所以发展迅速,因为它给了一个标准化的解决方案-系统平滑移植,容器虚拟化技术
环境配置相当麻烦,换一台机器,就要重来一次,费力费时,很多人想到,从根本上解决问题,软件带环境安装?也就是说,安装的时候,把原始环境一模一样地赋值过来。开发人员利用Docker可以消除协作编码时"在我的机器上可以正常工作"的问题
1.2docker是什么
docker是go语言实现的开源项目,docker的主要目标是"build ,ship and run any app,anywhere",也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的app及其运行环境能够做到“一次镜像,处处运行”。
linux容器技术的出现解决了这样一个问题,而docker就是在它的基础上发展过来的,将应用打成镜像,通过镜像成为运行在docker容器上的实例,而docker容器在任何操作系统上都是一致的,这就是实现了跨平台,跨服器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
一句话解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术
1.3 容器与虚拟机比较
虚拟机就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在windows10系统里面运行linux系统centos7。应用程序对此毫无感知,因为虚拟机看上去就和真实系统一模一样,对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。传统虚拟机技术基于安装在主操作系统上的虚拟机管理系统(vitualBox或vmware),创建虚拟机,在虚拟机上安装从操作系统,在从操作系统中安装部署各种应用。
虚拟机的缺点:1.资源占用多 2.冗余步骤多 3.启动慢
由于虚拟机存在这些缺点,linux发展出了另一种虚拟化技术:
Linux容器(lxc):linux容器是与系统其它部分隔离开的一系列进程,从另一个镜像运行,并由镜像提供支持进程所需的全部文件。容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试的再到生产的整个过程中,它都具有可移植性和一致性。
linux容器不是模拟一个完整的操作系统而是对进程进行隔离,有了容器,就可以将软件运行所需要的资源打包到一个隔离的容器中,容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
比较docker和传统虚拟机方式的不同之处:
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统, 在该系统上再运行所需应用程序
容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且也没有进行硬件虚拟。因此容器要比传统的虚拟机更轻便。
每个容器之间相互隔离,每个容器有自己的文件系统,容器之间进程不会相互影响,能区分计算机资源。
一处构建、随处运行:
更快速的应用交付和部署
更便捷的升级和扩缩容
更简单的系统运维
更高效的计算资源利用
1.4docker的基本组成
镜像(image),容器(container),仓库(repository)
docker镜像就是一个只读的模板,镜像可以用来创建Docker容器,一个镜像可以创建很多容器。
docker镜像类似java的类模板,
docker容器实例类似于java中new出来的实例对象。
仓库是集中存放镜像文件的场所。仓库分为公开和私有。最大的公开仓库是docker hub,国内的公开仓库包括阿里云、网易云
1.5 Docker的平台架构图解
docker是一个C/S模式的架构,后端是一个松耦合架构,众多模块各司其职
Docker运行的基本流程:
1.用户使用docker client与docker Daemon建立通信,并发送请求给后者
2.Docker daemon作为docker架构中的主体部分,首先提供DockerServer的功能使其可以接受Docker client的请求。
3.Docker engine执行docker内部的一系列工作,每一项工作都以一个job的形式存在。
4.job 运行过程中,当需要容器镜像时,则从docker registry中下载镜像,并通过镜像管理驱动Graph driver将下载镜像以graph的形式存储。
5.当需要为docker创建网络环境时,通过网络管理驱动network创建并配置docker容器网络环境
6.当需要限制docker容器运行资源或执行用户指令等操作时,则同exec driver
7.libContainer是一项独立的容器管理包,network driver 以及 exec deover都是通过libcontainer来实现具体对容器进行的操作。
1.6 安装docker
如果之前安装过docker,先按照官网文档卸载docker
yum 安装gcc 相关:
yum -y install gcc
yum -y install gcc-c++
设置仓库:
安装yum-utils
yum -y install yum-utils
设置stable仓库:
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum包索引
yum makecache fast 相当于重建下yum的索引
安装docker:yum -y install docker-ce docker-ce-cli containerd.io
启动docker
systemctl start docker
docker version
1.7 卸载docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
1.8阿里云镜像加速器
https://promotion.aliyun.com/ntms/act/kubernetes.html
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://iudq0ohl.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
卸载:systemctl stop docker
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
1.9为什么docker比vm快
docker有着比虚拟机更少的抽象层
由于docker不需要hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在cpu、内存利用率上docker将会在效率上有明显的优势。
docker利用的是宿主机的内核,而不需要加载操作系统os内核。
当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载os,返回新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。
查看docker总体帮助文档 docker --help
查看docker 命令帮助我难得 docker 具体命令 --help
2.docker命令
列出本地镜像
docker image # TAG表示标签版本号
-a 列出本地所有的镜像
-q 只显示镜像id
docker search 镜像名
--limit N 前N名
docker pull 某个镜像名称
docker pull 镜像名称:TAG
docker system df 查看镜像/容器/数据卷所占的空间
docker rmi 某个镜像名称id
-f 强制删除
docker rmi ${docker images -qa} 删除所有镜像
docker虚悬镜像:仓库、TAG都是<none>的镜像,俗称虚悬镜像dangling image
2.1 容器命令
docker run
--name = "容器新名字"
-d: 后台运行容器并返回容器id,也即启动守护式容器
-i: 以交互模式运行容器,通常与-t同时使用
-t: 为容器重新分配一个伪输入终端,通常与-i同时使用
也即启动交互式容器(前台有伪终端,等待交互)
-P:随机端口映射
-p:指定端口映射
docker ps 罗列出所有正在运行的容器
退出方式:1.exit
run进去容器,exit 退出,容器停止
2.ctrl+p+q
run进去容器,ctrl+p+q退出,容器不停止
启动已停止运行的容器
docker start 容器id或容器名
重启容器
docker restart 容器id或容器名
停止容器
docker stop 容器id或容器名
强制停止容器
docker kill 容器id或容器名
删除已停止的容器
docker rm 容器id
-f 强制删除
一次性删除多个容器
docker rm -f ${docker ps -a -q}
docker ps -a -q | xargs docker rm
启动守护式进程
docker run -d 容器名
docker run -d centos
问题:然后docker ps -a 进程查看,会发现容器已经退出
很重要的要说明一点,docker容器后台运行,就必须有一个前台进程
容器运行命令如果不是那些一直挂起的命令(如top,tail),就会自动退出的
这个是docker的机制问题,比如web容器,以nginx为例,正常情况下,配置启动服务只需要启动响应的service即可 service nginx start。但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀,因为它觉得没事可做了。
所以,最佳的解决方案是,将要运行的程序以前台进行的形式运行,常见就是命令行模式,表示我还有交互操作,别中断
查看容器日志
docker logs 容器id
查看容器内运行的进程
docker top 容器id
查看容器内部细节
docker inspect 容器id
从镜像容器角度,可以把容器看做是一个简易版的linux环境和运行在其中的应用程序
进入正在运行的容器并以命令行交互
docker exec -it 容器id bashShell
重新进入
docker attach 容器id
上述两个区别:attach直接进入容器启动命令终端,不会启动新的进程,用exit退出,会导致容器的停止
exec 是在容器中打开新的终端,并且可以启动新的进程,用eixt退出,不会导致容器的停止。
一般使用exec
拷贝容器文件到主机上
docker cp 容器id:容器内路径 目的主机路径
导出容器
docker export 容器id > abc.tar
导入容器(称为镜像)
cat abc.tar | docker import - 镜像用户/镜像名:镜像版本号
docker container prune:可以清理掉所有终止状态的容器。
3.docker镜像
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
docker镜像加载原理
docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统UnionFS.
docker commit 提交容器副本使之成为一个新的镜像
docker commit -m = “提交的描述信息” -a=“作者” 容器id 要创建的目标镜像名:标签名
Docker镜像层是可读的,容器层是可写的
当容器启动时,一个新的可写层被加载到镜像的顶部
这一层通常被称作为“容器层”,"容器层"之下的都叫"镜像层"
3.1本地镜像发布到阿里云
登录阿里云容器镜像服务
创建命名空间,创建镜像仓库
镜像推送到阿里云
3.2 docker 私有仓库
1.下载嘉兴docker registry
docker pull registry
2.运行私有库Registry,相当于本地有个私有Docker hub
docker run -d -p 5000:5000 -v /zz/myregistry/:/tmp/registry --privilege=true registry
默认情况下,仓库被创建在容器/var/lib/registry目录下,建议自行用容器卷映射,方便于主机联调
3.案例演示创建一个新镜像,ubuntu安装ifconfig命令
docker run -it ubuntu /bin/bash
apt-get update
apt-get install net-tools
docker commit -m="ifconfig add" - a = zzz 容器id
4.curl 验证私服上有什么镜像
curl -XGET http://xx.xx.xx.xx:5000/v2/_catalog
5.将新镜像zzyy:1.2修改符合私服规范的Tag
docker tag zzyy:1.2 xxx.xxx.xxx.xxx:5000/zzyy:1.2
6.修改配置文件是之支持http
cat /etc/docker/daemon.json
增加"insecure-registries":["192.168.155.10:5000"]
docker默认不支持http方式推送,通过配置选项来取消这个限制
3.3docker容器数据卷
1.Docker挂载主机目录访问如果出现cannot open directory :Permission denied
解决方法:在挂载目录后多加一个 --privilege=true参数即可
如果Centos7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为。在selinux里面挂载目录被禁止掉了,如果要开启,一般使用--privilege=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数。container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
容器卷:就是目录或文件,存在一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System 提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器 生存周期,因此docker不会在容器删除时删除挂载的数据卷。
一句话有点类似于redis里面的rdb额aof文件
将docker容器内的数据保存进宿主主机的磁盘中
运行一个带有数据卷存储功能的容器实例
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
查看数据卷是否挂载成功
docker inspect 容器id
数据同步:
docker 修改,主机同步获得
主机修改,docker同步获得
docker 容器stop,主机修改,docker容器数据同步
2.容器卷读写规则
默认规则:读写
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
容器实例内部限制,只能读取不能写
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
3.容器卷的继承
容器1继承容器2的卷规则
docker run -it --provileged=true --volumes-from 父类 --names u2 ubuntu
4.常用软件安装
总体步骤:
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动镜像
- 停止容器
- 移除容器
4.1安装Tomcat
安装最新的tomcat
docker run -d -p 8080:8080 --name=t1 tomcat /bin/bash
进入docker中的tomcat 将webapps.dist 重命名为webapps
安装tomcat8
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
4.2 安装mysql5.7
4.2.1 简易版
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
4.2.2 解决乱码及防止数据误删
挂载数据卷
docker run -d -p 3306:3306 --privileged=true
-v /home/mysql/log:/var/log/mysql
-v /home/mysql/data:/var/lib/mysql
-v /home/mysql/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=12345
--name=mysql
mysql:5.7
在宿主机/home/mysql/conf下新建my.cnf
[client]
default_character_set=utf8
[mysqld]
collation_server=utf8_general_ci
character_set_server=utf8
4.3 安装redis
4.3.1 简易版
docker run -d -p 6379:6379 redis:6.0.8
4.3.2 挂载容器卷
容器卷记得加入--privileged=true
在centos宿主机下新建目录/app/redis
修改配置文件:
开启redis验证
requirepass 123
允许redis外地连接
注释掉# bind 127.0.0.1
daemonize 设置为no,设置为yes 会和docker run -d参数冲突,导致容器启动失败
开启redis数据持久化
appendonly yes
docker run -p 6379:6379 --name myr3 --privileged=true
-v /app/redis/redis.conf:/etc/redis/redis.conf
-v /app/redis/data:/data
-d redis:6.0.8 redis-server /etc/redis/redis.conf
5.docker复杂安装
5.1 mysql 主从复制
1.新建主容器服务实例
docker run -p 3307:3306 --name=mysql-master
-v /mydata/mysql-master/log:/var/log/mysql
-v /mydata/mysql-master/data:/var/lib/mysql
-v /mydata/mysql-master/conf:/etc/mysql
-e MYSQL_ROOT_PASSWORD=root
-d mysql:5.7
2.进入/mydata/mysql-master/conf目录下新建my.cnf
[mysqld]
##设置server_id,同一局域网中需要唯一
server_id = 101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能
log-bin=mall-mysql-bin
##设置二进制日志使用内存大小
binlog_cache_size=1M
##设置使用的二进制日志格式 (mixed,statement,row)
binlog_format=mixed
##二进制日志过期清理时间。默认为0,表示不自动清理
expire_logs_days=7
##跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制终端。
## 如1062错误是一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
3.修改完master后,重启实例
docker restart mysql-master
4.进入msql-master容器
5.master容器实例内创建数据同步用户
create user 'slave'@'%' identified by '12345';
grant replication slave,replication client on *.* to 'slave'@'%';
6.新建从服务器容器实例3308
docker run -p 3308:3306 --name=mysql-slave
-v /mydata/mysql-slave/log:/var/log/mysql
-v /mydata/mysql-slave/data:/var/lib/mysql
-v /mydata/mysql-slave/conf:/etc/mysql
-e MYSQL_ ROOT_PASSWORD=root
-d mysql:5.7
7.新建my.cnf文件
[mysqld]
##设置server_id,同一局域网中需要唯一
server_id =102
##指定不需要同步的数据库名称
binlog-ignore-db=mysql
##开启二进制日志功能,以备slave作为其他数据库实例的master使用
log-bin=mall-mysql-slave1-bin
##设置二进制日志使用内存大小
binlog_cache_size = 1M
##设置使用二进制日志格式
binlog_format=mixed
##二进制日志过期清理时间。默认值我0,表示不自动清理
expire_logs_days=7
slave_skip_errors=1062
##relay_Log配置中继日志
relay_log=mall-mysql-relay-bin
##log_slave_updates标识slave将复制事件写进自己的二进制日志
log_slave_updates=1
##slave设置为只读 (具有super权限的用户除外)
read_only=1
8.重启mysql-slave
9、在主数据库中查看主从同步状态
show maste status
10.进入mysql-slave容器
11.在从数据库中配置主从复制
change master to master_host='宿主机ip',
master_user='slave',master_password='12345',
master_port=3307,
master_log_file='mall-mysql-bin.000001',
master_log_pos=617,
master_connect_retry=30;
12.在从库查看主从同步状态
show slave status;\G
13.在从数据库中开启主从同步
start slave;
5.2分布式存储
1到2亿数据需要缓存,请问如何设计存储案例
1.分布式取余分区
2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构建一个集群,用户每次读写操作都是根据公式:hash(key)%N个机器数,计算出哈希值,用来决定数据映射到哪一个节点上。
优点:简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台,8台,10台,就能保证一段时间的数据支持。使用hash算法让固定的一部分请求落到同一个服务器上,这样每台服务区固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。
缺点:原来规划好的节点,进行扩容或者缩容就比较麻烦了,不管扩缩,每次数据变动导致节点变动,映射关系需要重新计算,在服务器个数固定不变是没问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化。
2.一致性哈希算法分区
算法背景:为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不ok了。目的是当服务器个数发生变动时,尽量减少影响客户 端到服务器的映射关系
三大步骤:
算法构建一致性哈希环:
它也是按照使用取模的方法,方案一的节点取模法是对节点(服务器)的数量进行取模。而一致性哈希算法是对2^32取模,简单来说,一致性哈希算法将整个哈希值空间组织成一个虚拟的圆环。
服务器ip节点映射:
将集群中的各个ip节点映射到环上到某一个位置
将各个服务器使用hash进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,假如如下四个节点A,B,C,D
key落到服务器的落键规则:
容错性:
假设Node C宕机,可以看到此时对象A,B,D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间前一台服务器之间的数据,其他不受影响。简单说,C挂了,受到影响的只是B,C之间的数据,并且这些数据会转移到D进行存储。
扩展性:
数据量增加了,需要增加一台节点Node X,X的位置在A和B之间,那受到影响的也就是A 到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。
缺点:一致性哈希算法数据倾斜问题
在服务器节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中在某一台服务器上)问题,如
3.哈希槽分区
为什么出现?一致性哈希算法的数据倾斜问题
哈希槽实质上是一个数组,数组[0,2^14-1]形成hash slot空间。
解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽,用于管理数据和节点之间的关系。
多少个哈希槽?16384个槽。编号0-16383。这些槽会分配给集群中的所有主节点,分配策略没要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽 对应关系,解决了节点和槽 关系后,接下来就需要对key求哈希值,然后取余16384,余数是几key就落入对应的槽里。slot=CRC16(key)%16384.以槽为单位移动数据,因为槽 数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
为什么redis集群的最大槽位数是16384?
Redis并没有使用一致性hash而是引入了哈希槽的概念,Redis中的每个key通过CRC16校验后取模来决定放置哪个槽位,集群的每个节点负责一部分hash槽。CRC16算法产生的hash值为16bit,该算法可以产生2^16=65536个值。换句话说值是分布在0-65535之间, 那作者为啥在mod运算的时候,不mod65536,而是mod16384;
redis集群是主节点数量基本不可能超过1000个。集群节点越多,心跳包的消息体内携带的数据越多,如果节点1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个,那么对于节点数在1000以内的redis cluster集群,16384槽位够用了,没必要拓展到65536个。
5.2.1redis3主3从
docker run -d --name redis-node-1 --net host
--privileged=true -v /data/redis/share/redis-node-1:/data/ redis:6.0.8
--cluster-enabled yes --appendonly yes --port 6381
修改端口 执行6次上述命令
构建集群:
redis-cli --cluster create 192.168.155.10:6381 create 192.168.155.10:6382
create 192.168.155.10:6383 create 192.168.155.10:6384 create 192.168.155.10:6385
--cluster -replicas 1
--cluster -replicas 1 表示为每个master创建一个slave节点
查看集群状态:cluster info ,cluster nodes
客户端集群方式连接:
redis-cli -p 6381 -c
集群检查:
redis-cli --cluster check 192.168.155.10:6381
主从扩容
将新增的6387作为master节点加入集群:
reids-cli --cluster add-node 自己实际ip地址:6387 自己实际ip地址:6381
6387 就是将要作为master新增节点
6381 就是原原理集群节点里面的领路人
重新分派槽号:
redis-cli --cluster reshard ip地址:端口
redis-cli --cluster add-node 192.168.155.10:6388 192.168.155.10:6387
--cluster-slave
--cluster-master-id xxxxvcvc 这个是6387的编号,按照自己实际情况
主从缩容:
先删除从节点,再删除主节点
redis-cli --cluster del-node 192.168.155.10:6388 xxxxxx节点id
6.Dockerfile
6.1 介绍
dockerfile是用来构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
dockerfile内容:
每条保留字指令都必须为大写字母且后面至少要跟随一个参数
指令按照从上到下,顺序执行
每条指令都会创建一个新的镜像层并对镜像进行提交。
docker执行dockerfile的大致流程:
1.docker从基础镜像运行一个容器
2.执行一条指令并对容器做出修改
3.执行类似docker commit的操作提交一个新的镜像层
4.docker再基于刚提交的镜像运行一个新容器
5.执行dockerfile中的下一条指令直到所有指令都执行完成
6.2 常用保留字指令
FROM:基本都出现在第一行,表示镜像来着哪里。
MAINTAINER: 镜像维护者的姓名和邮箱地址
RUN:容器构建时需要运行的命令,两种格式:shell格式、exec格式,RUN是在docker build时运行
EXPOSE:当前容器对外暴露的端口
WORKDIR:指定在创建容器后,终端默认登录进来的工作目录,一个落脚点
USER:指定该镜像以什么样的用户去执行,如果都不指定,默认是root
ENV:用来在构建镜像过程中设置环境变量
VOLUMN:容器数据卷,用于数据保存和持久化操作。
ADD:将宿主机目录下的文件拷贝进镜像且会自动处理url和解压tar压缩包
COPY:类似ADD,拷贝文件和目录到镜像中。
将从构建上下文目录中的文件/目录复制到新的一层的镜像内
CMD:指定容器启动后要干的事
指令格式和RUN相似
dockerfile中可以有多个cmd指令,但只有最后一个生效,cmd会被docker run之后的参数替换
和RUN区别: CMD是在docker run时运行;RUN是在docker build时运行
ENTRYPOINT:也是用来指定一个容器启动时要运行的命令
类似于CMD,但是ENTERPOINT不会被docker run 之后的命令覆盖
https://mirrors.yangxingzhen.com
编写好Dockerfile文件后,docker build -t 新镜像名字:TAG. .表示Dockerfile当前面目录
6.3 虚悬镜像
仓库名、标签都是<none>的镜像,俗称dangling image
查看所有虚悬镜像: docker image ls -f dangling=true
docker image prune;删除虚悬镜像
7.docker 网络
docker 启动后,ifconfig 可以看到docke0的一个虚拟网桥
docker network ls
docker network 能干什么?
容器间的互联和通信以及端口映射
容器ip变动时可以通过服务名直接网络通信而不受影响
网络模式:
网络模式 | 简介 |
bridge | 为每个容器分配、设置ip等,并将容器连接到一个docker0虚拟网桥,默认为该模式 |
host | 容器将不会虚拟出自己的网卡,配置自己的ip等,而是使用宿主机的ip和端口 |
none | 容器有独立的network namespace,但并没有对其进行任何网络配置,如分配veth pair和网桥连接,ip等。 |
container | 新创建的容器不会创建自己的网卡和配置自己的ip,而是和一个指定的容器共享ip,端口范围等。 --network container:Name或者容器id |
7.1 network bridge
Docker服务默认会创建一个docker0网桥,它在内核层连通了其他物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。让主机和容器之间通过网桥互相通信。
7.2 自定义网络
docker link 过时
新建自定义网络
docker netwotk create 名称
自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)
8.docker compose 容器编排
docker compose是docker官方的开源项目,负责实现对Docker容器集群的快速编排
可以管理多个docker容器组成一个应用,需要定义一个yaml格式的配置文件
docker-compose.yml写好多个容器之间的调用关系,然后一个命令,就能同时启动或关闭这些容器。
8.1 安装compose
参考官网:https://docs.docker.com/compose/install/
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
输出版本,表示安装成功
卸载:
rm /usr/local/bin/docker-compose
8.1.1 compose
核心概念:1个文件 docker-compose.yml;两个要素:服务、工程
docker-compose up 命令相当于 一次性运行了 多个 docker run命令
常用命令:
docker-compose -h 帮助文档
docker-compose up 启动所有的docker-compose 服务
docker-compose up -d 启动所有docker-compose服务并后台运行
docker-compose down 停止并删除容器、网络、卷、镜像
docker-compose config 检查配置
docker-compose config -q 检查配置,有问题才有输出
docker-compose start
docker-compose restart
docker-compose stop
编写docker-compose.yml文件
version: "3"
services:
microService:
image: 镜像名:tag
container_name: ms01
ports:
- "6001:6001"
volumes:
- /app/xxx:/data
networks:
- xxxx
depends_on:
- redis
- mysql
redis:
image: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /app/redis/redis.conf:/etc/redis/redis.conf
- /app/redis/data:/data
networks:
- xxxx
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environments:
MYSQL_ROOT_PASSWORD: "12345"
MYSQL_ALLOW_EMPTY_PASSWORD: "no"
MYSQL_DATABASE: 'db2022'
MYSQL_USER: "root"
MYSQL_PASSWORD: "XXXXX"
ports:
- "3306:3306"
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.cnf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- xxxx
command: --default-authetication-plugin=mysql_native_password #解决外部无法访问
networks:
xxxx
9.docker可视化工具
portainer
安装命令:
docker run -d -p 8000:8000 -p 9000:9000 --name portainer --restart=always -v
/var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
docker statuse可以方便的看到当前宿主机上所有容器的CPU,内存以及网络流量等数据。但统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、没有监控指标过线预警等。