Docker 进阶
Docker 进阶
容器数据卷
1、什么是容器数据卷
解释
Docker是将运行环境和服务打包成一个镜像运行,我们知道容器一旦停止运行或者被销毁,容器中运行时所产生的文件就会消失。如果数据在容器中,有人不小心把容器停掉了或删掉了,数据就会丢,假如你使用了MySQL容器,然后MySQL容器停止运行了,那我们的数据库就没有了,停止容器就等于删库跑路了,那我们要怎么做才能保证即使容器停止或者被删掉数据都不会丢失呢?这时容器数据卷就诞生了,容器数据卷是容器与宿主机、容器与容器之间的一个数据共享技术,使用了容器数据卷Docker容器中产生的数据,就会同步到对应的宿主机或其他容器中,说白了就是挂载目录!
2、使用数据卷
2.1、命令挂载
# -it 交互运行 -v 挂载目录
docker run -it -v 宿主机目录:容器目录

上图所示
我们运行 docker run -it -v /home/testsync:/home centos /bin/bash ;将容器中的home文件和宿主机的home/testsync文件进行挂载,然后我们在容器中新建一个sync.go文件,退出容器后发现宿主机中的home文件夹中多了一个testsync文件夹里面有个sync.go文件,这说明我们的同步是成功的。
2.2、查看挂载信息
docker inspect 容器id

3、好处
数据同步,防止数据丢失
方便操作,挂载是双向同步的,如果我们把一些配置文件挂载到宿主机上,我们修改配置的时候就不用进入容器操作了
4、实战 (安装MySQL)
4.1、安装MySQL镜像
docker pull mysql:5.7
4.2、启动并挂载
我们先看官方文档是怎么运行的:https://hub.docker.com/_/mysql
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
从官方文档我们看出运行MySQL是要设置密码的
# 运行挂载并设置密码
docker run -d -p 3301:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql01 mysql:5.7
# 解释
-d 后台运行
-p 端口映射 -P(大p是随机映射,不用指定端口)
-v 数据卷挂载
-e 环境配置(这里是配置密码)
--name 容器名

4.3、测试
我们使用navicat测试连接一下

可以看到,连接成功,然后我们新建一个docker_db的库,再查看之前挂载的mysql/data文件夹

数据已经同步过来了,达到持久化
5、匿名挂载与具名挂载
5.1、匿名挂载
# 命令: -v 容器内路径
# eg: 使用匿名挂载启动一个nginx
docker run -d -P -name myNginx -v /ect/nginx nginx

# 查看所有挂载的 volume
docker volume ls

我们发现 volume name 是一个随机字符串,这就是匿名挂载
5.2、具名挂载
# 命令: -v 自定义name:容器内路径
# eg: 使用具名挂载启动一个nginx
docker run -d -P --name youNginx -v docker-nginx:/ect/nginx nginx

查看一下所有的 volume

这里的 volume name 就是我们自定义的名称,这就是具名挂载
5.3、卷文件位置
不管是匿名挂载还是具名挂载,所有容器内的卷文件都在/var/lib/docker/volumes/xxx/_data文件下的
# 查看卷信息
docker volume inspect 卷名

大多数情况下都是使用具名挂载和指定文件挂载两种方式,匿名挂载比较少用
5.4、拓展
docker run -d -P --name nginx01 -v jm-nginx:/ect/nginx:ro nginx
docker run -d -P --name nginx01 -v jm-nginx:/ect/nginx:rw nginx
# 这里我们发现多了一个ro 、rw,这是什么意思呢?
# ro -- readolny 只读
# rw -- readwrite 可读可写
# 一旦设置了 ro 在容器内部就无法修改了
6、初识Dockerfile
Dockerfile是用来构docker建镜像的文件
做一个简单的镜像
1.创建编辑文件
cd /home
# 在home目录下新建一个docker-my-volume文件夹
mkdir docker-my-volume
# 新建编辑文件
vim dockerfile01
文件内容如下:
FROM centos
VOLUNME ["volume1","volume2"]
CMD echo "==========end==========="
CMD /bin/bash

2.构建Dockerfile文件
docker build -f /home/docker-my-volume/dockerfile01 -t fan/centos:1.0 .
# 注意末尾有个点

可以看到我们自己新建的docker镜像就完成了
3.启动一下自己构建的镜像
docker run -it fan/centos:1.0 /bin/bash

这里有两个目录就是说明外部有两个文件与它同步
4.查看卷文件挂载的目录


