前言:

docker目前已经在实际的生产活动中应用非常广泛了,但在生产方面,我们使用docker需要考虑的地方就需要比测试更多了,比如,时区问题,CPU亲和度问题,服务依赖关系问题,网络配置和管理问题,数据持久化问题,日志管理问题。

以上问题产生的根本原因是由于docker自身的架构和设计所产生的。

比如,时区问题,是由于我们使用的镜像基本都是由国外的docker官方网站所制作的,当然了,基础镜像也就会使用国外的时区啦,而我们要在本地使用,需要进行适当的本地化改造,将时区统一到东八区啦docker中如果对时区不加限制,默认会采用格林尼治时间(GMT),这给日常程序部署、日志查看、错误调试等带来了诸多麻烦与困扰。每次都需要将event发生的显示时间+8个时区,手工换算成北京时间,想想都令人抓狂。

CPU亲和度问题和内存限制问题,是由于docker设计的时候就是可以无限抢占宿主机资源,如果容器内的服务疯狂抢占宿主机资源,将会导致宿主机出现一系列问题。

如果生产中使用docker部署项目,或者某个集群,那么,一般是有启动的先后顺序,也就是容器的启动先后顺序是有规定的,比如,WordPress这种项目就必须先启动数据库,在启动WordPress服务,由此,我们势必需要根据各个服务的依赖关系编排docker容器

并且docker设计之初对于网络的配置和管理是十分弱的,并定义了容器之间默认是相互隔离的,因此,我们需要对原有的默认的网络根据自己的需求进行改造。

服务并不是一成不变的,我们也有升级服务的需求,改变服务的需求,这些需要docker的持久化支持,也就是volume数据外接挂载。

docker默认是不会对日志做任何限制的,因此,我们需要对日志的大小做一定的限制,防止日志过大撑爆宿主机。



实验目的

贴近实战,使用一个MySQL的docker镜像,通过docker-compose对其进行编排,关于时区问题,数据持久化问题,日志问题详细介绍。

实验环境

vm虚拟机,虚拟机配置如下:

8G内存,8CPU,硬盘大小为100G。操作系统为centos7.7.1908

实验步骤

一,docker环境搭建

docker环境搭建没什么好说的,请看我的博客:docker的离线安装以及本地化配置_zsk_john的博客-CSDN博客

docker的版本是:

