一. 容器数据卷
1. docker理念回顾
- 将应用和环境打包成一个镜像
- 数据存放在容器中, 当我们删除容器时, 数据也会丢失
- 需求: 数据可以持久化, 数据可以存储在本地
- 容器之间数据隔离, 需要实现数据共享
- 目录挂载: 将容器内的目录, 挂载到Linux上面
- 总结一句话: 数据卷就是容器的持久化和同步操作
2. 使用数据卷
1. 命令
-
方法一: 直接使用命令来挂载
-v
docker run -it -v 主机目录:容器目录
2. 案例
-
命令
docker run -it -v /home/ceshi:/home centos /bin/bash
本机中多了一个
ceshi
文件夹
-
在主机中查看挂载信息
docker inspect 7cd3884d2a68
-
在容器中创建文件
-
主机中也会有该文件
-
在主机中创建文件
-
容器中也会有该文件
-
哪怕容器关掉, 主机在共享文件夹中修改内容, 也会同步到容器对应的文件夹中
3. 实战: 安装MySQL
-
安装mysql
docker pull mysql
-
启动
# 官方测试: docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=mysql-secret-pw -d mysql:tag # -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_PASSWORD=123456 --name mysql01 mysql
-
navicat连接docker中的MySQL
-
在Mysql中创建一个数据库, 在主机中会生成一个相应的文件夹
4. 具名和匿名挂载
1. 说明
-
匿名挂载
# -v: 容器内路径 # 只写了容器内路径, 没有写容器外路径 docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看卷 docker volume ls
-
具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx docker volume ls
-
查看卷路径
docker volume inspect juming-nginx
-
区分
-v 容器内路径 # 匿名挂载 -v 卷名:容器内路径 # 具名挂载 -v /宿主机路径:容器内路径 # 指定路径挂载
2. 扩展
-
命令
# 通过 -v 容器内路径:ro/rw 改变读写权限 # ro readonly 只读 # rw readwrite 可读写 docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
-
一旦设置了容器权限, 容器对我们挂载出来的内容就有限定了
-
只要看到了ro, 就说明这个路径只能通过宿主机来操作, 容器内部无法操作!
5. 初识Dockerfile
Dockerfile就是用来构建docker镜像的构建文件! 命令脚本
通过这个脚本可以生成一个镜像
1. 命令
-
dockerfile文件内容
# 指令 参数 # 指令必须是大写 FORM centos VOLUME ["volume01", "volume02"] CMD echo "====end====" CMD /bin/bash
-
命令
docker build -f dockerfile -t hjf/centos .
-
启动自己创建的镜像, 并查看卷
docker run -it b055e8ac9aa8 /bin/bash
多了2个自己挂载的卷, 挂载的卷一定有和主机中同步的目录
-
查看卷的挂载
# docker inspect 容器id docker inspect 2e17c5f5d41f
测试一下刚才的文件是否同步到主机中了.
-
说明
这种方式使用十分多, 因为我们通常会构建自己的镜像!
假设构建镜像时没有挂载卷, 要手动镜像挂载 -v 容器内容路径
6. 数据卷容器
两个MySQL同步数据
1. 测试
-
启动3个自己docker
docker run -it --name docker01 b055e8ac9aa8 # --volumes-from 同步docker01 # 相当于docker02和docker03中继承docker01 # docker01就是数据卷容器 docker run -it --name docker02 --volumes-from docker01 b055e8ac9aa8 docker run -it --name docker03 --volumes-from docker01 b055e8ac9aa8
-
在docker03中创建一个文件
tocker docker03.txt
-
进入docker01
docker exec -it 26fa030e3dc6 /bin/bash
-
查看docker01中是否也有docker03中创建的文件
2. 说明
-
共享卷之间是拷贝的概念, 删掉任意一个容器, 都不会影响其他容器中的内容
3. 多个Mysql数据实现共享
-
命令
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-form mysql01 mysql
这样就可以实现两个容器数据同步
二. DockerFile
dockerfile是用来构建docker镜像的文件! 命令参数脚本!
1. DockerFile介绍
1. 构建步骤
- 编写一个dockerfile文件
docker build
构建成为一个镜像docker run
运行镜像docker push
发布镜像(DockerHub, 阿里云镜像仓库)
2. 构建过程
1. 基础知识
- 每个保留关键字(指令)都必须是大写的
- 执行从上到下顺序执行
#
表示注解- 每个指令都会创建提交一个新的镜像层, 并提交
2. 说明
- dockerfile是面向开发的, 我们以后要发布镜像, 做镜像, 就需要编写dockerfile文件
- docker镜像逐渐称为企业交付的标准, 必须要掌握.
- DockerFile: 构建文件, 定义了一切的步骤, 源代码
- DockerImages: 通过DockerFile构建生成的镜像, 最终发布和运行的产品
- Docker容器: 容器就镜像运行起来提供服务
3. DockerFile的指令
1. 指令
-
FROM
基础镜像, 一切从这里开始构建
要创建的镜像是以什么镜像为基础的
-
MAINTAINER
镜像是谁写的, 指定维护者信息, 姓名 + 邮箱
-
RUN
镜像构建的时候需要运行的命令
-
ADD
步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
-
WORKDIR
镜像的工作目录
-
VOLUME
挂载的目录
-
EXPOSE
暴露端口配置
-
CMD
指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
-
ENTRYPOINT
指定这个容器启动的时候要运行的命令,可以追加命令
-
ONBUILD
当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令
-
COPY
类似ADD,将我们文件拷贝到镜像中
-
ENV
构建的时候设置环境变量!
2. 案例: 构建自己的Centos
Docker Hub中99%镜像都是从这个基础镜像过来的: FROM scratch, 然后配置需要的软件和配置来进行的构建
-
说明
-
编写一个自己的centos
FROM centos MAINTAINER Jiang锋时刻<Jiangfengtime@gmail.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "---end---" CMD /bin/bash
-
通过这个文件构建镜像
# 命令 docker build -f 文件路径 -t 镜像名:[tag] . docker build -f dockerfile-centos -t mycentos:0.1 .
docker images
-
运行镜像
docker run -it mycentos:0.1 /bin/bash
3. CMD 和 ENTRYPOINT
-
CMD: 指定这个容器启动的时候要运行的命令, 只有最后一个会生效, 可被替代
-
ENTRYPOINT: 指定这个容器启动的时候要运行的命令, 可以追加命令
-
测试CMD
docker build -f dockerfile-cmd-test -t cmdtest . docker run 664950f6fd23
不能追加
-
ENTRYPOINT
docker build -f dockerfile-entrypoint-test -t entrypointte st . docker run 8b94ec644ad9 -l
追加成功
4. 实战: Tomcat镜像
1. 准备工作
-
上传下载的tomcat和jdk包
-
创建readme.txt文件
下面这个Dockerfile中用到了这个文件
2. 相关指令
-
Dockerfile文件内容
FROM centos MAINTAINER Jiang锋时刻<jiangfengtime@gmail.com> ADD jdk-8u231-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.39.tar.gz /usr/local/ RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH ENV JAVA_HOME /usr/local/jdk1.8.0_231 ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.39 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.39/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.39/logs/catalina.out
-
Dockerfile创建镜像的命令
docker build -t diytomcat .
-
查看docker中的镜像
-
进入
docker run -d -p 9090:8080 --name tomcat01 -v /home/hjf/build/tom cat/test:/usr/local/apache-tomcat-9.0.39/webapps/test -v /home/hjf/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.39/logs diytomcat
5. 发布镜像
1. 发布镜像到Docker Hub
-
注册Docker Hub账户
-
执行登录docker hub账户的命令
# docker login -u 账户名 docker login -u jiangfengtime
-
发布镜像
# docker push 镜像名 dicker push mytomcat
需要包含发布者信息
# 给需要发布的镜像打上标签, 添加信息 docker tag af86f7269004 jiangfengtime/mytomcat:1.0 # 发布 docker push jiangfengtime/mytomcat:1.0
-
查看
2. 发布到阿里云容器服务
-
进入到阿里云容器镜像服务 > 命名空间 > 创建命名空间
-
进入到阿里云容器镜像服务 > 镜像仓库 > 创建镜像仓库
-
查看命令
-
登录阿里云
# 登录阿里云 docker login --username=13540438597 registry.cn-shanghai.aliyuncs.com
-
上传
# 打标签 # docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/common-mirror/mycentos:[镜像版本号] docker tag 0d120b6ccaa8 registry.cn-shanghai.aliyuncs.com/common-mirror/mycentos:1.0 # 上传 # docker push registry.cn-shanghai.aliyuncs.com/common-mirror/mycentos:[镜像版本号] docker push registry.cn-shanghai.aliyuncs.com/common-mirror/mycentos:1.0
三. Docker 网络
1. 理解Docker0
1. 说明
-
查看ip
ip addr
-
启动一个容器
docker run -d -P --name tomcat01 tomcat docker exec -it tomcat01 ip addr
-
主机可以ping通Docker容器的ip地址
2. 原理
-
我们每启动一个docker容器, docker就hi给容器分配一个IP地址, 我们只要安装了docker, 就会有一个网卡docker0的桥接模式, 使用的技术是evth-pair技术.
-
启动一个容器就会多一个veth的网卡, 我们发现这个容器带来的网卡, 都是一对一对的.
-
evth-pair就是一对虚拟设备接口, 他们都是一对一对出现的, 一端连着协议, 一端彼此相连. 正因为有这个特性, evth-pair充当一个桥梁, 连接各种虚拟网络设备.
OpenStac, Docker容器之间的连接, OVS的连接, 都是使用evth-pair技术
-
容器间也可以相互ping通
# 查看容器的ip地址 docker exec -it tomcat01 ip addr docker exec -it tomcat02 ip addr # ping另一个容器的ip docker exec -it tomcat01 ping 172.17.0.3 docker exec -it tomcat02 ping 172.17.0.2
-
原理图
-
结论
tomcat01和tomcat02是公用的一个路由器docker0
所有的容器不指定网络的情况下, 都是docker01路由的, docker会给我们的容器分配一个默认的可用ip
2. --link
思考一个场景, 我们编写了一个微服务, 如果服务重启了, 服务对应的ip地址就会发生变化, 我们希望可以处理这个问题, 希望可以通过名字来访问容器
1. 案例
-
命令
# 两个容器间无法直接通过容器名称相连 docker exec -it tomcat01 ping tomcat02 # 启动tomcat03, 并用 --link 将tomcat03 与tomcat01相连 docker run -d -P --name tomcat03 --link tomcat01 tomcat # tomcat01不能和tomcat03相连 docker exec -it tomcat01 ping tomcat03 # 但tomcat03可以和tomcat01相连 docker exec -it tomcat03 ping tomcat01
-
原理
–link就是再host配置中增加了容器名和ip地址的映射
2. 说明
- Docker已经不建议使用–link了
- 自定义网络, 不适用docker0
- docker0问题: 它不支持容器名连接访问
3. 自定义网络
1. 查看了所有的docker网络
-
命令
docker network ls
2. 网络模式
- bridge: 桥接模式 (默认)
- host: 和宿主机共享网络(不建议使用)
- none: 不配置网络
- container: 容器内网络连通(不建议使用)
3. 测试
-
命令
docker run -d -P --name tomcat01 --net bridge tomcat # 等价, 默认就是bridge docker run -d -P --name tomcat01 tomcat
4. 自定义网络
-
创建自定义网络
# --driver bridge 网络模式 # --subnet 192.168.0.0/16 子网地址 # --gateway 192.168.0.1 网关 docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet docker network ls
-
查看详情
docker network inspect mynet
-
使用自定义网络启动容器
# 启动网络 docker run -d -P --name tomcat-net-1 --net mynet tomcat docker run -d -P --name tomcat-net-2 --net mynet tomcat # 查看自定义网络的详情 docker network inspect mynet
-
容器间ping
docker exec -it tomcat-net-1 ping 192.168.0.3 docker exec -it tomcat-net-1 ping tomcat-net-2
-
说明
我们自定义的网络docker都已经帮我们维护好了对应的关系, 推荐使用
不同的集群使用不同的网络, 保证集群是安全和健康的
5. 网络连通
-
不同网络之间的容器, 不能ping通
docker run -d -P --name tomcat-net-1 --net mynet tomcat docker run -d -P --name tomcat01 tomcat docker exec -it tomcat01 ping tomcat-net-1
-
测试连通tomcat01 - mynet
# 连通 docker network connect mynet tomcat01 # 查看网络详情 docker network inspect mynet
直接把容器加到网络中, 一个容器两个ip
-
此时就可以ping通了
docker exec -it tomcat01 ping tomcat-net-1
-
结论
如果要跨网络操作, 就需要使用
docker network connect
连通