杨凌网站建设推广,印花图案设计网站,菜鸟教程网站,天津做网站软件1 容器数据卷
什么是容器数据卷#xff1a;
将应用和环境打包成一个镜像#xff01;数据#xff1f;如果数据都在容器中#xff0c;那么我们容器删除#xff0c;数据就会丢失#xff01;需求#xff1a;数据可以持久 化。MySQL容器删除了#xff0c;删容器跑路#…1 容器数据卷
什么是容器数据卷
将应用和环境打包成一个镜像数据如果数据都在容器中那么我们容器删除数据就会丢失需求数据可以持久 化。MySQL容器删除了删容器跑路需求MySQL数据可以存储在本地容器之间可以有一个数据共享的技术Docker 容器中产生的数据同步到本地 这就是 卷 技术目录的挂载将我们容器内的目录挂载到 Linux 上面 总结一句话容器的持久化和同步操作容器间也是可以数据共享的
数据卷的使用
方式一直接使用命令来挂载 -v
docker run -it -v 主机目录容器内目录# 测试
docker run -it -v /home/ceshi:/home centos /bin/bash
挂载之后进入容器内部且容器内的 /home 目录下是为空的
而此时对应的主机目录下多了一个 “ 测试 ” 文件夹
# 通过 docker inspect 容器id 查看具体信息
[rootiZf8z4ii45kfjc41qrt363Z home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a08e7f9bebe centos /bin/bash 4 minutes ago Up 4 minutes optimistic_johnson
34646bb73eca portainer/portainer /portainer 14 hours ago Up 14 hours 0.0.0.0:8088-9000/tcp romantic_goldberg
[rootiZf8z4ii45kfjc41qrt363Z home]# docker inspect 7a08e7f9bebe 测试文件的同步
只有一个物理地址二者共享一个资源
测试2
1、停止容器
2、宿主机修改文件
3、启动容器
4、容器内的数据依旧是同步的好处我们以后修改只需要在本地修改即可容器内会自动同步
安装 MySQL 思考MySQL 的数据持久化的问题
# 获取mysql镜像
docker pull mysql:5.7
# 运行容器,需要做数据挂载 #安装启动mysql需要配置密码的这是要注意点#启动
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
-- name 容器名字
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD123456 --name mysql01 mysql:5.7
# 启动成功之后我们在本地使用sqlyog来测试一下
# sqlyog--连接到服务器的3310--和容器内的3306映射 # 在本地测试创建一个数据库查看一下我们映射的路径是否ok
新建一个数据库后对应的主机内的/home/mysql/data也出现了test数据库的文件假设我们将容器删除 。发现我们挂载到本地的数据卷依旧没有丢失这就实现了容器数据持久化功能。 具名挂载和匿名挂载
匿名挂载
-P 不指定路径
-v 容器内路径!
docker run -d -P --name nginx01 -v /etc/nginx nginx# 查看所有的volume的情况
docker volume ls# 这种就是匿名挂载我们在 -v 只写了容器内的路径没有写容器外的路径 # 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
docker volume ls # 通过 -v 卷名容器内路径
# 查看一下这个卷 所有的docker容器内的卷没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data 下如果指定了目录docker volume ls 是查看不到的。我们通过具名挂载可以方便的找到我们的一个卷大多数情况使用具名挂载
# 三种挂载 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名容器内路径 #具名挂载 和指定路径挂载没关系具名是指定卷名
-v /宿主机路径容器内路径 #指定路径挂载 此时 docker volume ls 是查看不到的拓展
# 通过 -v 容器内路径 ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写# 一旦设置了容器权限容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx02 -v juming:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming:/etc/nginx:rw nginx# ro 只要看到ro就说明这个路径只能通过宿主机来操作容器内部是无法操作
初识 Dockerfile 挂载的第二种方式 Dockerfile 就是用来构建 docker 镜像的构建文件相当于命令脚本。 通过这个脚本可以生成镜像。镜像是一层一层的脚本的一个个的命令每个命令都是一层
# 创建一个dockerfile文件名字可以随便 建议Dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos VOLUME [volume01,volume02] CMD echo ----end----
CMD /bin/bash
#这里的每个命令就是镜像的一层
docker build -f /home/docker-test-volume/dockerfile1 -t kuangshen/centos:1.0 .最后面要加上 “.” 启动自己写的镜像 这个卷和外部一定有一个同步的目录。且这种方式属于匿名挂载 查看一下卷挂载docker inspect 容器id 测试一下刚才的文件是否同步出去了在主机的挂载目录下也能找到刚才创建的文件说明同步成功了
这种方式使用的十分多因为我们通常会构建自己的镜像
假设构建镜像时候没有挂载卷要手动镜像挂载 -v 卷名容器内路径 数据卷-容器之间 多个MySQL同步数据
输入 CTRL P Q 不停止当前容器的运行并退出 在 docker01 的卷中创建文件并在 docker02 的卷中查看 再创建一个 docker03可见文件也是同步的 测试可以删除docker01查看一下docker02和docker03是否可以访问这个文件 结果是依旧可以访问 理解类似指针的概念都指向同一个地址
多个mysql实现数据共享
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD123456 --name mysql01 mysql:5.7docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD123456 --name mysql02 --volumes-from mysql01 mysql:5.7# 这个时候可以实现两个容器数据同步
小结 容器之间配置信息的传递数据卷的生命周期一直持续到没有容器使用它为主 但是一旦你持久化到了本地这个时候本地的数据是一直不会被删除的
2 DockerFile
简介 dockerfile 是用来构建docker镜像的文件是一个命令参数脚本。
构建步骤 1、编写一个 dockerfile 文件 2、docker build 构建成为一个镜像 3、docker run 运行镜像 4、docker push 发布镜像DockerHub 、阿里云仓库
查一下官方怎么做的 很多官方镜像都是基础包很多功能没有我们通常会自己搭建自己的镜像官方既然可以制作镜像那我们也可以
DockerFile 构建过程
每个保留关键字(指令都是必须是大写字母执行从上到下顺序# 表示注释每一个指令都会创建提交一个新的镜像层并提交 Dockerfile 是面向开发的我们以后要发布项目做镜像就需要编写 dockerfile 文件这个文件并不难
Docker 镜像逐渐成企业交付的标准必须要掌握
DockerFile构建文件定义了一切的步骤。相当于源代码DockerImages通过DockerFile构建生成的镜像。是最终发布和运行的产品。Docker 容器容器就是镜像运行起来提供服务。DockerFile–DockerImages–Docker 容器代码–类–类创建出来的对象
DockerFile 常用指令
FROM # 基础镜像一切从这里开始构建
MAINTAINER # 镜像是谁写的 姓名邮箱
LABEL # 现在推荐写 LABEL代替上面的那个
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤如要加一个tomcat镜像就是加这个tomcat压缩包1.添加内容 2.添加同目录
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令只有最后一个会生效可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令可以追加命令
ONBUILD # 当构建一个被继承的 DockerFile 时这时就会运行ONBUILD的指令触发别的指令。
COPY # 类似ADD将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量 实战测试
Docker Hub 中 99% 的镜像都是从这个基础镜像过来的FROM scratch然后配置需要的软件和配置 来进行的构建 创建一个自己的 centos
# 1.编写Dockerfile的文件
FROM centos:7 # 注意这里要加上:7不然的话自动下载8的版本会失败
MAINTAINER shenxinde552456727qq.comENV MYPATH /usr/local
WORKDIR $MYPATHRUN yum -y install vim
RUN yum -y install net-toolsEXPOSE 80CMD echo $MYPATH
CMD echo ----end----
CMD /bin/bash# 2.通过这个文件构建镜像
# 命令 docker build -f 文件路径 -t 镜像名:[tag] .
docker build -f Dockerfile -t define/centos:0.1 .# 成功后会显示如下信息
Successfully built 7aa5c35cd638
Successfully tagged mycentos:0.1# 3、测试运行
对比之前的原生的 centos 我们增加之后的镜像 我们可以列出本地进行的变更历史 这样我们平时拿到一个镜像就可以研究一下它是怎么做的了
CMD 和 ENTRYPOINT 区别cmd 会覆盖命令后者不会
CMD # 指定这个容器启动的时候要运行的命令只有最后一个会生效可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令可以追加命令测试 cmd
# 编写dockerfile文件
vim dockerfile-test-cmd
FROM centos:7
CMD [ls,-a]# 构建镜像
docker build -f dockerfile-test-cmd -t cmd-test:0.1 .Successfully built a3867a9baee9
Successfully tagged cmdtest:0.1# 运行镜像 发现命令生效了
docker run a3867a9baee9 # 想追加一个命令 -l 成为 ls -al
$ docker run a3867a9baee9 -l
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: -l: executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
错误原因cmd 的情况下-l 替换了 CMD[[“ls”,“-a”]。而 -l 不是命令所以会报错。 解决方案写出完整的命令ls -al。如下便是成功
测试 ENTRYPOINT
# 编写dockerfile文件
vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT [ls,-a] # 构建
docker build -f dockerfile-cmd-entrypoint -t entrypoint-test:0.1 .# 显示成功
Successfully built 4d16832a0317
Successfully tagged entrypoint-test:0.1# 运行并成功显示
docker run 4d16832a0317
.
..
.dockerenv
bin
dev
etc
home
lib
lib64 ...# 再次测试将命令-l直接添加在run的后面。会发现也能正常显示
# 说明这个命令是直接拼接在我们的ENTRYPOINT命令后面的
docker run 4d16832a0317 -l
total 56
drwxr-xr-x 1 root root 4096 Mar 25 06:28 .
drwxr-xr-x 1 root root 4096 Mar 25 06:28 ..
-rwxr-xr-x 1 root root 0 Mar 25 06:28 .dockerenv
...
Dockerfile中很多命令都十分的相似我们需要了解它们的区别我们最好的学习就是对比他们然后测试效果。
实战Tomcat 镜像 1、准备镜像文件准备tomcat 和 jdk到当前目录编写好README 。 2、编写 Dockerfile 文件使用官方命名 Dockerfile。这样的话build 时就会自动寻找这个文件就不用加 -f 指定文件了。
FROM centos:7
MAINTAINER zhaoshuai-lczhaoshuai-lcinspur.comCOPY readme.txt /usr/local/readme.txtADD jdk-8u381-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.78.tar.gz /usr/local/RUN yum -y install vimENV WORK_PATH /usr/local
WORKDIR $WORK_PATHENV JAVA_HOME /usr/local/jdk1.8.0_161
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.60
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.60
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/binEXPOSE 8080CMD /usr/local/apache-tomcat-9.0.78/bin/startup.sh tail -f /usr/local/apache-tomcat-9.0.78/logs/catalina.out3、构建镜像
docker build -t diytomcat:1.0 .# 显示成功
Successfully built 5786c54120cf
Successfully tagged diytomcat:1.0
4、run 镜像
docker run -d -p 9090:8080 --name zhaoshuaitomcat -v /home/zhaoshuai/build/tomcat/test:/usr/local/apache-tomcat-9.0.78/webapps/test diytomcat:1.05、访问测试
# 测试本机连接
curl localhost:90906、发布项目由于做了卷挂载我们直接在本地编写项目就可以发布了
web-app version3.0 xmlnshttp://java.sun.com/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd
/web-app
html
headtitleHello World/title/head
body
Hello World!br/
/body
/html
发现项目部署成功可以直接访问 我们以后开发的步骤需要掌握Dockerfile的编写我们之后的一切都是使用docker镜像来发布运行
查看日志:
发布自己的镜像: 提交 push 镜像
# 第一种 build的时候添加你的dockerhub用户名然后在push就可以放到自己的仓库了
$ docker build -t chengcoder/mytomcat:0.1 .
# 第二种 使用docker tag #然后再次push
$ docker tag 容器id chengcoder/mytomcat:1.0
# 然后再次push阿里云镜像服务 1、登录阿里云找到容器镜像服务 2、创建命名空间 和 仓库 3、选择本地仓库 4、操作指南
3 Docker 网络
理解Docker0 清空所有环境
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -aq)测试 问题 docker 是如果处理容器网络访问的
# 测试 运行一个 tomcat
docker run -d -P --name tomcat01 tomcat# 查看网络
docker exec -it tomcat01 ip addr
此时出现报错。这是版本不一致导致的缺失命令
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: ip: executable file not found in $PATH: unknown
进入容器更新所需的命令
docker exec -it tomcat01 /bin/bash
apt update apt install -y iproute2
更新完成后退出容器再次输入 docker exec -it tomcat01 ip addr 查看网络情况
发现容器启动的时候会得到一个 eth0if103 的 ip 地址这是 docker 分配的 思考 Linux 能不能ping通容器内部-- 可以 容器内部可以ping通外界吗 可以
原理 1、我们每启动一个 docker 容器docker 就会给 docker 容器分配一个 IP我们只要安装了 docker就会有一个网卡 docker0 桥接模式使用的技术是 veth-pair 技术 再次测试 ip addr发现多了一个 ip 2、再启动一个容器测试发现又多了一对网卡 再次进入容器tomcat02内部更新命令资源退出后重新查看ip 可以发现和上面的是能对应上的所以说是一对网卡
# 我们发现这个容器带来网卡都是一对对的
# veth-pair 就是一对的虚拟设备接口他们都是成对出现的一端连着协议一端彼此相连
# 正因为有这个特性利用 veth-pair 充当一个桥梁连接各种虚拟网络设备的
# OpenStac,Docker容器之间的连接OVS的连接都是使用veth-pair技术
3、我们来测试下 tomcat01 和 tomcat02 是否可以ping通
# 进入容器更新命令资源
docker exec -it tomcat02 /bin/bash
apt update apt install -y iproute2
apt install iputils-ping# 更新完成后退出容器输入 ping 命令
exit
docker exec -it tomcat02 ping 172.17.0.2 结论容器和容器之间是可以 ping 通的并且是通过 docker0 而非直接连通 所有的容器不指定网络的情况下都是 docker0 路由的docker会给我们的容器分配一个默认的可用 ip
Docker 使用的是 Linux 的桥接宿主机是一个 Docker 容器的网桥 docker0 Docker中所有网络接口都是虚拟的不需要考虑硬件因素虚拟的转发效率高内网传递文件
只要容器删除对应的一对网桥就没了
思考一个场景我们编写了一个微服务database urlip: 项目不重启但是数据ip换了我们希望可以处理这个问题。故通过名字来进行访问容器。
自定义网络: 查看所有的 docker 网络 网络模式
bridge 桥接 docker默认自己创建也是用bridge模式
none 不配置网络一般不用
host 和所主机共享网络
container 容器网络连通用得少局限很大
测试 先清空所有的环境
docker rm -f $(docker ps -aq)
这时就恢复成只有三个网卡的状态 自定义网络
# 我们直接启动的命令 --net bridge,而这个就是我们的docker0
# bridge就是docker0
$ docker run -d -P --name tomcat01 tomcat
等价于 docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点默认域名不能访问。 --link可以打通连接但是很麻烦
# 我们可以 自定义一个网络
[rootinspur ~]# docker network create --driver bridge --subnet 172.18.0.0/16 --gateway 172.18.0.1 mynet
# subnet 是子网gateway 是路由 $ docker network inspect mynet; 启动两个tomcat再次查看网络情况
docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcatdocker network inspect mynet 可以看到现在的两个容器网卡是我们自定义的 ip 地址 在自定义的网络下服务可以互相ping通仅仅使用名字无需 --link 我们自定义的网络docker帮我们维护好了对应的关系推荐我们平时这样使用网络
好处
redis -不同的集群使用不同的网络保证集群是安全和健康的 mysql-不同的集群使用不同的网络保证集群是安全和健康的 网络连通:
docker0 和 mynet 是无法直接连接的并且也不能直接打通。若需要连通的话要 connect 连接 docker0 的容器 和 mynet 的网络 连通之后发现 docker0 下的容器 tomcat1直接被连到 mynet 的网络下了 这就是 一个容器 两个 ip 地址 好比阿里云服务器有一个公网 ip 和一个私网 ip
docker network connect mynet tomcat1
docker network inspect mynet docker0 下的 tomcat1 连通加入后此时它已经可以和 mynet 下的tomcat01 ping通了 而 docker0 下的 tomcat2 仍然是不通的 假设要跨网络操作别人就需要使用docker network connect 连通