5.测试容器内的文件是否与容器外部同步
[root@VM_0_8_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6f7b7136627 8c058fc997ea "/bin/bash" 14 minutes ago Up 14 minutes happy_curie
[root@VM_0_8_centos ~]# docker attach f6f7b7136627
[root@f6f7b7136627 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume1 volume2
[root@f6f7b7136627 /]# cd volume1
[root@f6f7b7136627 volume1]# ls
[root@f6f7b7136627 volume1]# touch text.log # 在容器内新建一个目录
[root@f6f7b7136627 volume1]# ls
text.log

7、数据卷容器
2.1、概念
就是容器与容器之间数据同步

2.2、测试容器卷
1.首先我们运行一个容器,作为父容器
# 运行一个容器把他命名为 centos-master
docker run -it --name centos-master 8c058fc997ea /bin/bash
2.再运行另一个容器,挂载到centos-master上
# 运行一个centos01容器并与master挂载
docker run -it --name centos01 --volumes-from centos-master 8c058fc997ea /bin/bash

3.在master上添加一个文件,查看是否会同步到01上
操作步骤如下图:

4.再启动一个容器02,挂载到master上
docker run -it --name centos02 --volumes-from centos-master fan/centos:1.0 /bin/bash

5.在master上新建文件,查看01容器和02容器的同步情况
如下图所示:

6.停止或删除master容器,01容器和02容器的数据会丢失吗?
我们知道容器一旦停止里面建的文件就会消失,那数据卷容器停止了,其他容器的数据会消失吗?
1、测试停止master容器

结果可以看出数据卷容器停止了,不会影响其他容器的数据
2、测试删除master容器

可以看出数据容器卷被删掉了也不会影响其他容器的数据
应用
可以实现MySQL,Redis等数据共享,配置文件信息传递。
结论
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。如果是持久化到宿主机,数据也是不会被删除的。
Dockerfile
概念:Dockerfile是用来构建docker镜像的文件,是一个命令参数脚本。
1、Docker 构造步骤
1、编写一个Dockerfile文件
2、docker build 构建成为一个镜像
3、ocker run 运行镜像
4、docker push 发布镜像
2、Dockerfile 构建过程
基础知识
- 1、每个保留的关键字都必须大写, 且后面要跟随至少一个参数
- 2、执行顺序是从上到下
- 3、井号(#)代表注释
- 4、每个指令都会创建提交一个新的镜像层并提交

注意
Dockerfile 是面向开发的,我们发布项目都需要编写Dockerfile文件
3、Dockerfile 指令
3.1、保留字
FROM # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER # 镜像维护者的姓名+邮箱地址
RUN # 容器构建时需要运行的命令
EXPOSE # 当前容器对外暴露的端口号
WORKDIR # 指定在容器创建后,终端默认登录进来工作目录
ENV # 用来在构建镜像过程中设置环境变量
ADD # 将宿主机目录下的文件拷贝到镜像里面并且ADD命令会自动处理URL和解压tar压缩包
COPY #
VOLUME # 容器数据卷,用于数据保存和持久化工作
CMD # 指定一个容器启动时要运行的命令,只有最后一个会生效,可以被取代
ENTRYPOINT # 指定一个容器启动时要运行的命令,可以追加命令
ONBUILD # (触发器)当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后,父镜像的onbuild被触发。

3.2、实战(自己写一个Dockerfile)
首先分析一下官方的centos镜像的Dockerfile

从Docker Hub上可以知道99%的Dockerfile都是从FROM scratch开始的,scratch是真正的基础镜像
我们运行一下从docker hub下载的的centos发现很多基础的命令都没有。非常的不好用,那我们就写一个自己的centos吧

开始创建一个自己的centos镜像
1.编写Dockerfile
# 编写Dockerfile
FROM centos
MAINTAINER fanzx<fan.zhong.xing@foxmail.com>
# 设置环境变量
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 安装命令
RUN yum -y install vim
RUN yum -y install tree
# 暴露80端口
EXPOSE 80
# 输出环境变量
CMD echo $MYPATH
CMD echo "------------------------end"
CMD /bin/bash
2.构建文件镜像
dokcer build -f dockerfile文件路径 -t 镜像名:[tag] . # 注意末尾有个点


3.测试运行自己的镜像

镜像是可以运行的,进入的目录也是我们设置的/usr/local,我们安装的tree命令也是可以的,可以看到是没有问题的
4.查看镜像的变更历史

3.3 CMD 和 ENTRYPOINT 的区别
区别
CMD和ENTRYPOINT都是指定一个容器启动时要运行的命令,但是如果dockerfile中可以有多个CMD指令,只有最后一个生效 ,CMD会被docker run之后的参数替换 ;而有多个ENTRYPOINT指令,每个指令都生效。
做一个简单的测试
CMD 测试

运行镜像后我们发现在dockerfile里的CMD命令是有运行的。
正常情况下我们run镜像的时候是可以追加命令的,假如我们追加-l,看看会怎么样?
# 思考:我们追加-l,原本Dockerfile里有 ls -a,那组合起来就是 ls -al 吗?
docker run cmdtest -l

运行之后发现报错了,报错说"-l"不是一个指令。
ENTRYPOINT 测试
还一样编写一个Dockerfile并创建镜像运行,是没有问题的。

运行run追加-l
docker run entryointtest -l

运行之后没有报错,而是执行的 docker run entryointtest ls -al的效果
结论:从测试的结果就能更清楚的看出CMD和ENTRYPOINT的区别了,CMD只有最后一个会生效,可以被取代,而ENTRYPOINT则是命令追加
4、实战:使用Dockerfile创建一个PHP项目镜像
待实现
5、发布自己的镜像
5.1、发布到DockerHub
1.注册账号
2.确认这个账号可以使用
3.提交镜像
# 登录dockerhub(一定要登录了才能提交)
docker login -u 账号 -p 密码
# 也可以先-u然后回车输入密码

# 提交镜像 (这些操作和git有点像)
docker push 镜像名:TAG
5.2、发布到阿里云
这个就不多介绍了,自己去阿里云找,里面的文档很详细
6、小结

Docker 网络
1、网络原理
查看网络
ip addr

每启动一个docker容器,docker就会给容器分配一个ip。我们只要安装了docker,就会有一个网卡docker0,使用的是桥接模式,使用的技术是veth-pari技术。
网络原理图

2、--link(了解)
3、自定义网络
1、查看所有的docker网络
docker network ls

- bridge : 桥接模式(docker默认模式)
- host:和宿主机共享网络
- none:不配做网络
2、创建自定义网络
# -d模式 bridge桥接 --subnet子网 --gateway网关
docker network create -d bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynetwork

我们自定义的网络docker已经帮我们维护好了对应关系,直接使用就可以了。推进使用自定义网络!
好处:不同的容器使用不同的网络,保证了容器之前的网络安全。
3、使用自定义网络
我们使用自定义的网络运行一下tomcat
docker run -d --name tomcat02 --network mynetwork tomcat


可以看到是正常运行的,而且通过inspect看到网络是我们自定义的。
