docker高级

241 阅读13分钟

学习视频地址:www.bilibili.com/video/BV1gr…

docker复杂安装详说

安装mysql主从复制

主从搭建步骤

1、新建主服务器容器实例3307
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,将my.cnf文件内容写入
cd /mydata/mysql-master/conf
vim my.cnf
3、修改完配置后重启master实例
docker restart mysql-master
4、进入mysql-master容器
docker exec -it mysql-master /bin/bash
mysql -uroot -p
root
show databases;
5、master实例容器内创建数据同步用户
创建slave用户,只有这些用户可以拿数据
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
授权(可以做哪些权限的读取操作)
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、进入/mydata/mysql-slave/conf目录新建my.cnf
cd /mydata/mysql-slave/conf
vim my.cnf
8、修改完配置后重启slave实例
docker restart mysql-slave
9、在主数据库中查看主从同步状态(在mysql-master实例内部)
show master status;
10、进入mysql-slave容器内
docker exec -it mysql-slave /bin/bash
mysql -uroot -p
root
11、在从数据库中配置主从复制 (ifconfig ens33查看宿主机ip)
change master to master_host='宿主ip',master_user='slave',master_password='123456',master_port=3307,master_log_file='mall-mysql-bin.000001',master_log_pos=617,master_connect_retry=30;
12、在从数据库中查看主从同步状态( \G 竖着排列信息)
show slave status \G;
13、在从数据库中开启主从同步
start slave;
14、查看从数据库状态发现已经同步
show slave status \G;
15、主从复制测试
主机新建库-使用库-新建表-插入数据,ok
create database db01;
use db01;
create table t1 (id int,name varchar(20));
insert into t1 values(1, 'z3');
select * from t1;
从机使用库-查看记录,ok
use db01;
select * from t1;

mysql-master的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

mysql-slave的my.cnf

[mysqld]
## 设置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

安装redis集群

cluster(集群)-docker版 哈希曹分区进行亿级数据存储
1、哈希取余分区
2、一致性哈希算法
是什么?
为了解决分布式缓存数据变动和映射问题,一个机器宕机了,分母数量改变了,自然取余数不ok了。
能干嘛?
提出u一致性hash解决方案,目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。
3大步骤:
算法构建一致性哈希环;
服务器ip节点映射;
key落到服务器的落键规则;
3、哈希曹分区

Dockerfile

dockerfile文档:docs.docker.com/engine/refe…

image.png

是什么?
Dockerfile是用来构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

dockerfile构建3步曲

1、编写dockerfile文件
2、docker build命令构建镜像
3、docker run 依镜像运行容器实例

dockerfile解析

docker内容基础知识
1:每条保留字指令都 必须为大写字母 且后面要跟随至少一个参数
2:指令按照从上到下顺序执行
3:#表示注释
4:每条指令都会创建一个新的镜像层并对镜像进行提交

docker执行dockerfile大致流程
1、docker从基础镜像运行一个容器
2、执行一条指令并对容器做出修改
3、执行类似docker commit的操作提交一个新的镜像层
4、docker再基于刚提交的镜像运行一个新容器
5、执行dockerfile中的下一条指令直到所有指令都执行完成

dockerfile常用保留字指令

FROM:基础镜像,当前镜像是哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from
MAINTAINER:镜像维护者的姓名和邮箱地址
RUN:容器构建时需要运行的命令,两种格式:shell格式和exec格式,run是在docker build时运行
EXPOSE:当前容器对外暴露出的端口
WORKDIR:指定在创建容器后,终端默认登录进来的目录,一个落脚点
USER:指定该镜像以什么样的用户去执行,如果都不指定,默认是root
ENV:用来在构建镜像过程中设置环境变量,比如  ENV MY_PATH /user.mytest ;使用 WORKDIR $MY_PATH
ADD:将宿主机目录下的文件拷贝进镜像且会自动处理url和解压tar压缩包
COPY:类似ADD,拷贝文件和目录到镜像中,将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
VOLUME:容器数据券,用于数据保存和持久化工作
CMD:
作用:指定启动容器后要干的事情
CMD容器启动命令:
CMD指令的格式和 RUN相似,也支持两种格式
shell格式: CMD <命令>
exec格式:CMD [可执行文件, 参数1,参数2...]

