Docker基础(四)——数据持久化&单机集群部署实战

作为Docker学习笔记,数据持久化、部署实战相关,以备后查。 虚拟机地址为实验环境,折腾较多,示例不保证能随时访问。

Docker数据持久化

默认情况下容器内创建的所有文件都存储在可写容器层上。即:

  • 当该容器不再存在时,数据就就会丢失。
  • 容器的可写层与运行容器的主机紧密耦合,无法轻松地将数据移动到其他地方。
  • 写入容器的可写层需要存储驱动程序来管理文件系统。存储驱动程序使用Linux内核提供的union filesystem。与使用直接写入主机文件系统的数据卷相比,这种额外的抽象降低了性能。

Docker为容器提供了两种方式来将文件存储在主机中:volumesbind mounts,这样即使容器停止后文件也可以保存。如果在Linux上运行Docker,还可以使用tmpfs mount;如果在Windows上运行Docker,则还可以使用named pipe

无论使用哪种方式,在容器的文件系统中都可以看作 关联的目录或单个文件。可以根据数据在Docker主机上的存储位置来理解不同方式之间的差别,如下图所示:

  • Volumes存储在由Docker管理的主机文件系统中的某个位置(在Linux上的目录为/var/lib/docker/volumes/)。非Docker进程不应该修改文件系统的这一部分。Volumes是在Docker中持久化保存数据的最佳方式。
  • Bind mounts可以存储在主机系统的任何位置,甚至可能是重要的系统文件或目录中。Docker主机上的非Docker进程或Docker容器可以随时对其进行修改。
  • tmpfs mount仅存储在主机的内存中,不会写入到主机的文件系统中。

Volumes

  1. 创建mysql容器

    docker run -d --name mysql01 -e MYSQL_ROOT_PASSWORD=cph123 mysql

  2. 列出所有volume

    docker volume ls

    1
    2
    DRIVER              VOLUME NAME
    local 6f97012d2f8521c73a3cb84e0073fe66233bdb26eaae9c25d57f56388ea26d75
  3. 检查指定volume

    docker volume inspect 6f97012d2f8521c73a3cb84e0073fe66233bdb26eaae9c25d57f56388ea26d75

  4. 使用-v参数指定volume名称

    docker run -d --name mysql01 -v mysql01_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=cph123 mysql

  5. 再次查看volume

    docker volume ls

    1
    2
    3
    DRIVER              VOLUME NAME
    local 6f97012d2f8521c73a3cb84e0073fe66233bdb26eaae9c25d57f56388ea26d75
    local mysql01_volume
  6. 检查指定volume

    docker inspect mysql01_volume

持久化测试
  1. 进入容器中 docker exec -it mysql01 bash

  2. 登录mysql mysql -uroot -pcph123

  3. 创建测试库 create database db_test;

  4. 退出mysql、container

  5. 删除mysql容器 docker rm -f mysql01

  6. 查看volume docker volume ls

    1
    2
    3
    DRIVER              VOLUME NAME
    local 6f97012d2f8521c73a3cb84e0073fe66233bdb26eaae9c25d57f56388ea26d75
    local mysql01_volume
  7. 新建mysql container,指定使用mysql01_volume

    docker run -d --name test-mysql -v mysql01_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=cph123 mysql

  8. 进入容器中,登录mysql服务器,查看数据库,可以看到db_test仍然存在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    +--------------------+
    | Database |
    +--------------------+
    | db_test |
    | information_schema |
    | mysql |
    | performance_schema |
    | sys |
    +--------------------+

Bind mounts

  1. 创建tomcat容器

    docker run -d --name tomcat01 -p 9090:8080 -v /tmp/test:/usr/local/tomcat/webapps/test tomcat

  2. 查看对应目录

    • centos7:/tmp/test

    • tomcat01容器:/usr/local/webapps/test

  3. 在centos的/tmp/test/目录下新建a.html

    1
    <p style="color:red; font-size=40pt;">Bind mounts test</p>
  4. 进入tomcat容器对应目录下发现存在相同内容的a.html

单机集群部署实战

搭建MySQL高可用集群

模拟集群环境示例:

  1. 拉取镜像

    docker pull percona/percona-xtradb-cluster:5.7.21

  2. 重命名镜像(方便操作)

    docker tag percona/percona-xtradb-cluster:5.7.21 pxc

  3. 创建单独网段供mysql集群使用

    • 创建 docker network create --subnet=172.18.0.0/24 pxc-net

    • 查看网段详情 docker network inspect pxc-net

    • 删除网段 docker network rm pxc-net

  4. 创建和删除volume(提前创建v1、v2、v3以备后续使用)

    • 创建 docker volume create --name v1

    • 查看详情 docker volume inspect v1

    • 删除 docker volume inspect v1

搭建pxc[mysql]集群
  1. 创建node1

    1
    docker run -d -p 3306:3306 -v v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=cph123 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=cph123 --privileged --name=node1 --net=pxc-net --ip 172.18.0.2 pxc
    • -e CLUSTER_NAME=PXC 指定PXC集群名字
    • -e XTRABACKUP_PASSWORD=cph123 指定数据库同步密码
    • --privileged 设置优先级
  2. 创建node2

    1
    docker run -d -p 3302:3306 -v v2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=cph123 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=cph123 -e CLUSTER_JOIN=node1 --privileged --name=node2 --net=pxc-net --ip 172.18.0.3 pxc
    • -e CLUSTER_JOIN=node1 将该数据库加入到节点node1上组成集群
  3. 创建node3

    1
    docker run -d -p 3303:3306 -v v3:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=cph123 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=cph123 -e CLUSTER_JOIN=node1 --privileged --name=node3 --net=pxc-net --ip 172.18.0.4 pxc
