一、Docker简介
1、是什么?
解决了运行环境和配置问题软件容器。方便做持续集成并有助于整体发布的容器虚拟化技术。一次构建到处运行
2、能干嘛
linux虚拟机的缺点:1. 资源占用多 2. 冗余步骤多 3. 启动慢
Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离,没有自己的内核,而且以没有进行硬件虚拟,每个容器之间互相隔离。
二、Docker安装
1、Docker的基本组成
镜像 容器 仓库
* Docker镜像(Images)就是一个只读的模板。镜像可以用来创建很多容器。
* 容器是用镜像创建出来的运行实例。可以把容器看成一个简易版的Linux环境。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
* 仓库是集中存放镜像文件的场所。仓库分为公开仓库和私有仓库。
架构图:
2、安装步骤
以CentOS7举例,官方文档地址:Install Docker Engine on CentOS | Docker Documentation
1.卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine2.需要的安装包
yum install -y yum-utils
3.设置镜像的仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum软件包索引 yum makecache fast
4.安装docker相关的 docker-ce 社区版 ee 企业版
yum install docker-ce docker-ce-cli containerd.io
5.启动docker systemctl start docker
6.查看安装版本 docker version
7.docker run hello-word
8.查看一下下载的这个hello-word镜像
docker images
还可以使用阿里云容器镜像服务进行进一步加速
三、Docker正篇
1、镜像命令
* docker images 列出本地主机上的镜像
-a:列出本地所有的镜像(含中间影像层)
-q:只显示镜像ID
--digests:显示镜像的摘要信息
--no-trunc:显示完整的镜像信息
* docker search 某个xxx镜像名字
-s 30 tomcat 列举点赞超过30的
* docker pull 拉取的某个xxx镜像的名字:版本号 默认是:latest
* docker rmi -f 删除的某个xxx镜像名字ID:版本号 默认是:latest
删除多个 docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部 docker rmi -f $(docker images -qa)
2、容器命令
* 有镜像才能创建容器,这是根本前提(下载一个CentOS镜像演示)
* 新建并启动容器
docker run [options] image(镜像ID) [command] [arg...]
--name="容器新名字":为容器指定一个名称
-d:后台运行容器,并返回容器ID,也即启动守护式容器
-i:以交互模式运行容器,通常与-t同时使用
-t:为容器重新分配一个伪输入终端,通常与-i一起使用
-P:随机端口映射
-p:指定端口映射,有一下四种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
* 查看正在运行的所有容器 docker ps
-a:列出当前所有正在运行的容器+历史上运行过的
-l:显示最近创建的容器
-n:显示最近n个创建的容器
-lq:静默模式,只显示容器编号
--no-trunc:不截断输出
* 退出容器
exit 容器停止退出
ctrl+p+q 容器不停止退出
* 启动容器 docker start 容器ID或容器名
* 重启容器 docker restart 容器ID或容器名
* 停止容器 docker stop 容器ID或容器名
* 强制停止容器 docker kill 容器ID或容器名
* 删除容器 docker rm 容器ID或容器名
* 一次性删除所有容器 docker rm -f $(docker ps -qa)
重要:
* 查看日志: docker logs -ft --tail
-t 时加入时间戳 -f跟随最新的日志打印 --tail 显示最后多少条
* 查看容器内的进程 docker top 容器ID
* 查看容器内部细节 docker inspect 容器ID
* 重新进入后台容器
在容器中打开新的终端,并且可以启动新的进程 docker exec -it 容器ID /bin/bash
直接进入容器启动命令的终端,不会启动新的进程 docker attach 容器ID
*将容器内文件拷贝到主机上 docker cp 容器ID:容器内路径 目的主机路径
*将容器拷贝到主机上 docker export 容器ID > 文件名.tar
恢复:cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
3、提交镜像副本使之成为一个新的镜像
ubuntu镜像中安装vim
apt-get update #更新我们的包管理工具
apt-get install vim #安装vim
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:版本号
4、推送和拉取到阿里云
创建阿里云镜像服务
5、Docker Registry本地私服
1) docker pull registry
2) 启动:docker run -d -p 5000:5000 -v /zsh/myregistry:/tmp/registry --privileged=true registry
3) 安装ifconfig命令:apt-get update apt-get install net-tools
4) 验证私服库有什么镜像:curl -XGET http://ip:5000/v2/_catalog
5) 修改符合私服规范镜像名称:docker tag iubuntu:1.1 ip:5000/iubuntu:1.1
6) 修改配置文件使之支持http:
7) 推送至本地私服库:docker push ip:5000/iubuntu:1.1
拉取:docker pull ip:5000/iubuntu:1.1
6、容器数据卷
上面标明蓝色的地方
查看镜像信息、绑定数据卷等:docker inspect 容器ID
容器内部只能读不能写: -v /zsh/myregistry:/tmp/registry:ro
容器卷的继承和共享:【u2 继承 u1】
docker run -it --privileged=true -v /mydocker/u:tmp/u ---name u1 ubuntu
docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu
7、安装基础软件
1) Tomcat:docker pull billygoo/tomcat8-jdk8
2) mysql:docker pull mysql:5.7
运行:docker run -d -p 3306:3306 --privileged=true -v /opt/mysql/log:/var/log/mysql -v /opt/mysql/data:/var/lib/mysql -v /opt/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
修改编码: 查看:show variables like 'character%'; 在conf目录新建my.cnf
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
重启:docker restart mysql
进入:docker exec -it 容器ID /bin/bash
3) redis:docker pull redis:6.0.8
运行:docker run -d -p 6379:6379 --name redis --privileged=true -v /opt/redis/redis.conf:/etc/redis.conf -v /opt/redis/data:/data redis:6.0.8 redis-server /etc/redis.conf
8、mysql主从复制docker版
主sql服务器
1) 运行:docker run -d -p 3307:3306 --privileged=true -v /opt/mysql/mysql-master/log:/var/log/mysql -v /opt/mysql/mysql-master/data:/var/lib/mysql -v /opt/mysql/mysql-master/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql-master mysql:5.7
2) 创建并修改配置 vim my.cnf
[client]
default_character_set=utf8
[mysqld]
## 设置数据库编码
collation_server = utf8_general_ci
character_set_server = utf8
## 设置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)创建用户并授予权限
create user 'slave'@'%' identified by '123456';
grant replication slave,replication client on *.* to 'slave'@'%';
从sql服务器
1) 运行:docker run -d -p 3308:3306 --privileged=true -v /opt/mysql/mysql-slave/log:/var/log/mysql -v /opt/mysql/mysql-slave/data:/var/lib/mysql -v /opt/mysql/mysql-slave/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql-slave mysql:5.7
2) 创建并修改配置 vim my.cnf
[client]
default_character_set=utf8
[mysqld]
## 设置数据库编码
collation_server = utf8_general_ci
character_set_server = utf8
## 设置server_id 同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备Slave作为其他数据库实例的Master时使用
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_only=1
3)在主数据库中查看主从同步状态:show master status;
4)在从服务器中配置主从复制
change master to master_host='主数据库IP',master_user='在主数据库创建的用于同步数据的用户号账号',master_password='密码',master_port=3307,master_log_file='指定从数据库要复制数据的日志文件,通过查看主数据库的同步状态,获取File参数',master_log_pos=获取Position参数,master_connect_retry=30(连接失败重试的时间间隔,单位为秒);
5)在从数据库中查看主从同步状态:show slave status;
6)在从服务器中开启主从同步:start slave;
9、分布式存储算法
1)哈希取余算法 hash/集群台数
2)一致性哈希算法[0,2^32-1]
3)哈希槽分区(解决一致性哈希算法的数据倾斜问题)
10、redis集群配置docker版
1)运行:docker run -d --name redis-node-1 --net host --privileged=true -v /opt/redis/redis-node-1/data:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
2)构建主从关系(进入到其中一台redis服务器):redis-cli --cluster create ip:6381 ip:6382 ip:6383 ip:6384 ip:6384 ip:6385 ip:6386 --cluster-replicas 1
--cluster-replicas 1 表示为每个master创建一个slave节点
3)进入6381作为切入点,查看集群状态:
redis-cli -p 6381
cluster info
cluster nodes
4)进入到容器中,集群环境连接redis-cli :redis-cli -p 6381 -c
5)查看集群信息:redis-cli --cluster check ip:6381
6)主从容错切换迁移:master宕机之后再恢复变成slave(解决:停掉当前master使之变成slave)
7)主从扩容
运行6387:docker run -d --name redis-node-7 --net host --privileged=true -v /opt/redis/redis-node-7/data:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
运行6388:docker run -d --name redis-node-8 --net host --privileged=true -v /opt/redis/redis-node-8/data:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
* 将新增的6387作为master节点加入集群:redis-cli --cluster add-node ip:6387 ip:6281
* 检查集群情况第1次:redis-cli --cluster check ip:6387 (结果是没有分配槽位)
* 重新分配槽号(三个旧节点匀一点给6387):redis-cli --cluster reshard ip:port
* 为主节点分配从节点:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID(ID为上边蓝色圈着的)
* 检查集群情况第2次:redis-cli --cluster check ip:6387 (完成)
8)主从缩容
先删除从机 —> 重新分配槽号 —> 删除主机
* 获得6388节点ID:redis-cli --cluster check ip:6381
* 删除6388从节点:redis-cli --cluster del-node ip:port 从机6388节点ID
* 重新分配槽号:redis-cli --cluster reshard ip:port
* 删除6387主节点:redis-cli --cluster del-node ip:port 主机6387节点ID
11、Dockerfile
Dockerfile reference | Docker Documentationhttps://docs.docker.com/engine/reference/builder/
1)保留字
* FROM 基础镜像,当前新镜像基于哪个镜像,指定一个存在的镜像作为模板
* MAINTAINER 镜像维护者的姓名
* RUN 是在docker buid时运行
* EXPOSE 对外暴露出的端口
* WORKDIR 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
* ENV 用来在构建镜像过程中设置环境变量
* VOLUME 容器数据卷,用户数据保存和持久化工作
* ADD 将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
* COPY 类似ADD,拷贝文件到镜像中
* CMD 指定容器启动后要做的事情,会被docker run后面的指令覆盖
* ENTRYPOINT 也是指定容器启动后要做的事情,但不会被docker run后面的指令覆盖
2)编写Dockerfile
FROM centos
MAINTAINER zsh
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编译器
RUN yum -y install vim
#安装ifconfig民令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库、maven
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD是相对路径jar,把jdk-8u191-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u191-linux-x64.tar.gz /usr/local/java
ADD apache-maven-3.6.3-bin.tar.gz /usr/local
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_191
ENV PATH $JAVA_HOME/bin:$PATH
#配置maven变量
ENV MAVEN_HOME /usr/local/apache-maven-3.6.3
ENV PATH $MAVEN_HOME/bin:$PATH
CMD /bin/bash
3)构建:docker build -t centos-java8 .
了解:虚悬镜像:仓库名和标签都是none
查看:docker image ls -f dangling=true
删除:docker image prune
微服务实战:
Dockerfile文件 docker run -d -p port:port 镜像ID
#基础镜像使用java
FROM java:8
#作者
MAINTAINER zsh
#VOLUME指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并连接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器中
ADD 工程名.jar 新工程名.jar
#运行jar包
RUN bash -c 'touch /新工程名.jar'
ENTRYPOINT ["java","-jar","/新工程名.jar"]
#暴露微服务端口号
EXPOSE port
12、docker netword
docker network --help
自定义网络:
默认的bridge只能通过ip访问,不能通过--name 的服务名访问,并且某个docker宕机后ip会变动
docker network create zsh_network (完成IP和服务名的ping通)
13、Docker-compose容器编排
1)定义:对Docker容器集群的快速编排
2)安装/卸载:Install Docker Compose | Docker Documentation
3)服务、工程概念
4)步骤
5)Compose常用命令
6)实战
mysql + redis + springboot.jar
编写docker-compose.yml,将微服务里面的IP改成docker的服务名redis、mysql
version: "3"
services:
microService:
image: 镜像名字
container_name: springboot #容器启动后的名字
ports:
- "port:port"
volumes:
- /opt/springboot/:/data #自定义容器卷
networks:
- zsh_network #自定义network 命令:docker netword create zsh_network
depends_on:
- redis
- mysql
redis:
images: redis:6.0.8
ports:
- "6379:6379"
volumes:
- /opt/redis/redis.conf:/etc/redis/redis.conf
- /opt/redis/data:/data
network:
- zsh_network
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: '123456'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
#创建数据库
MYSQL_DATABASE: ''
#创建登录用户和密码
MYSQL_USER: ''
MYSQL_PASSWORD: ''
ports:
- "3306:3306"
volumes:
- /opt/mysql/data:/var/lib/mysql
- /opt/mysql/conf/my.cnf:/etc/my.cnf
- /opt/mysql/init:/docker-entrypoint-initdb.d
networks:
- zsh_network
command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
#docker network create zsh_network命令
networks:
zsh_network
检查配置是否有问题 docker-compose config -q —> 执行 docker-compose up -d
停止 docker-compose stop
14、轻量级可视化工具Portainer
Install Portainer with Docker on Linux - Portainer Documentationhttps://docs.portainer.io/v/ce-2.9/start/install/server/docker/linux
运行并安装: --restart=always表示docker重启它也重启
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
登录:http://192.168.35.136:9000/
15、Docker容器监控之CAdvisor+InfluxDB+Granfana
小公司查看内存、CPU等用:docker stats
编写docker-compose.yml —> 检查配置是否有问题 docker-compose config -q
version: "3.1"
valumes:
grafana_data: {}
services:
#负责存储
influxdb:
image: tutum/influxdb:0.9
restart: always
environment:
- PRE_CREATE_DB=cadvisor #创建数据库
ports:
- "8083:8083"
- "8086:8086"
volumes:
- /opt/influxdb:/data
#负责收集
cadvisor:
image: google/cadvisor
links:
- influxdb:influxsrv
command: -storage_driver=influxdb-storage_driver_db=cadvisor-storage_driver_host=influxsrv:8086
restart: always
ports:
- "8080:8080"
valumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
#负责图形化界面
grafana:
image: grafana/grafana
user: "104"
restart: always
links:
- influxdb:influxsrv
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- HTTP_USER=admin
- HTTP_PASS=admin
- INFLUXDB_HOST=influxsrv
- INFLUXDB_PORT=8086
- INFLUXDB_NAME=cadvisor
- INFLUXDB_USER=root
- INFLUXDB_PASS=root