注意:dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换。
它和RUN命令的区别:CMD是在docker run时运行,RUN是在docker build时运行
ENTRYPOINT
也是用来指定一个容器启动时要运行的命令,
类似于CMD指令,但是ENTRYPOINT不会被docker run 后面的命令覆盖
而且这些命令行参数会被当做参数送给ENTRYPOINT指令指定的程序

命令格式:ENTRYPOINT ["<executeable>", "param1","param2"...]
ENTRYPOINT可以和CMD一起用,这里的CMD等于是给ENTRYPOINT传参。
当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令,它两个组合会变成<ENTRYPINT>"<CMD>"

image.png

案例

要求centos有vim+ifconfig+jdk8
jdk下载地址:https://www.oracle.com/java/technologies/downloads/#java8(现在的版本高,可以下载jdk以往版本,以免出错)
我下的版本为 jdk-8u171-linux-x64.tar.gz
下载tar.gz后缀的包就可以
docker pull centos
docker run -it centos /bin/bash
vim  发现没有vim命令
ifconfig 发现没有ifconfig命令
java -version 发现没有java

编写Dockerfile 注意D大写
cd /
mkdir myfile
cd /myfile
想办法将 jdk-8u171-linux-x64.tar.gz 放进去

把Dockerfile内容写进去(见下文)
vim Dockerfile   
docker build --help
// 执行docker build命令(模板)注意后面有个. 代表 当前目录
docker build -t 新镜像名字:TAG .

docker build -t centosjava8:1.5 .
运行完会生成centosjava8镜像
docker run -it centosjava8:1.5 /bin/bash
vim 1.txt
:wq
ifconfig
java -version

Dockerfile内容

FROM centos:7
MAINTAINER feng<feng@126.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 glibci.686 
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
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 80

CMD echo $MYPATH
CMD echo "success-----------ok"
CMD /bin/bash

虚悬镜像

仓库名和标签名都是none的镜像称之为虚悬镜像。
用Dockerfile写一个

cd /myfile
mkdir test
cd test
vim Dokcerfile
写入如下内容
FROM ubuntu
CMD echo 'action is success'

build镜像
docker build .
docker images 发现有个仓库名和标签名都是none的镜像

平时删除错误时也会出现虚悬镜像,会让程序存在一定风险

单独查看全部的虚悬镜像
docker image ls -f dangling=true
删除全部的虚悬镜像
docker image prune

用Dockerfile构建myubuntu镜像

1、编写Dockerfile文件
cd /
mkdir mydockerfile
cd mydockerfile
vim Dockerfile
============输入如下内容============
FROM ubuntu
MAINTAINER fqh<fqh@126.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH

#RUN apt-get update
#RUN apt-get install net-tools
#RUN apt-get install -y iproute2
#RUN apt-get install -y inetutils-ping

EXPOSE 80

CMD echo $MYPATH
CMD echo "install inconfig cmd into ubuntu success------ok"
CMD /bin/bash
==================================

docker网络

docker不启动,默认的网络模式:

ifconfig 会有这3个网桥
ens33  外界连接虚拟机的网桥
lo
virbr0

docker启动后

ifconfig
会多出docker0网桥,docker就是根据这个172.17.0.1与宿主机或其它docker容器通信

安装完docker后会默认创建3大网络模式

docker network ls  查看所有的docker网路
brige
host
none

docker network --help 查看docker network命令说明
docker network create networkname 创建docker网络
docker network rm networkname 删除docker网络
docker network inspect networkname 查看某个网络数据源

docker网络能干嘛?

容器间的互联通以及端口映射
容器ip变动的时候可以通过服务名直接网络通信而不受到影响

docker网络模式

bridge:为每一个容器分配、设置ip等。并将容器连接到一个docker0,虚拟网桥默认为该模式。
host:容器将不会虚拟出自己的网卡,配置自己的IP等。而是使用宿主机的IP和端口。
none:容器有独立的network namespace,但并没有对其进行任何的网络设置,如分配veth pair和网桥连接,IP等。
container:新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等。

