docker的学习
一、docker基础知识
docker的出现所解决的问题,解决了运行环境和配置的问题,方便做持续集成和整体发布的软件容器,docker基于golang实现的开源项目
docker和虚拟机的区别
虚拟机 启动慢 占用资源大 步骤冗余 docker则相反
docker的基本组成 镜像(image) 容器(container) 仓库(repository)
docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就是image镜像文件,只有通过这个镜像文件才能生成docker容器实例(类似于java中new一个对象)。image文件可以看做是容器的模板,docker根据image文件生成容易的实例。同一个image文件,可以生成多个同时运行的容器实例。
镜像文件
image文件生成的容器实例,本身也是一个文件,称为镜像文件。
容器实例
一个容器运行一种服务,当我们需要的时候就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器
仓库
就是放一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候再从仓库中拉下来就可以了。
阿里云镜像加速器(每个人不一样)
Docker Version不低于1.10时,建议直接通过daemon config进行配置。使用配置文件/etc/docker/daemon.json(没有时新建该文件)添加以下内容
加速地址:https://vopazfb5.mirror.aliyuncs.com
{ "registry-mirrors": ["https://vopazfb5.mirror.aliyuncs.com"] }
二、docker相关命令
1、docker镜像常用命令
docker images 查看镜像
docker system df 查看镜像信息
docker search xxx 查看镜像名
docker pull xxx 拉取镜像
docker rmi xxx 删除镜像
2、docker容器相关命令
以ubuntu为例:
使用镜像ubuntu:latest以交互模式启动一个容器,在容器内执行/bin/bash命令
docker pull ubuntu 获取镜像
docker run -it ubuntu /bin/bsah 在容器中运行镜像
docker ps 罗列出所有容器
docker rm xxx 删除停止的容器
容器重要命令
docker run -d xxx 容器后台运行,首先得以交互式运行容器, docker run -it xxx
docker logs xxx 查看日志
docker top xxID
docker inspect xxxID 查看容器具体信息
重新进入docker ctrl +p +q 退出容器,不会导致容器停止
docker exec -it xxxid /bin/bash
docker attach xxxid
attach直接进入容器启动命令的终端,不会启用新的进程,用exit退出,会导致容器的停止
exec是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止(较常用)。
docker cp 容器ID:容器内路径 目标路径
导出容器:docker export 容器id>文件名.tar
导入容器:cat 文件名.tar |docker import -镜像用户/镜像名:镜像版本号
镜像分层原理和镜像commit操作案例
docker commit 提交容器副本使之成为一个新的镜像
docker commit -m =”提交的描述信息” -a=”作者” 容器ID 要创建的目标镜像名:[标签名]
三、docker仓库
1、在阿里云创建镜像仓库,有相应的脚本
docker login --username=wcya**** registry.cn-zhangjiakou.aliyuncs.com
docker pull registry.cn-zhangjiakou.aliyuncs.com/wcyandzf/ubuntu:[镜像版本号]
docker login --username=wcya**** registry.cn-zhangjiakou.aliyuncs.com$ docker tag [ImageId] registry.cn-zhangjiakou.aliyuncs.com/wcyandzf/ubuntu:[镜像版本号]
docker push registry.cn-zhangjiakou.aliyuncs.com/wcyandzf/ubuntu:[镜像版本号]
2、建私服仓库,并上传镜像
docker pull registry docker run -d -p 5000:5000 -v /wcy/myregistry/:/tmp/registry –privileged=true registry
##新建一个镜像
docker commit -m =”提交的描述信息” -a=”作者” xxxxid wcy:1.3 docker tag wcy:1.3 ip:端口/wcy:1.3 docker push ip:端口 /wcy:1.3 curl -XGET http://ip:端口 /v2/_catalog 查看镜像是否上传
vim /etc/docker/deamon.json
echo "insecure-registries":["ip:端口"]>>deamon.json
##原因:docker默认不允许http方式推送镜像,通过配置选项来取消这个限制。重启docker生效。
docker挂载主机目录访问如果出现cannot open directory.:Permission denied
解决方法:在挂载目录后多加一个–privilege=true参数即可
四、容器数据卷
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供用于一些持续存储或者共享数据的特性;
卷的设计特性就是数据持久化,完全独立于容器的生存周期,因为docker在删除容器是不会删除其挂载的容器卷
1、运行一个带有容器卷存储功能的容器实例:
docker内新建文件会自动同步到指定目录下
docker run -it –privileged=true -v /宿主机绝对路径目录:/容器内目录 –name xx 镜像名
2、读写规则
docker run -it –privileged=true -v / 宿主机绝对路径目录:/容器内目录:ro –name xx 镜像名
3、卷的继承和共享
docker run -it — privileged=true –volume-from 父类 name xxx 镜像名 ##可以继承父类的卷,父类容器挂了也不会影响继承。
五、docker上安装常用软件说明
1、tomcat的安装说明
从hub.docker.com搜索需要安装镜像
docker pull tomcat 该镜像
docker run -d -p 端口:端口 –name xxx 镜像名
最新版(10.0.13)tomcat运行之后去网页验证会出现404错误
解决方法:查看端口映射或者防火墙端口是否关闭;将webapps.dist重命名成webapps
2、mysql的安装说明
从hub.docker.com搜索需要安装镜像
docker pull mysql 该镜像 启用mysql镜像 docker run –name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag mysql使用容器数据卷存储功能,相当于数据库备份 docker run -d -p 5000:3306 –privileged=true -e MYSQL_ROOT_PASSWORD=123456-v /bak/data:/var/lib/mysql -v /bak/log:/var/log/mysql -v /bak/config:/etc/mysql/conf.d –name mymysql docker.io/mysql:5.7.37
docker上默认字符集编码隐患
默认是拉丁文
解决方法:
在宿主机路径下编辑my.cnf,后重启MySQL
[client] default_character_set=utf8 [mysqld] collation_server=utf8_general_ci character_set_server=utf8
3、redis的安装与配置
从hub.docker.com搜索需要安装镜像
docker pull mysql 该镜像
启用redis镜像
docker run -p 6379:6379 –name myredis –privileged=true-v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data/:/etc/redis/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
六、docker复杂安装详说(集群)
1、安装mysql的主从复制
新建主机mysql
docker run -d -p 3307:3306 –privileged=true -e MYSQL_ROOT_PASSWORD=123456 \ -v /mydata/mysql-master/log:/var/log/mysql \ -v /mydata/mysql-master/data : /var/lib/mysql \ -v /mydata/mysql-master/conf:/etc/mysql/conf.d \ –name mymysql docker.io/mysql:5.7.37
my.cnf配置
[mysqld] ##设置server_id,同一局域网中需要唯一 server_id=101 ##指定不需要同步的数据库名称 binlog-ignore-db=msyql ##开启二进制日志功能 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
重启docker restart mysql-master
若启用失败,可查看日志找原因 docker logs xxxx
创建mysql数据同步用户
create user ‘slave’@’%’ identified by ‘xxxxxx’;
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON . TO ‘slave’@’%’;
新建从机
docker run –privileged=true -e MYSQL_ROOT_PASSWORD=xxxxxx -p 3308:3306 -d -v /mydata/mysql-slave/log:/var/log/mysql -v /mydata/mysql-slave/data:/var/lib/mysql -v /mydata/mysql-slave/conf:/etc/mysql/conf.d –name mysql-slave docker.io/mysql:5.7.37
my.cnf配置
[mysqld] ##设置server_id,同一局域网中需要唯一 server_id=102 ##指定不需要同步的数据库名称 binlog-ignore-db=msyql ##开启二进制日志功能 log-bin=mall-mysql-slave1-bin ##设置二进制日志使用内存大小(事务) binlog_cache_size=1M ##设置使用的二进制日志格式(mixed,statement,row) binlog_format=mixed ##二进制日志过期清理时间,默认值为0,表示不自动清理 expire_logs_days=7 ##跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断 ##如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致 slave_skip_errors=1062 ##relay_log配置中继日志 relay_log=mall-mysql-relay-bin ## log_slave_updates表示slave将复制事件写进自己的二进制日志 log_slave_updates=1 ##slave设置为只读(具有super权限的用户除外) read_ouly=1
主数据库中查看状态
show master status;
在从库中配置主从复制
change master to master_host=’ip’,master_user=’slave’,master_password=’xxxxxx’,master_port=3307,master_log_file=’mall-msyql-bin.000001′,master_log_pos=617,master_connect_retry=30;
在从数据库中开启主从复制
start slave;
查看从库主从复制状态
show slave status \G;
若slave_io_runing:no则检查主库中show master status;状态,不行就flush logs刷新状态,重复 在从库中配置主从复制 步骤
2、安装redis集群
分布式存储之哈希取余算法、一致性哈希算法、哈希槽分区
案例:1-2亿条数据需要缓存,设计存储方案
方案:3主3从redis集群扩缩容配置案例架构说明
①、3主3从集群配置
新建6个docker实例
docker run -d –name redis-node-1 –net host –privileged=true -v /data/redis/share/redis-node-1:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3681 docker run -d –name redis-node-2 –net host –privileged=true -v /data/redis/share/redis-node-2:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3682 docker run -d –name redis-node-3 –net host –privileged=true -v /data/redis/share/redis-node-3:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3683 docker run -d –name redis-node-4 –net host –privileged=true -v /data/redis/share/redis-node-4:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3684 docker run -d –name redis-node-5 –net host –privileged=true -v /data/redis/share/redis-node-5:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3685 docker run -d –name redis-node-6 –net host –privileged=true -v /data/redis/share/redis-node-6:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3686
进入docker容器后执行以下命令 –cluster-replicas 1 表示为每个master创建一个slave节点
进入第一个节点
redis-cli –cluster create 121.89.198.107:3681 121.89.198.107:3682 121.89.198.107:3683 121.89.198.107:3684 121.89.198.107:3685 121.89.198.107:3686 –cluster-replicas 1
如果出现以下问题,Waiting for the cluster to join进入无休止的等待
解决方案:
开放Redis服务的两个TCP端口。譬如Redis客户端连接端口为6379,而Redis服务在集群中还有一个叫集群总线端口,其端口为客户端连接端口加上10000,即 6379 + 10000 = 16379。所以开放每个集群节点的客户端端口和集群总线端口才能成功创建集群!
客户端端口:客户端访问Redis服务器的端口
集群总线端口:用二进制协议(gossip协议)的点对点集群通信的端口。用于节点的失败侦测、配置更新、故障转移授权,等等。
进入3681作为切入点,查看集群状态
redis-cli -p 3681 cluster info cluster nodes
②、主从容错切换迁移案例
加入参数从c,优化路由
redis-cli –cluster check 121.89.198.107:3681 查看集群信息
在正常情况下
在redis-node-2宕机情况下
当宕机redis恢复之后,依旧是slave
③、主从扩容案例
docker run -d –name redis-node-7 –net host –privileged=true -v /data/redis/share/redis-node-7:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3687 docker run -d –name redis-node-8 –net host –privileged=true -v /data/redis/share/redis-node-8:/data docker.io/redis:6.0.8 –cluster-enabled yes –appendonly yes –port 3688
将新增的3687节点(空槽号)作为master集群加入员集群
redis-cli –cluster add-node 121.89.198.107:3687 121.89.198.107:3681
重新分配槽号
redis-cli –cluster reshard 121.89.198.107:3681
查看redis集群状态
redis-cli –cluster check 121.89.198.107:3681
为主节点3687分配从节点3688
redis-cli –cluster add-node 121.89.198.107:3688 121.89.198.107:3687 –cluster-slave –cluster-master-id 8c976e32b0527a1a4cface54e60ce8927efe4679
查看状态
redis-cli –cluster check 121.89.198.107:3681
④、主从缩容案例
先删除从机3688,清出来的槽位重新分配,再删除3687,恢复成3主3从
redis-cli –cluster del-node 121.89.198.107:3688 17615e9217cbcc47e97047b9c00903a2682eb65e
将3687槽号清空,重新分配,本例将清出来的槽号都给3681
redis-cli –cluster reshard 121.89.198.107:3681
再次删除3687:
redis-cli –cluster del-node 121.89.198.107:3687 8c976e32b0527a1a4cface54e60ce8927efe4679 redis-cli –cluster check 121.89.198.107:3681
七、dockerfile
dockerfile是用来构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。
dockerfile内容基础知识:
a、每条保留字指令都必须为大写字母且后面要跟随至少一个参数
b、指令按照从上到下顺序执行
c、#表示注释
d、每条指令都会创建一个新的镜像层并对镜像进行提交。
docker执行dockerfile的大致流程:
a、docker从基础镜像运行一个容器
b、执行一条指令并对容器进行修改
c、执行类似docker commit的操作提交一个新的镜像层
d、docker再基于刚提交的镜像运行一个新的容器
e、执行dockerfile中的下一条指令直到所有指令执行完成
指令
FROM 基础镜像,当前镜像基于哪个镜像,指定一个已存在的镜像作为模板
MAINTAINER 镜像维护者的姓名和邮箱地址
RUN 容器构建时需要运行的命令;两种格式shell格式、 exec格式;RUN是在docker build时运行
EXPOSE 当前容器对外暴露的端口
WORKDIR 指定在创建容器后,终端默认登入进来的工作目录,一个落脚点
USER 指定该镜像以什么用户去执行,如果都不指定,默认是root
ENV 用来在构建镜像过程中设置环境变量
VOLUME 容器数据卷,用于数据保存和持久化工作
ADD 将宿主机目录下的文件拷贝进镜像且会自动化处理url和tar文件
COPY 类似ADD拷贝文件和目录到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到一层新的镜像内<目标路径>
CMD 指容器启动后要干的事情;dockerfile中可以有多个CMD指令,但只有最有一个生效,CMD会被docker run 之后的参数替换;和RUN的区别:CMD是在docker run时运行,RUN是在docker bulid时运行
ENTRYPOINT 也是来指定一个容器启动时要运行的命令;类似于CMD指令,但是ENTRYPOINT不会被docker run后面的参数覆盖,而且这些命令行参数会被当做参数传递给ENTRYPOINT指令指定的程序
实际案例:自定义镜像mycentosjava8
要求:centos7镜像具备vim+ifconfig+jdk8
大致步骤:
Dokcerfile FROM docker.io/centos:7.5.1804 MAINTAINER wcy<xxxx@xx.com> ENV MYPATH /usr/local WORkDIR $MYPATH #安装vim编辑器 RUN yum -y install vim #安装ifconfig命令查看ip RUN yum -y install net-tools #安装java8及lib库 RUN yum -y install glibc.i686 RUN mkdir /usr/local/java #ADD是相对路径jar,把jdk8添加到容器中,安装包必须要和Dockerfile在同一位置 ADD jdk-11.0.4_linux-x64_bin.tar.gz /usr/local/java#配置java环境变量 ENV JAVA_HOME /usr/local/java/jdk-11.0.4 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH EXPOSE 8080 CMD echo $MYPATH CMD echo ‘success…ok’ CMD /bin/bash
在Dockerfile同一文件夹下执行
docker bulid -t 镜像名:TAG .
虚悬镜像
仓库名、标签都是<none>的镜像,俗称dangling image
查看虚悬镜像:
docker image ls -f dangling=true
删除虚悬镜像:
docker image prune
通过IDEA新建一个普通的微服务模块
通过dockerfile发布微服务部署到docker容器
打包成镜像文件
dockerfile
#基础镜像使用java FROM java:8 #作者 MAINTAINER wcy #volume指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建一个临时文件并链#接到容器的tmp VOLUME /tmp #将jar包添加到容器中并更名为xxx_docker.jar ADD xxxx.jar xxx_docker.jar#运行jar包 RUN bash -c ‘touch /xxx_docker.jar’ ENTRYPOINT [ “java”,”-jar”,”/xxx_docker.jar” ] #暴露6001端口作为微服务 EXPOSE 6001
八、docker network
查看docker网络命令
docker network ls 查看docker网络命令
docker network –help
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
作用:
容器间的互联和通信以及端口映射
容器ip变动时候可以通过服务名直接网络通信而不受到影响
docker网络模式
bridge为每一个容器分配设置ip,并将容器连接到一个docker0虚拟网桥,默认为该模式
host容器将不会模拟出自己的网卡,配置自己的ip等,而是使用宿主机的ip和端口
none容器有独立的network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,ip等container新创建的容器不会创建自己的网卡和配置自己的ip,而是和一个指定的容器共享ip、端口范围等。|
bridge模式:使用–network bridge指定,默认使用docker0
host模式:使用–network host指定
none模式:使用–network none指定
container模式:使用–network container:name 或者容器id指定
bridge模式
host模式
–network host指定之后容器创建时不需要-p加端口,也无自己的ip。
容器将不会获得一个独立的network namespnce,而是和宿主机公用一个networkspace
container模式
自定义网络
before:容器之间默认模式为bridge,可以互相ping通ip,但是无法ping通容器名
after: 创建一个自定义network,容器之间可以互相ping通容器名
docker network create wcy docker run -d -p 3307:8080 –network wcy –name test1 docker.io/billygoo/tomcat8-jdk8 docker run -d -p 3308:8080 –network wcy –name test2 docker.io/billygoo/tomcat8-jdk8
九、docker-compose
compose是docker公司推出的一个工具软件,可以管理多个docker组成一个应用,需要定义一个YAML格式的配置文件docker-compose.yml,写好多个容器之间的调用关系,只需要一个命令就能同时启动关闭这些容器。
compose允许用户通过一个单独的docker-compose.yml模板文件(YAML格式),来定义一组相关的应用容器为一个项目(project)
compose核心概念,一个文件docker-compose.yml ,两要素,服务:一个个应用容器实例,比如订单微服务、库存微服务、mysql容器等;工程:由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
docker-compose 三个步骤:
a、编写dockerfile定义各个微服务应用并构建出对应的镜像文件
b、使用docker-compose.yml定义一个完整的业务单元,安排好整体应用中的各个容器服务。
c、最后执行docker-compose up命令来启动并运行整个程序,完成一键部署上线。
compose常用命令
docker-compose -h #查看帮助
docker-compose up #启动所有docker-compose服务
docker-compose up -d #启动所有docker-compose服务并后台运行
docker-compose down #停止并删除容器、网络、卷、镜像
docker-compose exec yml里面的服务id #进入容器实例内部docker-compose exec docker-compose.yml 文件中写的服务id /bin/bash
docker-compose ps #展示当前docker-compose编排过的运行的所有容器
docker-compose top #展示当前docker-compose编排过的容器进程
docker-compose log #查看容器输出日志
docker-compose config #检查配置
docker-compose config -q #检查配置,有问题才输出
docker-compose restart/stop/start #重启/停止/启动服务