• Docker 面试题2则--取数据库连接数和docker-compose


    Docker 面试题2则

    1. 题目

    早上接到群里小伙伴求助面试题,据说20K以上.面试题如下

    题⽬1:编写Dockerfile 编写 Dockerfile ,构建⼀个Docker镜像(不能包含 MySQL 服务端程序),完成以下需求:
         镜像中包含⼀个 shell 脚本,容器启动后每隔 30s 收集 MySQL 数据库当前的连接数,将数据同时输出⾄ /data/log ⽂件(⽇志可以持久化保存)及标准输出中
         数据库IP、端⼝、⽤户及密码可以在容器启动时通过 -e 指定环境变量来修改
         要求容器启动后可以使⽤ docker logs container_name 和 docker exec -i -t container_name tail -f /data/log 两种⽅式查看⽇志信息
      每次输出的信息格式如下 [2019-01-01 00:00:00] Number of active DB connections is 10. 
    题⽬2:编写Docker-compose 编写 docker-compose.yml 脚本,使⽤题⽬1中构建的镜像及 MySQL 镜像启动服务
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 解题过程

    看到他的题,第一反应是考的分层打镜像,然后二进制安装mysql,最后再用docker-compose实现数据库启动.群里其他小伙伴也是这个反应.
    仔细读了几遍题目后才发现并不是这样.我们来梳理下要求.

    1. 通过Dockerfile构建一个镜像,镜像中包含一个shell脚本,脚本的作用是每隔30秒取一下Mysql数据库连接数
    2. 将脚本取到的记过写入/data/log
    3. 数据库的IP,端口,用户及密码通过docker -e的方式传入容器,这部分参数是可以修改的
    4. 容器可以用docker exec -i -t container_name tail -f /data/log 查看日志
    5. 容器可以用docker logs -f container_name查看日志
    6. 日志格式为:[2019-01-01 00:00:00] Number of active DB connections is 10.
    7. 用docker-compose实现启动一个mysql,并用题1的容器监控这个mysql的连接数

    3. 破题

    3.1 查询数据库连接的脚本

    我们先启动一个数据库容器

    docker pull mysql:5.6.38
    docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:5.6.38
    
    • 1
    • 2

    尝试连接下数据库

    root@k8s-master-01:/opt/k8s-data/dockerfile/mysql# mysql -uroot -proot123 -h192.168.31.201 -P3306 -e "show databases;"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    +--------------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    获取下数据库的连接数

    root@k8s-master-01:/opt/k8s-data/dockerfile/mysql# mysql -uroot -proot123 -h192.168.31.201 -P3306 -e "show status like 'Threads_connected';"
    mysql: [Warning] Using a password on the command line interface can be insecure.
    +------------------+-------+
    | Variable_name     | Value |
    +-------------------+-------+
    | Threads_connected | 1     |
    +-------------------+-------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以看到值取到了.那么我们把这个值交给一个变量即可

    root@k8s-master-01:/opt/k8s-data/dockerfile/mysql# a=`mysql -uroot -proot123 -h192.168.31.201 -P3306 -e "show status like 'Threads_running';"|grep Threads_connected|awk '{print $2}'`
    mysql: [Warning] Using a password on the command line interface can be insecure.
    root@k8s-master-01:/opt/k8s-data/dockerfile/mysql# echo $a
    1
    
    • 1
    • 2
    • 3
    • 4

    3.2 将值写入/data/log

    这个很简单,分两步

    1. 脚本内
    count=``mysql -uroot -proot123 -h192.168.31.201 -P3306 -e "show status like 'Threads_connected';"|grep Threads_running|awk '{print $2}'`
    echo $count >>/data/log
    
    2. 启动容器的时候
    ```bash
    docker run -d -v /data:/data docker-image
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.3 将参数传递给脚本

    通过$1 $2 $3的位置参数将值传递给脚本

    #!/bin/bash
    DO=1
    while [ "$DO" -gt 0 ] ;do
    MYSQL_IP=$1
    MYSQL_PORT=$2
    MYSQL_PASSWD=$3
    count=`mysql -uroot -p${MYSQL_PASSWD}  -h${MYSQL_IP} -P${MYSQL_PORT} -e 'show status'|grep Threads_connected|awk '{print $2}'`
    echo " $count." >> /data/log
    sleep 30
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.4 将参数传递给容器

    通过-e将参数传递给容器,此时在容器中可以打印出传递进来参数的值

    docker run -d -e MYSQL_IP="192.168.31.201" -e MYSQL_PORT="3306" -e MYSQL_PASSWD="root123" -v /data:/data container-image
    
    • 1

    3.5 通过docker logs显示日志

    在脚本中添加一行

    echo $count >> /dev/stdout
    
    • 1

    3.6 日志输出格式修改

    修改后的count.sh

    #!/bin/bash
    DO=1
    while [ "$DO" -gt 0 ] ;do
    MYSQL_IP=$MYSQL_IP
    MYSQL_PORT=$MYSQL_PORT
    MYSQL_PASSWD=$MYSQL_PASSWD
    MYSQL_USER=$MYSQL_USER
    TIME=`date +"%Y-%m-%d %H:%M:%S"`
    count=`mysql -u${MYSQL_USER} -p${MYSQL_PASSWD}  -h${MYSQL_IP} -P${MYSQL_PORT} -e 'show status'|grep Threads_connected|awk '{print $2}'`
    echo "[${TIME}] Number of active DB connections is $count." >> /data/log
    echo "[${TIME}] Number of active DB connections is $count." >> /dev/stdout
    sleep 30
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Dockerfile

    FROM centos:7.9.2009 
    RUN rm -f /etc/yum.repos.d/*
    ADD mysql-community-client-5.7.31-1.el7.x86_64.rpm /root
    ADD mysql-community-common-5.7.31-1.el7.x86_64.rpm /root
    ADD mysql-community-libs-5.7.31-1.el7.x86_64.rpm /root
    ADD Centos-7.repo /etc/yum.repos.d/
    ADD count.sh /root/
    RUN yum install /root/mysql-community-*.rpm -y
    ENV MYSQL_USER "root"
    ENV MYSQL_IP ""
    ENV MYSQL_PORT "3306"
    ENV MYSQL_PASSWD ""
    ENTRYPOINT ["/root/count.sh"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    build.sh

    #!/bin/bash
    Version=$1
    docker build -t harbor.intra.com/baseimages/mysql-threads:v${Version} .
    
    docker push harbor.intra.com/baseimages/mysql-threads:v${Version}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.7 docker-compose

    version: '3'
    services:
      mysql:
        image: mysql:5.6.38
        restart: always
        ports:
          - 3306:3306
        environment:
          MYSQL_ROOT_PASSWORD: root123
      mysql-threads:
        image: harbor.intra.com/baseimages/mysql-threads:v12
        build:
          context: .
          dockerfile: Dockerfile
        restart: always
        environment:
          MYSQL_IP: "192.168.31.104"
          MYSQL_PORT: "3306"
          MYSQL_PASSWD: "root123"
        volumes:
          - /data:/data 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    最后的效果
    请添加图片描述

  • 相关阅读:
    MyBatis开荒
    C语言入门(七)while和do-while循环
    【计算机网络】
    【无标题】
    8、JdbcTemplate
    深入探索JavaScript中的5种经典算法
    驱动开发:内核远程堆分配与销毁
    书生浦语训练营第2期-第4节笔记
    人工智能-深度学习之残差网络(ResNet)
    蓝桥杯每日一题20223.9.26
  • 原文地址:https://blog.csdn.net/qq_29974229/article/details/126247316