创建dokcer网络时通过 --network [bridge|host|none|container:name或容器id] 指定网络模式
bridge模式默认使用docker0网桥

查看容器的网路情况 docker inspect 容器名  看最后20行 network的信息,可以看到容器ip和网关等信息
docker run -d --name u1 ubuntu /bin/bash
docker run -d --name u2 ubuntu /bin/bash
docker inspect u2 
docker stop u2 
docker run -d --name u3 ubuntu /bin/bash
docker inspect u3 发现u3的ip和原来u2停止前的ip一样,得出结论,容器内的ip是会变动的
所以规划好docker的网络时很有必要的。一般创建一个docker网络专门制定一个服务使用。方便docker集群通信的管理。

docker network bridge

image.png

查看几个网络的内部情况 docker network inspect 网络名
docker network inspect bridge

dokcer启动后会默认创建一个docker0默认网桥,它有一个docker0内部接口,该桥接网络的名称叫docker0,他在内核层连接了其它的物理或虚拟网卡,这就将所有容器和本地主机都放在同一个物理网络,docker默认指定了docker0接口的ip地址和子网掩码,让主机和容器可以通过网桥相互通信。

创建容器时如果没有指定容器网络,会默认使用docker0网桥,每个容器会分配到自己的ip
docker run -d -p 8081:8080 --name tomcat81 tomcat
docker run -d -p 8082:8080 --name tomcat82 tomcat
ip addr
发现在docker0下面多了两个veth开头的网络:336-->335  338-->337
docker上面都叫veth,容器内都叫eth0,他们的数字是一一匹配,成双成对的。
进入tomcat81
docker exec -it tomcat81 /bin/bash
ip addr 
335 --> 336

docker network host

image.png

host网桥:直接使用宿主机的ip地址与外界进行通信,不再额外需要NAT转换。
查看host网桥内部情况
docker network inspect host
使用host网络直接用宿主机的ip和端口,再指定端口就多余了,去掉-p 8083:8080
docker run -d --network host --name tomcat83 tomcat
docker inspect tomcat83 发现tomcat83并没有自己的ip和子网掩码,因为他是和宿主机共用一个
用浏览器访问 宿主机ip:8080可以访问到tomcat83

docker network none

none网络模式下只有lo本地模式,没有其他的模式了。
不为docker容器进行任何的网络配置
平时很少用none的网络模式,了解一下即可

docker network container

image.png

alpine是一个更精简的linux镜像
docker run -it --name alpine1 alpine /bin/sh
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh
进入两个容器 ip addr 发现使用的是一样的网络
当alpine1停掉后,alpine2就只剩一个lo(本地网络了)

自定义网络模式

删除原来所有的容器
docker rm -f $(docker ps -a -q)
创建tomcat81和tomcat82容器
docker run -d -p 8081:8080 --name tomcat81 tomcat
docker run -d -p 8082:8080 --name tomcat82 tomcat
进入tomcat81容器ping tomcat82的ip可以ping通(证明docker上的容器是可以互相通信的)
但是ping tomcat82的容器名ping不通
如果将两个容器加入到同一个自定义网络模式,就可以使用容器名ping通了,即使容器的ip有变化,也可以ping通!
=========这就需要用自动以网络模式了==========
1、创建自定义网络模式 bb_network
docker network create aa_network
docker network ls
2、新建容器加入上一步新建的自定义网络
docker run -d -p 8081:8080 --network aa_network --name tomcat81 tomcat
docker run -d -p 8082:8080 --network aa_network --name tomcat82 tomcat
3、在容器内ping另一个容器
在tomcat81内ping tomcat82
ping tomcat82 发现ping通了

docker compose容器编排

是什么?

docker-compose是dokcer官方的开源项目。
负责实现对docker容器集群的快速编排。

docker-compose是dokcer公司退出的一个工具软件,可以管理多个docker容器生成一个应用。
你需要定义一个YAML格式的配置文件,docker-compose.yml,**写好多个容器之间的调用关系**,然后只要一个命令就能同时启动/关闭这些容器。

docker建议一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独分割开来,但是这样我们又面临一个问题。

如果需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像?这样太繁琐了,所以官方退出了多服务部署工具docker-compose。

