Docker实战-高级篇

4,128 字 · 约 14 分钟Docker#Docker#容器编排#云原生

Docker实战-高级篇

一、Docker复杂安装

MySQL主从复制

看ShardingSphere一节,已经部署过

1~2亿条数据需要缓存,请问如何设计存储案例

单机单台肯定不可能

哈希取余

哈希取余:优点:简单粗暴,直接有效,只需要预估好机器数,就能保证一段时间的数据支撑;缺点:集群扩缩容麻烦,映射关系需要重新计算;

一致性哈希算法

一致性哈希算法:解决服务器个数变动时的映射关系变化;

需要构建一致性哈希环:

一致性哈希算法必然有个Hash函数并按照算法产生Hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个Hash空间(大概0-2^32-1),这个是一个线性空间,通过适当的逻辑控制使其首位相连,这样在逻辑上形成一个环形空间

它也是按照取模的方法,不过是对2^32取模

第二步是服务器IP节点映射:

将集群中某个IP节点映射到环上的某一个位置,将哥哥服务器使用Hash获得一个哈希值,具体可以使用服务器的IP或者主机名作为关键字进行哈希,这样每台机器都能确定在哈希环上的位置

第三步是key落到服务器上的规则:

当需要存储一个kv对,首先计算key的Hash值,将这个key使用相同的函数hash计算处hash值并确定在此环上的位置,从此位置沿着环顺时针行走,遇到的第一台服务器就是它存储的服务器

优点:

  • 解决了哈希取余的容错性:假设某台服务器宕机,只会影响到其前面的那台机器,数据转移到后一台服务器
  • 扩展性:扩容后不会影响

缺点:

  • 会有数据倾斜问题:当节点太少的情况下,缓存对象会集中缓存到某一台服务器上
哈希槽分区

为了解决一致性哈希算法的数据倾斜问题

哈希槽实质上就是一个数组,数组0,2^14-1形成Hash Slot空间

解决了均匀分配的问题,在数据和节点之间又加入了一层,这层被称为哈希槽,用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里面是数据

槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动

哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配

一个集群只能有16484个槽,便好0-16383,这些槽会集中分配给集群中的所有主节点,分配策略没有要求,可以指定哪些便好的槽分配给哪个主节点,集群会记录节点和槽的对应关系,解决了节点和槽的问题之后,接下来对key进行哈希,然后对16384取余,余数是几,key就落到哪个槽中,以槽为单位移动数据

Redis集群实现

三主三从

创建虚拟网卡,主要用于Redis集群与外界的网络通信,一般常用桥接模式

docker network create --subnet=192.168.100.0/24 rcn

创建redis.conf配置文件:

mkdir docker-redis-cluster && cd docker-redis-cluster

新建6台实例

进入容器,构建集群关系

二、DockerFile解析

介绍

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需要的指令和参数构成的脚本

Dockerfile构建

步骤:

  • 编写Dockerfile文件
  • docker build命令构建镜像
  • docker run依照镜像运行实例

Dockerfile内容基础知识:

  • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • 指令按照从上到下顺序执行
  • #表示注解
  • 每条指令都会创建一个新的镜像层并对镜像进行提交

Docker执行Dockerfile的流程:

  • Docker从基础镜像运行一个容器
  • 执行一条指令并对容器做出修改
  • 执行类似Docker commit的操作提交一个新的镜像层
  • docker再基于刚才提交的镜像运行一个新容器
  • 执行Dockerfile中的下一条指令直到所有指令都执行完成

从应用软件角度看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个阶段

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署和运维,三者缺一不可

Dockerfile常用保留字

FROM

基础镜像,当前新镜像是基于哪个镜像,指定一个已经存在的镜像作为模板,第一条必须是FROM

MAINTAINER

镜像维护者的姓名和邮箱

RUN

容器构建时运行的命令

两种格式:

  • shell格式:RUN后面直接跟命令,如:RUN yum -y install vim
  • exec格式:格式:RUN ["可执行文件", "参数1", "参数2"]

RUN是在docker build时运行的

EXPOSE

当前容器对外暴露的端口

WORKDIR

指定在创建容器后,终端默认登录进来的工作目录

USER

指定该镜像以什么样的用户去执行,如果都不指定,默认是root

ENV

