分类: Docker

Dockerfile的基础学习

DockerFile

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

https://docs.docker.com/reference/dockerfile/

构建三步骤

  • 1、编写Dockerfile文件
  • 2、docker build 命令构建镜像
  • 3、docker run 依照新生成的镜像运行容器实例

Dockerfile基础知识

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

Docker执行Dockerfile的大致流程

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

从应用软件的角度来看Dockerfile Docker镜像与Docker容器分别代表软件的三个不同阶段,Dockerfile是软件的原材料,Docker镜像是软件的交付品,Docker容器则可以认为是软件镜像的运行状态,即是依照镜像运行的容器实例。

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

1、Dockerfile定义了程序需要的一切东西。包括执行代码或文件,环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等
2、Docker镜像 在用Dockerfile定义过一个文件后,docker build 时会产生一个Docker镜像,当运行Docker镜像时会真正开始提供服务
3、Docker容器 容器是直接提供服务的。

Dockerfile常用保留字指令

FROM 继承的基础父镜像

RUN 容器构建时需要运行的命令
    两种格式 
      一种是shell格式 
      RUN 命令
      一种是exec格式
      RUN ['./test.php',"参数1","参数2"]
    RUN是在docker build 时运行

EXPOSE 当前容器对外暴露出的端口

WORKDIR 指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点

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

ENV 用来在构建镜像过程中设置环境变量,这个环境变量可以在后续的任何RUN指令中使用,也可以在其他指令中直接使用这些环境变量

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

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

COPY 类似ADD 拷贝文件和目录到镜像中
     将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置
     COPY src dest
     COPY ['src','dest']
     目标路径是容器内的指定路径 该路径不哦那个事先建好

CMD 指定容器启动后要干的事情
    Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
    他跟RUN命令的区别
    CMD是在docker run时运行
    RUN是在docker build时运行

ENTRYPOINT 也是用来指定一个容器启动时要运行的命令
    类似于CMD指令,但是ENTRYPOINT不会被docker run后边的命令覆盖,而且这些命令行参数会被当作参数发送给ENTRYPOINT指令指定的程序
    注意 ENTRYPOINT可以和CMD一起用,一般是变参才会使用CMD 这里的CMD是等于在给 ENTRYPOINT传递参数。当指定了 ENTRYPOINT 后 CMD的含义就发生了变化,不再是直接运行命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令,他们两个组合会变成 <ENTRYPOINT><CMD>
    优点
    案例:
    定义nginx:test镜像
    FROM nginx

    ENTRYPOINT ["nginx","-c"] # 定参
    CMD ["/etc/nginx/nginx.conf"] # 变参
docker run nginx:test docker run nginx:test -c /new.conf
nginx -c /etc/nginx/nginx.conf nginx -c /new.conf

构建

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

Docker的基础学习(三)

容器数据卷

用于完成数据的持久化,重要资料的备份存储,就是主机的目录和容器内的目录进行映射,将容器内的数据备份+持久化到本地主机目录。
坑:容器卷记得加入参数 --privileged=true
Docker挂载主机目录访问如果出现 cannot open directory.:Permission denied
解决办法:在挂载目录后多加一个 --privileged=true 参数即可
why

如果是在CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里边挂在挂载目录被禁止,如果要开启,我们一般使用--privileged=true 命令。扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,容器内的root用户会拥有真正的root权限,否则容器内的root只是外部的一个普通用户的权限。

卷就是目录或文件,存在于一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过UnionFileSystem提供一些用于持续存储或共享数据的特性。

卷的设计目的就是数据持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

Docker容器产生的数据,如果不备份,那么当容器实例删除之后,容器内的数据自然也就没有了。为了能保存数据 所以在docker中我们使用卷。

特点:

  • 1、数据卷可在容器之间共享或者重用数据
  • 2、卷中的更改可以直接实时生效
  • 3、数据卷中的更改不会包含在镜像的更新中
  • 4、数据卷的生命周期一直持续到没有容器使用它为止
docker run -v 本地宿主机路径:容器内部路径 --privileged=true
-v 添加自定义容器卷 可以多个
--privileged=true 放开权限

