docker比虚拟机有更少的抽象层
安装Dockerdocker利用的是宿主机的内核,避免引导。
安装需求
- To install Docker Engine, you need a maintained version of CentOS 7 or 8. Archived versions aren’t supported or tested.
卸载旧版本
yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine
仓库安装Docker
安装工具包
yum install -y yum-utils
设置镜像仓库
yum-config-manager
--add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #默认是国外,慢
yum更新
yum makecache fast
安装Docker最新的客户端、服务,容器
yum install docker-ce docker-ce-cli containerd.io
启动Docker
systemctl start docker
验证是否启动成功
docker version
运行Hello World程序
docker run hello-world
docker run hello-world 运行分析
查看下载的Hello-World镜像
docker images
Docker卸载
yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker rm -rf /var/lib/containerd
阿里云镜像加速
#前提,需要阿里云账号登录阿里云 这里懒得注册账号了,就没做了Docker的常用命令
帮助命令
docker version #docker版本显示
docker info #docker系统信息显示,包括镜像和容器的数量
docker 命令 --help #帮助命令
官方文档命令查询
https://docs.docker.com/engine/reference/run/
镜像命令
# 查看本机所有的镜像 docker images
# 只显示镜像的ID docker -images -q # 搜索dockerHub上的镜像 docker search xxx [--filter=stars=xxx] #--filter 过滤器 #下载镜像 docker pull xxx[:tag] #tag:版本 #删除指定镜像 docker rmi -f 镜像名称或者镜像ID #批量删除所有镜像 docker rmi -f $(docker images -aq)
容器命令
- 有了镜像才能创建容器
新建容器并启动
docker run [可选参数] image #可选参数 --name="xxx" #启动的容器的名称 -d #后台运行 -it #交互方式运行,进入容器查看内容 -p #指定容器的端口 -P #随机指定端口
退出容器
exit #容器停止退出 #容器中使用 ctrl+P+Q 快捷键来实现容器不停止退出
列出所有正在运行的容器
docker ps [可选参数] -a #列出当前运行的容器和历史运行过的容器 -n=? #显示最近创建的容器 -q #只显示容器的编号
删除容器
#删除指定容器,不能删除正在运行的容器 docker rm 容器ID #删除指定容器 docker rm -f 容器ID #删除所有的容器 docker rm -f $(docekr ps -aq)
启动和停止容器
docker start 容器ID #启动指定的容器 docker restart 容器ID #重启指定的容器 docker stop 容器ID #停止指定的容器 docker kill 容器ID #强制停止当前运行的容器
常用的其它命令
#后台运行 docker run -d 镜像名
#查看容器中的进程命令 dokcer top 容器ID
查看容器的元数据
docker inspect 容器ID
进入当前正在运行的容器
#方式1,进入容器后打开一个新的终端,可以操作 docker exec -it 容器ID /bin/bash #方式2,进入容器正在执行的终端 docker attach 容器ID
从容器内拷贝文件到主机上
docker cp 容器ID:容器内路径 目的主机路径
内存使用查看
docker stats
ES限制内存启动
#es不限制内存启动时,对于内存比较小的宿主机来说,有可能造成卡死,所以有时候需要限制内存消耗启动 docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch #参数解析 -d #后台启动 --name es01 #容器别名 -p 9200:9200 -p 9300:9300 #端口映射 主机端口:Docker容器内端口 -e "discovery.type=single-node" #集群配置,此处单节点 -e ES_JAVA_OPTS="-Xms64m -Xmx512m" #限制内存消耗,最小64M,最大512M镜像管理可视化面板
- portainer
#Docker的图形化界面管理工具 docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
- Rancher(CI/CD),进阶使用
docker commit 提交成为一个新的副本 docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[tag]容器的数据卷
容器内的数据通过挂载到容器外的文件夹来同步数据
容器的持久化和同步操作!容器间也是可以数据共享的
使用数据卷使用命令来挂载 -v
docker run -it -v 主机目录:容器内的目录[:ro/rw] #可选参数解析 ro : 路径只读 #容器有权限,不可更改内容,只能在宿主机更改文件 rw : 路径可读可写
#查看容器的详细信息 docker inspect 容器ID具名挂载&匿名挂载
匿名挂载:挂载时只写了容器内的路径,没有写容器外的路径
#匿名挂载宿主机的卷名是一串数字字符组合的长字符串 -v 容器内路径 #查看所有的卷(volume)的情况 docker volume ls
具名挂载:挂载时未写容器外的路径,而是使用 卷名:容器内的路径格式
#具名挂载可以方便我们找到卷 -v 卷名:容器内路径
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/***目录下
#三种挂载的区别 -v /宿主机路径:容器内的路径 #指定路径挂载 -v 卷名:容器内的路径 #具名挂载 -v 容器内的路径 #匿名挂载 #拓展 可以使用dockerfile来在构建容器时自动挂载数据卷容器
多个容器之间进行数据挂载同步时,父容器就是数据卷容器
-- volumes-from #示例 docker run 新容器 --volumes-from 已经启动的容器 镜像id/镜像名[:tag] #多个容器进行数据挂载同步,当删除其中一个容器时,与其相关的数据不会丢失,其它容器会同步保存相关文件数据。只有当挂载的所有容器都被删除时,才会丢失数据。一旦容器和宿主机之间挂载同步,只有容器全部被删除,宿主机数据删除或者删除宿主机时数据才会丢失DockerFile
Dockerfile就是用来构建docker镜像的脚本文件
构建步骤:
- 编写一个dockerfile文件
- docker bulid构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub)
基础语法
- 每个保留的关键字(指令)都必须是大写字母
- 执行从上往下执行
- #表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交
dockerfile指令
FROM #基础镜像,一切从这里开始的构建 #镜像是谁写的,标准命名:姓名+邮箱 RUN #镜像构建时需要需要运行的命令 ADD #添加如Tomcat,MySQL等内容 WORKDIR #镜像的工作目录 VOLUME #挂载卷的目录 EXPOSE #暴露端口 [-p]命令 CMD #指定这个容器启动时需要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT #指定这个容器启动时需要运行的命令 onBUILD #当构建一个被继承DockerFile,这个时候就会运行ONBUILD指令 COPY #将我们的文件拷贝到镜像中 ENV #构建的时候设置环境变量
#查看镜像构建的历史记录 docker histroy 镜像IDDocker实战1 Tomcat镜像制作
- 准备一个tomcat、jdk的压缩包
- 编写readme.txt和dockerfile等文件
#dockerfile文件 FROM centos MMAINTAINER ycyCOPY readme.txt /usr/local/readme.txt ADD jdk-8u221-linux-x64.rpm /usr/local/ ADD apache-tomcat-9.0.54.tar.gz /usr/local/ RUN yum -y install vim ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.54 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.54 ENV PATH $PATH:$CATALINA_HOME/lib;$CATALINA_HOME/bin EXPOSE 8080 CMD /usr/local/apache-tomcat-9.0.54/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.54/bin/logs/catalina.out
- 构建镜像
docker build [-f] -t 镜像名 . #以Dockerfile命名时,[-f]参数可不写
- 启动镜像
docker run -d -p 9090:8080 --name tomcat01 -v /home/ycy/build/tomcat/test:/usr/local/apache-tomcat-9.0.54/webapps/test -v /home/ycy/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.54/logs diytomcat发布镜像
DockerHub
#登录docker账户 docker login -u [账户名] docker push [作者/镜像名:tag]
#错误解决 The push refers to repository [docker.io/ycy/diytomcat] An image does not exist locally with the tag: ycy/diytomcat #给镜像加一个tag docker tag [镜像id] [新的镜像名称:版本号]
阿里云镜像 这里同样懒得注册阿里云账号,没做了
- 登录阿里云
- 找到容器镜像服务
- 创建命名空间
- 创建容器镜像(镜像仓库)
- 有推送镜像教程
安装docker即会安装docker0,启动时展示,是一个虚拟网卡
#实验:使用Tomcat容器来连接数据库容器,实现容器间的网络互通 #启动一个tomcat docker run -d -P --name tomcat01 tomcat #查看容器的内部网络地址 docker exec -it 容器名 ip addr
#错误 OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ifconfig": executable file not found in $PATH: unknown #解决方法: #进入容器内 apt update && apt install -y iproute2
#Linux内ping容器地址 ping 172.17.0.2 #状态:OK
原理
- 只要安装了docker,就会安装一个网卡docker0,以桥接模式接到真实的网络上
- 每启动一个容器,都会被docker0分配一个地址
- docker 网络使用evth-pair技术来保证网络互通
当没有容器启动时,我们在Linux中使用ip addr命令查看ip地址信息,只有本机回环地址、本机网络地址,和docker0地址信息
当我们启动一个容器时查看ip地址信息
此处多了一个51: veth61199a7@if50的网卡信息
进入容器内部查看ip地址信息
容器内也有一个50: eth0@if51的网卡信息
再启动一个tomcat容器,查看ip地址信息
发现又多了一个53: veth8635c73@if52的网卡信息
进入新的容器内查看ip信息
容器内也有一个52: eth0@if53的网卡信息
解释
51: veth61199a7@if50和50: eth0@if51、53: veth8635c73@if52和52: eth0@if53这两对网卡信息就是evth-pair技术的实现。在docker网络中,使用evth-pair技术来实现网络的互通
- evth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连
- 我们一般使用evth-pair充当一个桥梁,来实现docker通信,以上述的实例,画图理解
小结
docker中的所有网络接口都是虚拟的,因为虚拟的接口转发效率高。
但是只要容器停止或者删除了,对应的网桥和docker0分配的地址就失效了,再次启动时会分配新的一对evth-pair接口和网络地址。
思考:微服务场景中,使用JDBC连接数据库时,通常需要设置database url = ip ,如果容器崩了或者停止了,就会导致ip改变,JDBC无法连接MySQL,如何解决?
docker网络— --link解决:使用容器的ID或者服务名来连接通信,而不是使用ip来连接。通过服务名来进行容器的访问,docker解决方案为 --link
# 启动两个tomcat,使用tomcat1来ping测试tomcat2 docker exec -it tomcat1 ping tomcat2 # 状态 False 无法找到tomcat2服务 ping: tomcat2: Name or service not known # --link示范 #再启动一个tomcat3,以--link的形式和tomcat2连接启动 docker run -d -P --name tomcat3 --link tomcat2 tomcat # tomcat3 ping tomcat2 docker exec -it tomcat3 ping tomcat2 # 状态 Ok PING tomcat2 (172.17.0.2) 56(84) bytes of data. 64 bytes from tomcat2 (172.17.0.2): icmp_seq=1 ttl=64 time=0.169 ms 64 bytes from tomcat2 (172.17.0.2): icmp_seq=2 ttl=64 time=0.082 ms ...... # tomcat2 ping tomcat3 docker exec -it tomcat2 ping tomcat3 # 状态 False ping: tomcat3: Name or service not known # 结论:使用--link命令后,tomcat3可以ping通tomcat2,但是tomcat2不可以ping通tomcat3 # 原理探究 # 查看tomcat3的hosts文件,可以发现标注绿色的一行做了地址 容器名称的绑定,所以tomcat3可以ping通tomcat2 docker exec -it tomcat3 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters `172.17.0.2 tomcat2 1bdb7bc92c17` 172.17.0.4 b4240695272c # 错误 OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ping": executable file not found in $PATH: unknown # 解决 # 进入容器 apt-get update apt install iputils-ping
docker网络— 自定义网络注意:–link已经不推荐使用,而使用自定义网络
容器互联一般指自定义网络实现,虽然使用–link也能实现,但是不够灵活
# 查看所有的docker网络 docker network ls
# 网络模式 * bridge : 桥接模式 docker0与自定义网络 * none : 不配置网络 一般不用 * host : 主机模式 和宿主机共享网络 * contairner : 容器网络联通 用的很少(局限性很大) 资料需自查
# 测试:创建一个自定义网络 # 之前从镜像直接启动容器时,会默认走docker0,[]内参数默认会添加,例如如下命令 docker run -d -P --name tomcat1 [--net bridge] tomcat # docker0特点:默认,域名不能访问,虽然可以通过--link打通,但是不够灵活 # 自定义一个网络 docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 ynet # 参数解释 --driver bridge :指定桥接模式 --subnet 192.168.0.0/16 :指定网段 --gateway 192.168.0.1 :指定网关 ynet :自定义网络名 # 再次查看所有网络信息 docker network ls
# 指定网络启动两个tomcat docker run -d -P --name tomcat1 --net ynet tomcat docker run -d -P --name tomcat2 --net ynet tomcat # 使用容器名ping测试 docker exec -it tomcat1 ping tomcat2 # 状态 OK
docker网络— 不同网段容器互联由此得出,使用自定义网络时,不需要任何配置,docker为我们维护好了关系,同一个网段下容器可以通过容器名互联,而且搭建集群时,不同的集群使用不同的网络,互相不影响
案例:以上已经有了在ynet网段下的两个容器,并且可以ping通,如果使用默认的docker0再创建一个tomcat3,tomcat3是否能和tomcat1和tomcat2联通?
# 使用默认的docker0来创建一个tomcat3容器 docker run -d -P --name tomcat3 tomcat # 使用tomcat3来ping测试tomcat1、tomcat2 docker exec -it tomcat3 ping tomcat2 docker exec -it tomcat3 ping tomcat1 # 状态 False ping: tomcat2: Name or service not known ping: tomcat1: Name or service not known # 原因:tomcat3和tomcat2、tomcat1不在同一个网段,自然不通 # 解决: # 通过 docker network --help 命令以发现有 connect 参数
# 使用connect参数来完成不同网段的容器的互联互通 docker network connect ynet tomcat3 # 使用tomcat3来ping测试tomcat1、tomcat2 docker exec -it tomcat3 ping tomcat2 docker exec -it tomcat3 ping tomcat1 #状态:OK #原理:
- 通过docker network inspect ynet命令可以看到以上信息中,ynet直接给tomcat3分配了一个本网段的地址
- 其本质是一个容器两个地址
课程链接取消互联可以使用disconnect参数,如
docker network disconnect ynet tomcat3
https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0