例如实现一个web微服务项目,出了web服务容器本身,往往还需要加上后端的数据库mysql,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。

compose允许用户通过单独的docker-compose.yml模板文件(YAML格式),来定义一组相关联的容器为一个项目(project)。

可以很容易的用一个文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-compose解决了容器与容器之间如何编排的问题。

compose下载安装

文档地址:docs.docker.com/reference/
这里用高版本version3,需要与docker引擎版本匹配,可以在version3里查阅。
compose下载地址:docs.docker.com/compose/ins…
这里选择独立安装(相对于compose-plugin)

1、下载并安装Compose独立版
curl -SL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
或者用这个命令
curl -SL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-$(uname -S)-$(uname -m) -o /usr/local/bin/docker-compose
2、加一个读写权限
chmod +X /usr/local/bin/docker-compose
3、检查安装是否成功
docker compose version

卸载compose

rm /usr/local/bin/docker-compose

compose核心概念

1、一个文件
docker-compose.yml
2、两要素
1):服务(service)
就是鲸鱼背上一个一个容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器、redis容器等。
2):工程(project)
由一组关联的应用容器组成的一个完整业务单元,在docker-compose文件中定义。

compose使用的3个步骤

1、编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
2、使用docker-compose.yml
3、定义一个完整业务单元,安排好整体应用中的各个容器服务。
4、最后执行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 dokcer-compose.yml文件中写的服务id /bin/bash
docker-compose ps #展示当前docker-compose编排过的运行的所有容器
docker-compose top #展示当前docker-compose编排过的容器进程
docker-compose logs yml里面写的服务id #查看容器输出日志
docker-compose config #检查配置
docker-compose config -q #检查配置,有问题才有输出
docker-compose restart #重启服务
docker-compose start #启动服务
docker-compose stop #停止服务

编写docker-compose.yml

# compose版本,以后用3以后的版本
version: "3"

# services里面写每个服务
services:
  # 下面的微服务相当于docker run -d -p 6001:6001 -v /app/microService:/data --network atguigu_net --name ms01 zzyy_docker:1.6
  #微服务的服务(服务名不冲突就行了)
  microService:
    # 镜像
    image: zzyy_docker:1.6
    # 容器名称
    container_name: ms01
    # 端口映射
    ports:
      - "6001:6001"
    # 数据券
    volumes:
      - /app/microService:/data
    networks:
      - atguigu_net
    # 此服务要依赖于redis、mysql先启动
    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:
      - atguigu_net
    # 命令 用redis-server 启动了/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf

  mysql:
    image: mysql:5.7
    # 环境
    environment:
      # root密码
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      # 新建个数据库
      MYSQL_DATABASE: 'db2021'
      # 新建个用户
      MYSQL_USER: 'zzyy'
      # 用户密码为 zzyy123
      MYSQL_PASSWORD: 'zzyy123'
    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:
      - atguigu_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问

networks:
  # 相当于 docker network create atguigu_net
  atguigu_net:

编排

在docker-compose.yml通目录下
1、让docker-compose在当前用户组有权限
chmod +x /usr/local/bin/docker-compose
2、检查docker-compose.yml的配置有没有问题
docker-compose config -q
3、执行编排命令
docker-compose up -d
4、关停
docker-compose stop

docker可视化工具portainer

是什么?

对docker监控和统计

官网: www.portainer.io

步骤:
1、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-ce:latest

参数说明
--restart=always docker重启,这个服务就会重启
2、第一次登陆许创建admin,访问地址xxx.xxx.xxx:9000
在浏览器输入 ip:9000 输入一个8位密码
3、设置admin用户和密码后首次登陆
4、选择local选项卡后本地docker详细信息展示(compose、镜像、容器、数据券等)
5、上一步相当于什么命令?
docker system df

图形化工具能干些什么?
1、控制容器的启动、停止等
2、查看容器日志
3、查看容器内部细节(inspect)
4、可以直接进入容器内操作

5、用portainer安装nginx
1)、container选项卡点击add container
2)、输入容器名  相当于 --name xxx
3)、选择镜像  nginx
4)、添加端口映射 80:80
5)、构建容器