运行一个带有容器卷存储功能的容器实例
docker run -it --privileged=true -v 本地宿主机绝对路径:容器内部路径 镜像名
docker run -it --name=quan --privileged=true  -v /Users/iuu/Developer/docker/quan/:/home/ 192.168.1.8:5001/iuu_local_ubuntu /bin/bash 
============================
查看数据卷是否挂载成功
docker inspect  quan
输出如下信息
"Mounts": [
            {
                "Type": "bind",
                "Source": "/host_mnt/Users/iuu/Developer/docker/quan",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
============================

读写规则映射添加说明
读写 rw (默认)
docker run -it --privileged=true -v 本地宿主机绝对路径:容器内部路径:rw 镜像名

只读 ro 容器内部被限制只能读取不能写入 宿主机不受影响
docker run -it --privileged=true -v 本地宿主机绝对路径:容器内部路径:ro 镜像名

docker inspect  quan
输出如下信息
"Mounts": [
            {
                "Type": "bind",
                "Source": "/host_mnt/Users/iuu/Developer/docker/quan",
                "Destination": "/home",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],
============================
卷的继承和共享
--volumes-from 容器ID/容器名称 

容器quan3-ext-quan2继承容器quan2的卷 包含挂载目录 和权限都继承quan2的
docker run -it --name=quan3-ext-quan2 --privileged=true --volumes-from quan2   192.168.1.8:5001/iuu_local_ubuntu 

Docker的基础学习(二)

镜像分层概念

镜像是什么?

镜像 是一种轻量级、可执行的独立软件包,他包含运行某个软件所需要的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量、配置文件等),这个打包好的运行环境就是image镜像文件。
只有通过这个镜像文件才能生成Docker容器实例

分层的镜像

镜像就像是一个蛋糕,一层一层堆叠出来的。
以pull命令为例子,在下载的过程中我们可以看到docker的镜像好像是在一层一层的下载。

iuu@iuudeMac-mini ~ % docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
94a23d3cb5be: Downloading [========>                                          ]   9.51MB/53.6MB
ac9d381bd1e9: Download complete 
aa9c5b49b9db: Download complete 
841dd868500b: Downloading [============================>                      ]  31.17MB/54.67MB
42dee876d816: Downloading [========================================>          ]  4.358MB/5.42MB
c4851c976ae9: Waiting 
e80a0433b650: Waiting 
e10afb8c99ce: Waiting 
7870523e466f: Waiting 

UnionFS(联合文件系统)

UnionFS文件系统是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外边来看,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像的加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs(foot file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用HOST的kernel,自己只需要提供rootfs就行了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。

镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。

比如说有多个镜像都从相同的base镜像构建而来,那么Docker Host只需在磁盘上保存一份base镜像;同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而镜像的每一层都可以被共享。

Docker镜像层都是只读的,容器层是可写的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作容器层,容器层之下都叫做镜像层。

制作自己的镜像

docker commit 提交容器副本使之成为一个新的镜像
docker commit -m="备注" -a="作者" 容器ID/容器名 目标镜像名:[标签名 不写则为latest]

基于官方 ubuntu 创建一个容器
docker run -it --name=u02 ubuntu /bin/bash

ubuntu 安装 vim 命令
apt-get update
apt-get -y install vim

将现在的容器生成一个新的镜像
docker commit -m='新增vim命令' -a='iuu' u01 iuu/vim_ubuntu:1.0
docker commit -m='新增vim命令' -a='iuu' u01 vim_ubuntu:1.0
docker commit -m='新增vim命令' -a='iuu' 2d4263116d7f vim_ubuntu:1.0

使用生成的镜像
docker run --name=vim_ubuntu -it vim_ubuntu:1.0 /bin/bash
docker run --name=iuu_vim_ubuntu -it iuu/vim_ubuntu:1.0 /bin/bash

容器发布到阿里云/DockerHub

阿里云

容器镜像服务 创建命名空间 创建仓库

登陆
docker login --username=41760@qq.com registry.cn-hangzhou.aliyuncs.com

TAG
docker tag  镜像ID  registry.cn-hangzhou.aliyuncs.com/iuu_me/vim_ubuntu:[镜像版本号]

推送
docker push registry.cn-hangzhou.aliyuncs.com/iuu_me/vim_ubuntu:[镜像版本号]

拉取
docker pull registry.cn-hangzhou.aliyuncs.com/iuu_me/vim_ubuntu:1.0

DockerHub

登陆网站 创建仓库

命令行登陆
docker login

TAG
docker tag 镜像ID  DockerHub用户名/仓库名:镜像版本号
docker tag 2fad279b3143  jianchaodada/tree_ubuntu:1.0

推送
docker push jianchaodada/tree_ubuntu:1.0

案例 没带版本号 则默认用 latest
docker commit -m='删除无用文件' -a='iuu' aliyun  iuu_ubuntu 
docker tag 2fad279b3143  jianchaodada/iuu_ubuntu 
docker push jianchaodada/iuu_ubuntu  

Docker私有仓库

DockerRegistry是官方提供的工具,可以用于构建私有镜像仓库

下载DockerRegistry镜像
docker pull registry 
运行私服实例
docker run -d -p 5000:5000  --name=DockerRegistry   -v /Users/iuu/Developer/docker/DockerRegistry:/var/lib/registry --privileged=true registry
默认情况下仓库被创建在容器的 /var/lib/registry/ 目录下 建议用容器卷映射,方便与宿主机联调

案例:
在ubuntu镜像中安装ifconfig命令
apt-get update
apt-get install -y net-tools

ifconfig

基于容器生成镜像 上传到dockerhub
docker commit -m='安装ifconfig' -a='iuu' aliyun  iuu_ubuntu 
docker images 
docker tag 5e2a0179f0d8  jianchaodada/iuu_ubuntu
docker push jianchaodada/iuu_ubuntu  

curl验证私服库上有什么镜像
curl -XGET http://127.0.0.1:5001/v2/_catalog

修改配置文件让docker 支持http协议推送 默认不允许http协议推送 修改完重启docker 
修改 daemon.json 在配置加速地址的地方加: 
"insecure-registries":["192.168.1.8:5001"]

基于容器生成镜像 上传到私服
docker commit -m='安装ifconfig' -a='iuu' aliyun  iuu_local_ubuntu
docker tag 0f72c1a675f3 192.168.1.8:5001/iuu_local_ubuntu
docker push 192.168.1.8:5001/iuu_local_ubuntu
curl -XGET http://127.0.0.1:5001/v2/_catalog

拉取私服库里的镜像
docker pull 192.168.1.8:5001/iuu_local_ubuntu 

Docker的基础学习(一)

Docker 的基本组成

镜像 images  
容器 container  基于镜像生成容器
仓库 repository 存储镜像的仓库

可以把容器看作一个简易版的Linux环境和运行在其中的应用程序
仓库分为公开库 和 私有仓库

CentOS7 安装docker

1、检查内核版本 官方建议 3.10 以上
uname -r 
2、卸载旧版本
sudo yum remove docker  docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
3、设置存储库-国内可以设置为阿里云
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
4、更新yum缓存
yum makecache fast
5、安装docker
5.1、安装最新版
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

5.2、安装指定版本
5.2.1 列出存储库中的可用版本
yum list docker-ce --showduplicates | sort -r

5.2.2 安装指定版本的docker
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io docker-buildx-plugin docker-compose-plugin

6、启动 Docker
sudo systemctl start docker

7、运行测试容器
sudo docker run hello-world

8、验证
docker ps -a
docker images -a
docker --help
docker version 
ps -ef |grep docker
docker info

停止 
sudo systemctl stop docker
卸载 
sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras

sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

镜像加速器配置

进入目录
cd /etc/docker/

创建daemon.json文件并写入内容
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"]
}
EOF

重新加载 systemd 管理器配置
sudo systemctl daemon-reload

重启服务
sudo systemctl restart docker

查看信息
docker info

测试 Hello World 镜像

docker run hello-world

当本地没有hello-world镜像时,会自动从远程仓库下载该镜像
当输出hello world提示后,容器就会自动终止
docker run xxx 首先在本机查找镜像,找到则直接生成容器实例运行。 找不到则从云端仓库查找,仓库找到则下载镜像到本地,生成容器实例运行,如果云端仓库查找不到则进行报错。

Docker 为什么会比虚拟机快

有比虚拟机更少的抽象层
利用的是宿主机的内核,而不需要加载操作系统OS内核

帮助启动类命令

启动 systemctl start docker
重启 systemctl restart docker
停止 systemctl stop docker
状态 systemctl status docker
开机启动 systemctl enable docker
查看概要信息 docker info
查看帮助文档 docker --help
查看具体命令帮助 docker 命令 --help

镜像命令

=====================================
本机镜像列表 
docker images  

REPOSITORY 仓库源
TAG        镜像标签版本号
IMAGE ID   镜像ID 
CREATED    镜像创建时间
SIZE       镜像大小

同一个仓库源可以有多个TAG版本,代表这个仓库源的不同个版本,我们使用REPOSITORY:TAG来定义不同的镜像。如果你不置顶一个镜像的版本标签,例如你只使用ubuntu,docker将默认使用ubuntu:latest镜像。

-a 列出本地所有的镜像(含历史映像层)
-q 只显示镜像ID 
=====================================
查找镜像
docker search 

NAME         镜像名称       
DESCRIPTION  镜像说明     
STARS        点赞数量
OFFICIAL     是否官方的
AUTOMATED    是否自动构建的 

--limit 只列出N个镜像 默认25个
docker search --limit 10 php
=====================================
下载镜像

docker pull 镜像名字[:TAG]
docker pull 镜像名字 (默认latest镜像)
=====================================
查看镜像/容器/数据卷/构建缓存所占空间

docker system df

TYPE         类型(镜像/容器/数据卷/构建缓存)
TOTAL        总数
ACTIVE       活动数
SIZE         大小  
RECLAIMABLE  可回收(例如未使用的镜像或停止的容器占用的空间)
=====================================
删除一个或多个镜像
docker rmi <image_id_or_name1> 
docker rmi <image_id_or_name1:TAG> <image_id_or_name2> ...
删除全部镜像
docker rmi -f$(docker images -aq)
如果镜像正在被使用(例如由某个容器),可以使用 -f 选项强制删除:
docker rmi -f <image_id_or_name> 
清理未使用的镜像:
docker image prune
要删除所有未被使用的镜像(不仅仅是悬挂镜像),可以使用 -a 选项:
docker image prune -a

虚悬镜像 仓库名字、标签都是<none>的镜像 建议删掉 

容器命令

=====================================
新建+启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS 有些是一个减号 有些是两个减号
--name="容器名字" 为容器指定名称,不指定则系统随机分配
-d               后台运行容器并返回容器ID
-i               以交互模式运行容器,通常与-t同时使用
-t               为容器重新分配一个伪终端,通常与-i同时使用
-P               随机端口映射 (大写P)
-p               指定端口映射 (小写p)
    本地IP+端口:容器端口   -p 10.1.0.1:8080:80
    本地端口:容器端口      -p 8080:80

举例 启动一个ubuntu容器:
docker run -it ubuntu /bin/bash 
退出ubuntu终端则直接输入 exit
=====================================
列出正在运行的容器
docker ps

CONTAINER ID   容器ID
IMAGE          所属镜像
COMMAND        启动容器时运行的命令
CREATED        容器的创建时间
STATUS         容器的当前状态(Up 2 hours 表示已运行2小时)
PORTS          暴露端口
NAMES          容器名字 

-a或--all:显示所有容器(默认只显示正在运行的容器)。
-f或--filter filter:根据提供的条件过滤输出。
--format string:使用自定义模板格式化输出:
    'table':以表格格式打印输出并带有列标题(默认)。
    'table TEMPLATE':使用指定的 Go 模板以表格格式打印输出。
    'json':以 JSON 格式打印输出。
    'TEMPLATE':使用指定的 Go 模板打印输出。
    更多信息请参考 Docker 文档 中关于格式化输出的部分。
-n或--last int:显示最后创建的n个容器(包括所有状态,默认为 -1)。
-l或--latest:显示最新创建的容器(包括所有状态)。
--no-trunc:不截断输出。
-q或--quiet:只显示容器 ID。
-s或--size:显示总文件大小。
=====================================
退出容器

run进去容器 exit退出 容器停止
run进去容器 ctrl+p+q退出 容器不停止 
=====================================
启动已经停止的容器
docker start 容器ID/容器名称
=====================================
重启容器
docker restart 容器ID/容器名称
=====================================
停止容器
docker stop 容器ID/容器名称
=====================================
强制停止容器
docker kill 容器ID/容器名称
=====================================
删除已停止的容器
docker rm 容器ID/容器名称
强制删除容器
docker rm -f 容器ID/容器名称 
一次性删除全部容器实例 (包含启动中的)
docker rm -f$(docker ps -a -q)
docker ps -a -q | xargs docker rm -f
=====================================
前台交互式启动
docker run -it  redis:alpine3.20
后台守护式启动
docker run -d  redis:alpine3.20
查看容器启动日志
docker logs 容器ID/容器名称
查看容器内运行的进程
docker top  容器ID/容器名称

查看容器内部细节(容器作为最小化linux系统的一些系统配置信息)
docker inspect 容器ID/容器名称
=====================================
进入正在运行的容器并以命令行交互
docker exec -it 容器ID/容器名 bashShell
例如 
docker exec -it my_u01 /bin/bash 

重新进入
docker attach 容器ID/容器名

attach 直接进入容器启动命令的终端,不会启动新的进程,用exit退出,会导致容器停止
exec 是在容器中打开新的终端,并且可以启动新的进程,用exit退出,不会导致容器的停止

推荐使用docker exec 命令,因为退出容器终端,不会导致容器的停止
一般用-d后台启动的容器 用exec进入对应的容器实例干活

=====================================
从容器内拷贝文件到主机上
docker cp 容器ID/容器名:容器内路径 目标主机路径(本地路径)
docker cp my_u02:/1.txt /Users/iuu/22.txt
=====================================
导入和导出容器

export 导出容器的内容留作为一个tar归档文件
docker export 容器ID/容器名 > 文件名.tar
docker export my_u02 > /Users/iuu/my_u02.tar 

import 从tar包中的内容创建一个新的文件系统再导入为镜像

cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
cat /Users/iuu/my_u02.tar |docker import - iuu/my_u02:1.0

利用导入的镜像生成容器
docker run --name=my_u02  -it iuu/my_u02:1.0  /bin/bash
=====================================

基于Docker 实现MySql的主从复制

1、新建主服务容器实例3310
================================
docker run -d -p 3310:3306 --name mysql-master \
-v /Users/iuu/Developer/docker/mysql/master/log:/var/log/mysql \
-v /Users/iuu/Developer/docker/mysql/master/data:/var/lib/mysql \
-v /Users/iuu/Developer/docker/mysql/master/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=root \
-e LANG="C.UTF-8" \
mysql:latest 
================================
2、新建my.cnf
================================
[mysqld]
# 设置server_id 同一局域网中要唯一
server_id=101

# 无需开启二进制日志文件的数据库
# 多个数据库则要重复设置
binlog-ignore-db=mysql

# 打开二进制日志功能.
# 在复制(replication)配置中,作为MASTER主服务器必须打开此项
# 如果你需要从你最后的备份中做基于时间点的恢复,你也同样需要二进制日志.
log-bin=mall-mysql-bin 

# 在一个事务中binlog为了记录SQL状态所持有的cache大小
# 如果你经常使用大的,多声明的事务,你可以增加此值来获取更大的性能.
# 所有从事务来的状态都将被缓冲在binlog缓冲中然后在提交后一次性写入到binlog中
# 如果事务比此值大, 会使用磁盘上的临时文件来替代.
# 此缓冲在每个连接的事务第一次更新状态时被创建
binlog_cache_size=10M

# binlog日志格式
# mysql默认采用statement,建议使用mixed
binlog_format=mixed

# 超过指定天数的binlog将被删除
# 二进制日志过期时间设置为7天(7天 = 7 * 24 * 60 * 60 秒)
binlog_expire_logs_seconds = 604800

# 主从复制跳过错误
# 1062 指一些主键重复
# 1032 主从数据库数据不一致
# 跳过指定error no类型的错误
# slave-skip-errors=1062,1053,1146 
# 跳过所有错误
# slave-skip-errors=all 
slave-skip-errors=1062
================================
3、修改完配置后重启 master 实例
================================
docker restart mysql-master
================================
4、进入master容器
================================
docker exec -it mysql-master /bin/bash
mysql -uroot -p
show databeses;
================================
5、master 容器实例内创建数据同步用户
================================
创建用户
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
授权
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
================================
6、新建从服务器实例 3311
================================
docker run -d -p 3311:3306 --name mysql-slave \
-v /Users/iuu/Developer/docker/mysql/slave/log:/var/log/mysql \
-v /Users/iuu/Developer/docker/mysql/slave/data:/var/lib/mysql \
-v /Users/iuu/Developer/docker/mysql/slave/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=root \
-e LANG="C.UTF-8" \
mysql:latest 
================================
7、新建my.cnf
================================
[mysqld]
# 设置server_id 同一局域网中要唯一
server_id=102

# 无需开启二进制日志文件的数据库
# 多个数据库则要重复设置
binlog-ignore-db=mysql

# 打开二进制日志功能.
# 在复制(replication)配置中,作为MASTER主服务器必须打开此项
# 如果你需要从你最后的备份中做基于时间点的恢复,你也同样需要二进制日志.
log-bin=mall-mysql-slave1-bin 

# 在一个事务中binlog为了记录SQL状态所持有的cache大小
# 如果你经常使用大的,多声明的事务,你可以增加此值来获取更大的性能.
# 所有从事务来的状态都将被缓冲在binlog缓冲中然后在提交后一次性写入到binlog中
# 如果事务比此值大, 会使用磁盘上的临时文件来替代.
# 此缓冲在每个连接的事务第一次更新状态时被创建
binlog_cache_size=10M

# binlog日志格式
# mysql默认采用statement,建议使用mixed
binlog_format=mixed

# 超过指定天数的binlog将被删除
# 二进制日志过期时间设置为7天(7天 = 7 * 24 * 60 * 60 秒)
binlog_expire_logs_seconds = 604800

# 主从复制跳过错误
# 1062 指一些主键重复
# 1032 主从数据库数据不一致
# 跳过指定error no类型的错误
# slave-skip-errors=1062,1053,1146 
# 跳过所有错误
# slave-skip-errors=all 
slave-skip-errors=1062

# 配置中继日志
relay_log=mall-mysql-relay-bin

# 启用从库记录复制操作到自己的二进制日志
log_slave_updates = ON

# 限制一个 MySQL 实例的读写操作。
# 0 允许读写操作(默认行为)
# 当设置为 1 时,表示只允许读操作,而写操作会被拒绝
read_only=1
================================
8、修改完配置后重启 slave 实例
================================
docker restart mysql-slave
================================
9、在主数据库中查看主从同步状态
================================
show master status;
================================
10、进入 slave 服务器
================================
docker exec -it mysql-slave /bin/bash
mysql -uroot -p
show databeses;
================================
11、在从数据库中配置主从复制
================================
change master to 
master_host='192.168.1.8',
master_user='slave',
master_password='123456',
master_port=3310,
master_log_file='mall-mysql-bin.000002',
master_log_pos=712,
master_connect_retry=30;
================================
12、在从数据库中查看主从同步状态
================================
show slave status \G;
show slave status;
看这两个参数
Slave_IO_Running: No
Slave_SQL_Running: No
================================
13、在从数据库中开启主从同步
================================
start slave;
================================
14、查看从数据库状态发现已经同步
================================
show slave status \G;
================================
15、主从复制测试
================================
主机新建库
create database db01;
主机新建表
use db01;
create table t1 (id int, name varchar(20));
主机插入数据
insert into t1 values(1,'张三');
主机查看数据
select * form t1;
从机查看数据
select * form t1;
================================
1 2