[root@hdp-1 ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.5
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        55c4c88
 Built:             Tue Mar  2 20:14:11 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.5
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       363e9a8
  Built:            Tue Mar  2 20:18:31 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

docker-compose的版本是:

[root@hdp-1 ~]# docker-compose -verison
docker-compose version 1.25.1, build a82fef07

二,MySQL的镜像文件

链接:https://pan.baidu.com/s/1xWhp4r7Sy4UgLk0ep45k7w 
提取码:mysq 

MySQL的版本为5.7.22 ,这里需要注意,该镜像的基础镜像是由debian操作系统制作的!!!!!!!!!一定要清楚这一点!!!

三,镜像文件导入docker环境内

将上述镜像文件放入虚拟机内,执行以下命令:

docker load < mysql-Docker.tar 
cdb3f9544e4c: Loading layer [==================================================>]  58.44MB/58.44MB
6f8d38b0e2b6: Loading layer [==================================================>]  338.4kB/338.4kB
aae63f31dee9: Loading layer [==================================================>]  10.43MB/10.43MB
4801a487d51a: Loading layer [==================================================>]  4.471MB/4.471MB
c0c26734fb83: Loading layer [==================================================>]  1.536kB/1.536kB
94f8d8f5acbf: Loading layer [==================================================>]  46.11MB/46.11MB
8aeebb3964c1: Loading layer [==================================================>]  28.16kB/28.16kB
22b402e93939: Loading layer [==================================================>]  3.584kB/3.584kB
489bddb9c55e: Loading layer [==================================================>]  257.2MB/257.2MB
f8cb294d5d80: Loading layer [==================================================>]  9.728kB/9.728kB
a968f24d4187: Loading layer [==================================================>]  1.536kB/1.536kB
Loaded image: mysql:5.7.22

执行查看镜像命令,应该有如下输出:

[root@hdp-1 ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
mysql        5.7.22    6bb891430fb6   3 years ago   372MB

四,编写docker-compose 的编排文件,文件可放在任意位置,文件名也任意,但后缀必须是yaml或者yml。文件内容如下(本文定义文件名为MySQL.yaml):

version: '3'

services:
  mysql:
    container_name: mysql-5.7.22
    image: mysql:5.7.22
    restart: always
    environment:
      MYSQL_USER: admin
      MYSQL_PASSWORD: admins
      MYSQL_DATABASE: database
      MYSQL_ROOT_PASSWORD: admin
      TZ: Asia/Shanghai
    volumes:
      - /usr/local/mysql/data:/var/lib/mysql
    ports:
      - 3306:3306
    network_mode: host

那么,这个yaml文件里写的都是什么意思呢?

(1)version这里申明docker服务的大体版本,我使用的版本是docker-ce-20.10.5版本,因此,这里version的值至少应该是3,取值范围是3到3.7,如果修改成3.8,那么结果是这样的:

[root@hdp-1 ~]# docker-compose -f mysql.yaml stop mysql
ERROR: Version in "./mysql.yaml" is unsupported. You might be seeing this error because you're using the wrong Compose file version. Either specify a supported version (e.g "2.2" or "3.3") and place your service definitions under the `services` key, or omit the `version` key and place your service definitions at the root of the file to use version 1.
For more on the Compose file format versions, see https://docs.docker.com/compose/compose-file/

(2) container_name

此行定义容器的名称,写在这个文件里的好处显而易见,便于管理。容器的各类操作都和名称是密切相关的。

(3)environment 容器的环境变量

这里就有点意思了,首先,有一个问题 ,这里定义了一个MySQL用户,和该用户的密码,以及该用户的数据库名称,那么,可否定义多个用户,多个数据库名称呢?

经我测试,答案是不可以定义多个用户和密码。那么,如果想要MySQL多个用户怎么办?

volume挂载/docker-entrypoint-initdb.d/这个目录,然后在宿主机放入初始化用户的SQL脚本,例如在/usr/local//mysql/init这个目录下编辑文件 init.sql文件,文件内容如下这样

CREATE USER 'myuser'@'%' IDENTIFIED BY 'myuser';
GRANT All privileges ON *.* TO 'myuser'@'%';
flush privileges;

这个SQL脚本将会建立一个名字叫myuser的用户,并建立一个数据库,数据库名称为myuser,该用户可远程到此数据库上。

例如:

version: '3'
services:
  mysql:
    container_name: mysql
    image: mysql:5.7.22
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "1g"
    environment:
      - "MYSQL_USER=huiqing"
      - "MYSQL_PASSWORD=Huiqing^*^O3799"
      - "MYSQL_ROOT_PASSWORD=R349_&^#@e]"
      - "TZ=Asia/Shanghai"
    volumes:
      - /data/soft/software/mysql/data:/var/lib/mysql
      - /data/soft/software/mysql/conf/:/etc/mysql/conf.d
      - /data/soft/software/mysql/source:/docker-entrypoint-initdb.d
    ports:
      - 42706:3306

 此时,进入容器内,登录MySQL,两个root密码只有最后一个密码可登录。

[root@hdp-1 ~]# docker exec -it 1e292 /bin/bash
root@hdp-1:/# mysql -uroot -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uroot -padmins123
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uroot -padmins   
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uroot -padmins
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uroot -padmins123
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uzsk -pzsk1      
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'zsk'@'localhost' (using password: YES)
root@hdp-1:/# mysql -uzsk -p    
Enter password: 
ERROR 1045 (28000): Access denied for user 'zsk'@'localhost' (using password: YES)

然后执行:

docker-compose -f  MySQL.yaml down

docker-compose -f  MySQL.yaml up -d

让SQL脚本执行一次,就有新用户myuser了。

(4)数据映射 volume

数据库这样的服务是有数据的流动的,也就是数据流入流出,其实这样的服务并不太适合docker,但自从有了数据挂载映射volume,这些都不是太大的问题了,像本例中使用的yaml文件中的挂载,因为我们是使用的自定义式的覆盖挂载模式,也就是宿主机这边这个目录是空的,而容器端的目录也是空的,因此,不会出现覆盖现象。那么,我们每一次重启容器就会重新映射一次数据,从而保证数据的一致性。

详细介绍可参加本人博客docker 的数据卷挂载volume(持久化)及其意义(三种方式--volume,自定义volume,volume继承)_zsk_john的博客-CSDN博客_docker mysql volumes

(5)网络模式的管理

一般的情况下,我们使用默认的docker的桥接模式即可满足我们的需求,但,如果对容器间的通信有需求,这个时候就需要我们自定义网络啦。

docker-compose网络配置_chen_jianjian的专栏-CSDN博客这个博客写的还是不错的,由于网络管理是一个比较复杂庞大的内容,再次就不过多讨论了。

(6)日志管理问题

日志管理我在前面的博客内也写了很多,考虑再三,也就不重复前面的话了,可以看本人的博客:  docker的日志管理工作和时区本地化设置(docker日志过大,造成磁盘空间被占满的两种处理方法,以及时区的准确设置)_zsk_john的博客-CSDN博客 这里有详细的介绍

五,一个可用的贴近实战的docker启动MySQL正确的示例

version: '3'
services:
  mysql:
    container_name: mysql
    image: mysql:5.7.22
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "1g"
    environment:
      - "MYSQL_USER=huiqing"
      - "MYSQL_PASSWORD=Huiqing^*^O3799"
      - "MYSQL_ROOT_PASSWORD=R349_&^#@e]"
      - "TZ=Asia/Shanghai"
    volumes:
      - /data/soft/software/mysql/data:/var/lib/mysql
      - /data/soft/software/mysql/conf/:/etc/mysql/conf.d
      - /data/soft/software/mysql/source:/docker-entrypoint-initdb.d
    ports:
      - 42706:3306

这个编排文件表示启动一个MySQL5.7.22版本,配置文件映射到 /usr/local/mysql/conf/目录下,时区为中国上海,容器开放端口为3306,宿主机开放的端口为42706,日志限制在最大2G。日志驱动模式是json-file,也就是说如果使用docker logs mysql-lable 这个命令查看容器的日志,输出格式会为json格式。

那么以上的编排文件又会出现新问题了,这个docker容器所开放的端口是3306,如何更改成自定义的端口呢?

这就简单了,编写my.cnf 文件,文件内容如下:

[client]
port=3306
socket=/var/lib/mysql/mysql.sock
[mysqldump]
quick
max_allowed_packet = 16M
[mysqld]
bind-address = 0.0.0.0
#basedir = /var/lib/mysql
#datadir = /var/lib/mysql
port=3307
server-id = 1
socket=/var/lib/mysql/mysql.sock
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character_sets_dir=/var/lib/mysql/mysql/charsets
init_connect='SET NAMES utf8mb4'
default-storage-engine=INNODB
default_authentication_plugin=mysql_native_password
skip-character-set-client-handshake = true
lower_case_table_names = 1
key_buffer_size=16M
max_allowed_packet=16M
sql_mode=TRADITIONAL
slow_query_log=on
slow-query-log-file=/var/lib/mysql/slow.log
long_query_time=1
log-bin=my-binlog-name
binlog_format=MIXED
[mysql]
default-character-set=utf8mb4

将此文件cp到/data/soft/software/mysql/conf目录下,重启容器即可自定义端口为3307,并且开启了慢查询日志和binlog日志。此时,上面的那个yaml文件也要做相应修改:

version: '3'
services:
  mysql:
    container_name: mysql
    image: mysql:5.7.22
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "1g"
    environment:
      - "MYSQL_USER=huiqing"
      - "MYSQL_PASSWORD=Huiqing^*^O3799"
      - "MYSQL_ROOT_PASSWORD=R349_&^#@e]"
      - "TZ=Asia/Shanghai"
    volumes:
      - /data/soft/software/mysql/data:/var/lib/mysql
      - /data/soft/software/mysql/conf/:/etc/mysql/conf.d
      - /data/soft/software/mysql/source:/docker-entrypoint-initdb.d
    ports:
      - 42706:3307

也就是ports 修改为 - 42706:3307 ,然后在别的机器远程连接的时候填写连接端口为42706即可连接啦。

通过编辑my.cnf 文件即可定制自己想要的MySQL啦。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