数据库负载均衡
  1. 拉取haproxy镜像

    docker pull haproxy

  2. 创建haproxy配置文件(使用bind mounts方式)

    touch /tmp/haproxy/haproxy.cfg

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    global
    #工作目录,这边要和创建容器指定的目录对应
    chroot /usr/local/etc/haproxy
    #日志文件
    log 127.0.0.1 local5 info
    #守护进程运行
    daemon
    defaults
    log global
    mode http
    #日志格式
    option httplog
    #日志中不记录负载均衡的心跳检测记录
    option dontlognull
    #连接超时(毫秒)
    timeout connect 5000
    #客户端超时(毫秒)
    timeout client 50000
    #服务器超时(毫秒)
    timeout server 50000
    #监控界面
    listen admin_stats
    #监控界面的访问的IP和端口
    bind 0.0.0.0:8888
    #访问协议
    mode http
    #URI相对地址
    stats uri /dbs_monitor
    #统计报告格式
    stats realm Global\ statistics
    #登陆帐户信息
    stats auth admin:admin
    #数据库负载均衡
    listen proxy-mysql
    #访问的IP和端口,haproxy开发的端口为3306
    #假如有人访问haproxy的3306端口,则将请求转发给下面的数据库实例
    bind 0.0.0.0:3306
    #网络协议
    mode tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source
    balance roundrobin
    #日志格式
    option tcplog
    #在MySQL中创建一个没有权限的haproxy用户,密码为空。
    #Haproxy使用这个账户对MySQL数据库心跳检测
    option mysql-check user haproxy
    server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
    server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
    server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option tcpka
  3. 创建haproxy镜像

    1
    docker run -it -d -p 8888:8888 -p 3307:3306 -v /tmp/haproxy:/usr/local/etc/haproxy --name haproxy01 --privileged --net=pxc-net haproxy
    • 创建node1时占用了3306端口,此处对外提供3307端口
  4. 使用指定的配置文件启动haproxy

    • docker exec -it haproxy01 bash
    • haproxy -f /usr/local/etc/haproxy/haproxy.cfg
  5. MySQL数据库中创建haproxy用户,用于心跳检测

    • CREATE USER 'haproxy'@'%' IDENTIFIED BY '';

    • 如果创建用户失败,执行以下命令

      1
      2
      3
      drop user 'haproxy'@'%';
      flush privileges;
      CREATE USER 'haproxy'@'%' IDENTIFIED BY '';
  6. windows中浏览器访问监控界面: http://45.32.103.56:8888/dbs_monitor ,默认用户名/密码:admin/admin

  7. windows中通过haproxy连接数据库集群,进行数据操作可验证集群同步情况^_^

搭建Nginx+Spring Boot+MySQL环境

模拟集群环境示例:

搭建MySQL
  1. 创建volume

    docker volume create v1_pro

  2. 创建mysql容器

    docker run -d --name my-mysql -v v1_pro:/var/lib/mysql -p 3301:3306 -e MYSQL_ROOT_PASWORD=cph123 --net=pro-net --ip 172.19.0.6 mysql

  3. 使用DataGrip连接数据库,执行以下语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    create schema db_springboot collate utf8mb4_0900_ai_ci;
    use db_springboot;
    create table t_user
    (
    id int not null
    primary key,
    username varchar(50) not null,
    password varchar(50) not null,
    number varchar(100) not null
    );
搭建Spring Boot项目
  1. 基于Spring Boot+MyBatis实现CRUD操作,项目名称为“springboot-mybatis”

  2. 项目根目录下执行 mvn clean package打出jar包并上传至docker环境中

  3. 创建Dockerfile

    1
    2
    3
    4
    5
    FROM openjdk:8-jre-alpine
    MAINTAINER cph
    LABEL name="springboot-mybatis" version="1.0" author="cph"
    COPY springboot-mybatis-0.0.1-SNAPSHOT.jar springboot-mybatis.jar
    CMD ["java","-jar","springboot-mybatis.jar"]
  4. 基于Dockerfile构建镜像 docker build -t sbm-image .

  5. 创建java应用的Container docker run -d --name sbc1 -p 8081:8080 --net=pro-net --ip 172.19.0.11 sbm-image

  6. 查看启动日志 docker logs sbc1

  7. 在windows浏览器中访问: http://45.32.103.56:8081/user/listall

  8. 继续创建多个java应用的Container

    1
    2
    docker run -d --name sbc2 -p 8082:8080 --net=pro-net --ip 172.19.0.12 sbm-image
    docker run -d --name sbc3 -p 8083:8080 --net=pro-net --ip 172.19.0.13 sbm-image
搭建Nginx
  1. 在centos的/tmp/nginx/目录下新建nginx.conf,进行相应配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    user nginx;
    worker_processes 1;
    events {
    worker_connections 1024;
    }
    http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;

    server {
    listen 80;
    location / {
    proxy_pass http://balance;
    }
    }

    upstream balance{
    server 172.19.0.11:8080;
    server 172.19.0.12:8080;
    server 172.19.0.13:8080;
    }
    include /etc/nginx/conf.d/*.conf;
    }
  2. 创建nginx容器

    docker run -d --name my-nginx -p 80:80 -v /tmp/nginx/nginx.conf:/etc/nginx/nginx.conf --network=pro-net --ip 172.19.0.10 nginx

  3. 在windows浏览器中访问 http://45.32.103.56/user/listall ,能看到返回数据表示集群搭建成功^_^