用来在构建镜像过程中设置环境变量

也可以在其他指令中使用这些环境变量

ADD

将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包

COPY

类似ADD,拷贝文件和目录到镜像中

COPY src dest

VOLUME

容器数据卷,用于数据保存和持久化工作

CMD

指定容器启动后要干的事情

CMD指令格式与RUN相似

Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

和RUN指令的区别:

  • RUN是在docker build时运行
  • CMD是容器启动后运行
ENTRYPOINT

也是用来指定一个容器启动时要运行的命令

类似于CMD指令,但是ENTRYPOINT不会被docker run后面的命令覆盖,而且这些命令行参数会被当做参数传给ENTRYPOINT指令指定的程序

命令格式:ENTRYPOINT ["<executable>", "param1", ...]

ENTRYPOINT可以和CMD一起使用,一般是变参才会使用CMD,这里的CMD相当于给ENTRYPOINT传参

当指定了ENTRYPOINT之后,CMD的含义就发生了变化

自定义镜像centosjdk8

将centos中具备vim、ifconfig、jdk8等环境

拉取centos镜像

docker pull centos:centos7.9.2009

运行并进入实例:

docker run -it eeb6ee3f44bd /bin/bash

下载jdk

编写Dockerfile文件:vim Dockerfile

FROM centos:centos7.9.2009
MAINTAINER wang<no>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/CentOS-Base.repo && \
    sed -i 's|^#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com|g' /etc/yum.repos.d/CentOS-Base.repo && \
    yum clean all && yum -y makecache

RUN yum -y install vim
RUN yum -y install net-tools
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
ADD jdk-8u421-linux-x64.tar.gz /usr/local/java/

ENV JAVA_HOME /usr/local/java/jdk1.8.0_421
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

运行构建命令:别忘了后面的.

docker build -t 新镜像名字:TAG .

此时镜像就构建成功了,可以运行一个容器查看

虚悬镜像

仓库名和标签名都是none的镜像,俗称dangling image

通过以下命令查看虚悬镜像:

docker image ls -f dangling=true

通过如下命令删除虚悬镜像:

docker image prune

三、Docker微服务实战

新建一个SpringBoot工程,将其上传到Linux上

编写Dockerfile文件:

FROM openjdk:8u111-jdk

MAINTAINER wang

VOLUME /tmp

ADD docker-demo-0.0.1-SNAPSHOT.jar docker-demo.jar

RUN bash -c 'touch /docker-demo.jar'

ENTRYPOINT ["java", "-jar", "/docker-demo.jar"]

EXPOSE 30000

构建镜像

docker build -t docker-demo:1.0 .

四、Docker网络

介绍

Docker不启动,默认的网络情况:

virbr0:虚拟网桥服务

Docker启动后:

会有一个docker0虚拟网桥

使用命令:docker network ls命令展示docker网络列表:

NETWORK ID NAME DRIVER SCOPE dd18f3c90671 bridge bridge local 6035c624bb1b host host local f546edbfc3ba none null local

docker默认创建3个网络模式

docker网络命令

create:创建网络

rm:删除一个或多个网络

inspect:查看网络情况

ls:展示网络列表

作用

容器间的互联通信以及端口映射

容器IP变动的时候可以通过服务名直接网络通信而不受到影响

网络模式

bridge:桥接,为每一个容器分配、设置IP,并将容器连接到docker0,默认模式

host:容器不会虚拟出自己的网卡,配置自己的IP,而是使用宿主机的IP和端口

none:容器有独立的network namespace,但并没有对其进行任何网络设置

container:新创建的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围

使用参数:--network args来指定网络模式

docker容器内IP是会发生变化的

bridge模式

Docker会默认创建一个docker0网桥,其上有个docker0内部接口,它在内核层联通了其他的物理或虚拟网卡,这将所有容器和本地主机都放到了同一个物理网络,Docker默认指定了docker0的IP地址和子网掩码,让主机和容器之间可以通过网桥互相通信

虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中

当创建一个 Docker 容器的时候,同时会创建了一对 veth pair接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。

img

host模式

相当于Vmware中的NAT模式,与宿主机在同一个网络中,但没有独立IP地址。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。可以通过 --net=host 指定使用 host 网络。

img

container模式

Docker网络container模式是指定其和已经存在的某个容器共享一个 Network Namespace,此时这两个容器共同使用同一网卡、主机名、IP 地址,容器间通讯可直接通过本地回环 lo 接口通讯但这两个容器在其他的资源上,如文件系统、进程列表等还是隔离的

img

none模式

容器有自己的网络命名空间,但不做任何配置,它与宿主机、与其他容器都不连通的。

这种模式很少用到

自定义网络

不使用自定义网络,使用IP可以相互ping通,但是使用服务名不可以

五、Docker-Compose容器安排

Docker-Compose是Docker官方推出,用于实现对Docker容器集群的快速编排

需要定义一个YAML格式的配置文件,写好多个容器之间的调用关系,然后只要一个命令就可以同时启动或关闭这些容器

最新版的docker安装时会自动以插件的形式安装docker compose

核心概念

一个文件,两个要素

文件是指:docker-compose.yaml

两个要素:

  • 服务:一个个容器实例
  • 工程:由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yaml中定义

使用步骤:

  • 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
  • 使用docker-compose.yaml定义一个完整业务单元,安排好整体应用中的各个容器服务
  • 最后,执行docker compose up命令来启动并运行整个应用程序,完成一键部署上线

常用命令

格式:

docker compose [OPTIONS] COMMAND

build:格式为 docker-compose build [options] [SERVICE...],构建(重新构建)项目中的服务容器,服务容器一旦构建后,将会带上一个标记名,例如对于 web 项目中的一个 db 容器,可能是 web_db。

docker compose --help:查看帮助

docker compose up:启动所有docker comose服务

docker compose up -d:启动所有服务并后台运行

docker compose down:停止并删除容器、网络、卷、镜像

docker compose exec yml里面的服务ID:进入容器内部执行yaml中的服务ID /bin/bash

docker compose ps:展示当前编排过的所有运行中的容器

docker compose top:展示运行的容器进程

logs:查看容器输出日志

config -q:检查配置,有问题才输出

config:检查配置

start、stop、restart:启动、停止、重启三板斧

命令选项

  • -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。
  • -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
  • --verbose 输出更多调试信息。
  • -v, --version 打印版本并退出。

compose模板文件

默认的模板文件:

version: "3"

services:
  webapp:
    image: examples/web
    ports:
      - "80:80"
    volumes:
      - "/data"

注意每个服务都必须通过image指令指定镜像或者build指令(需要Dockerfile)来自动构建生成镜像

如果使用build指令,在Dockerfile中设置的选项将会自动被获取,无需在docker-compose.yaml中重复设置

build指令

指定Dockerfile所在文件夹的路径(可以是绝对路径,或者相对docker-compose.yml文件的路径);compose将会利用它自动构建这个镜像,然后使用这个镜像

也可以使用contex指令指定Dockerfile所在文件夹的路径

使用dockerfile指令指定Dockerfile文件名

使用arg指令指定构建镜像时需要用到的变量

image

指定为镜像名称或者镜像ID,如果镜像在本地不存在,compose会尝试拉取这个镜像

ports

暴露端口信息,可以使用容器端口格式(HOST:CONTAINER),或者仅仅指定容器的端口,宿主机会随机选择端口

注意:当使用 *HOST:CONTAINER* 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 *YAML* 会自动解析 *xx:yy* 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。

volumes

数据卷挂载的路径设置,可以设置为宿主机路径或者数据卷名称,并且可以设置访问模式

该指令支持相对路径

volumes:
 - /var/lib/mysql
 - cache/:/tmp/cache
 - ~/configs:/etc/configs/:ro
networks

配置容器连接的网络

version: "3"
services:

  some-service:
    networks:
     - some-network
     - other-network

networks:
  some-network:
  other-network:
container_name

指定容器名称。默认将会使用 项目名称_服务名称_序号 这样的格式。

注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。

depends_on

解决容器的依赖、启动先后的问题。

注意:web 服务不会等待 redis db 「完全启动」之后才启动。

environment

设置环境变量,可以使用数组或者字典两种格式

只给定名称的变量会自动获取compose主机上对应的变量值,可以用来防止泄漏不必要的数据

如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

仅可以指定内部端口为参数

command

覆盖容器启动后默认执行的命令。

六、Portainer

Docker可视化工具

方便管理单机和集群环境