这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记。
虚拟机与docker
虚拟机技术缺点:
- 资源占用多
- 冗余步骤多
- 启动慢
比较Docker和虚拟机技术的不同:
- 传统虚拟机,虚拟出一套硬件,运行一个完整的操作系统,然后再这个系统上安装和运行软件。
- 容器内的应用直接运行再宿主机的内容,容器时没有自己的内核的,也没有虚拟硬件,所以就轻便了。
- 每个容器间是相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响。
DevOps(开发、运维)
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
docker:打包镜像发布测试,一键运行。
更便捷的升级和扩缩容
使用了docker后,部署应用就像搭积木
更简单的系统运维
在容器化后,开发环境和测试环境都是高度一致的
更高效的计算资源利用
docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例,充分发挥服务器的性能
Docker的基本组成
镜像(image) :docker镜像就好比是一个模板,可以通过这个模板来创建服务。如:tomcat-image 👉run👉tomcat01容器。可以通过这个镜像创建多个容器。
容器(container) :docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的。启动、停止、删除、基本命令。
目前可以把这个容器理解为一个建议的linux系统。
仓库(repository) :仓库就是存档镜像的地方。仓库分为共有仓库和私有仓库。
Docker原理
运行流程
底层原理
Docker是一个C/S结构的系统,docker的守护进程运行在主机上,通过socket访问。
DockerServer接收到DockerClient的指令,就会执行这个命令。
Docker为什么比vm快
1.docker有着比虚拟机更少的抽象层
2.docker利用的是宿主机的内核,vm是用Guest OS
所以,新建一个容器的时候,docker不需要像虚拟机一样加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,是分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,是秒级别的。
Docker的常用命令
帮助命令
docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help # 万能命令
帮助文档:docs.docker.com/reference/
镜像命令
docker images # 查看所有本地的镜像
\
可选项\
--all , -a Show all images (default hides intermediate images)
--digests Show digests
--filter , -f Filter output based on conditions provided
--format Pretty-print images using a Go template
--no-trunc Don’t truncate output
--quiet , -q Only show image IDs
docker search mysql # 搜索mysql镜像
\
可选项\
Name, shorthand Default Description
--filter , -f Filter output based on conditions provided
--format Pretty-print search using a Go template
--limit 25 Max number of search results
--no-trunc Don’t truncate output
docker pull mysql[:tag] # 下载mysql镜像,如果不写tag默认latest
docker rmi -f id # 通过id删除指定容器
docker rmi -f id1 id2 id3 # 通过多个id删除多个容器
docker rmi $(docker images -aq) # 删除全部容器
容器命令
docker run [可选参数] image\
参数说明\
--name="name" 容器名字
-d 后台运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
容器端口
-P 随机指定端口
docker ps # 列出当前正在运行的容器
-a # 列出当前正在运行的容器 + 历史运行过的容器
-n # 显示最近创建的容器
-q # 只显示容器的编号
exit # 直接停止容器并退出
Ctrl + p + q # 容器不停止退出
docker rm 容器id
docker rm -f $(docker ps -aq)
docker ps -a -q | xargs docker rm
docker start 容器id # 开启容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止正在运行容器
docker kill 容器id # 杀死容器
常用命令
命令 docker run -d 镜像名\
docker run -d centos
\
问题docker ps,发现centos停止了\
\
常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止。\
nginx容器启动后,发现自己没有提供服务,就会立即停止。
查看日志\
docker logs
-tf # 显示日志
--tail 10 # 显示日志条数
查看容器中进程信息\
docker top 容器id
查看容器的元数据\
docker inspect 容器id
进入当前正在运行的容器\
\
方式一\
docker exec -it 容器id /bin/bash\
进入容器后开启一个新的终端,可以在里面操作\
\
方式二\
docker attach 容器id\
进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上\
docker cp 容器id:容器内路径 目的主机路径
阶段作业
部署Nginx
- docker search nginx
- docker pull nginx
- docker images
- docker run -d --name nginx3340 -p 3340:80 nginx(端口暴露)
- docker exec -it nginx3340 /bin/bash
- docker stop nginx3340
- docker rm nginx3340
Docker镜像
UnionFS(联合文件系统)
UnionFS(联合文件系统):UnionFS文件系统时一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统时docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特征:一次同时加载多个文件系统,但是从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Dockers镜像加载原理
docker的镜像实际上时由一层一层的文件系统组成,这种层级的文件系统UnionFS。
分层原理
commit镜像
docker commit 提交容器成为一个新的副本
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[tag]
容器数据卷
docker的理念回顾
如果数据都在容器中,当容器被删除时,数据就会丢失。需求:数据可以持久化
mysql容器删除后,就可以准备跑路了。需求:mysql数据可以储存在本地
容器之间可以有一个数据共享的技术。docker容器中产生的数据,同步到本地。
这就是卷技术。目录的挂载,将容器内的目录,挂载在宿主机上。(容器的持久化和同步操作!容器间也是可以数据共享的!)
使用数据卷
指定路径挂载\
docker run -it -v 主机目录:容器目录 centos /bin/bash
\
主机目录与容器目录双向绑定
实战:安装MySQL
下载\
docker pull mysql
\
启动\
-d 后台运行
-p 端口映射
-v 数据卷挂载
-e 环境配置
--name 容器命名
docker run -d -p 3306:3306 -v /usr/local/docker-volume/mysql/conf:/etc/mysql/conf.d -v /usr/local/docker-volume/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=Xu595082586 --name mysql3306 mysql
具名挂载与匿名挂载
匿名挂载\
-v 容器内路径
docker run -d -P --name nginx3340 -v /etc/nginx nginx\
-v 只写容器内的命令\
\
具名挂载\
-v 卷名:容器内路径
docker run -d -P --name nginx3340 -v juming-nginx:/etc/nginx nginx
上图说明:/etc/nginx nginx目录挂载在/var/lib/docker/volumes/juming-nginx/_data
-v 主机目录(绝对路径):容器目录 # 指定路径
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
\
一下命令将报错\
docker run -d -P --name nginx03 -v nginxtest/in:/etc/nginx nginx
拓展:
:ro 只能通过宿主机操作,无法在容器内修改文件\
docker run -d -P --name nginx3340 -v juming-nginx:/etc/nginx:ro nginx
\
:rw\
docker run -d -P --name nginx3340 -v juming-nginx:/etc/nginx:rw nginx
初识DockersFile
dockerfile就是用来构建docker镜像的构建文件。命令脚本。
通过脚本生成镜像\
\
第一步,写脚本文件\
FORM centos
VOLUME ["volume01", "volume02"]
CMD echo "-----end-----"
CMD /bin/bash
#第二步,build(命令结尾需要一个点)
docker build -f dockerfiletext -t single/nginx-single:1.0 .
数据卷容器
docker run -it --name docker01 single/centos
docker run -it --name docker02 --volumes-from docker01 single/centos
\
现象:docker容器运行后,宿主机与docker01存在数据卷\
docker02数据卷挂载在docker01上,docker02运行后,宿主机上不再生成新的数据卷。\
宿主机 <--> docker01 <--> docker02
DockersFile
dockerfile是用来构建docker镜像的文件
步骤:
- 编写一个dockersfile文件
- docker build构建成为一个镜像
- docker run运行镜像
- docker push发布镜像(DockerHub、阿里云镜像仓库)
DockerFile构建过程
- 每个保留关键字都必须是大写字母
- 执行从上至下
- #表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交。
dockerfile是面向开发的,以后我们要发布项目,做镜像,就要编写dockerfile文件,这个文件十分简单!
dockerfile:构建文件,定义了一切的步骤,源代码。
dockerimage:通过dockerfile构建生成的镜像,最终发布和运行的产品
docker容器:容器就是镜像运行起来提供服务器
FROM # 基础镜像
MAINTAINER # 镜像作业,名字+邮箱
RUN # 镜像构建的时候需要执行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包
WORKDIR # 镜像的工作目录
VOLUME # 挂载目录
EXPOSE # 暴露端口
RUN # 运行
CMD # 指定容器启动的时候的命令,只有最后一个会生效
ENTRYPOINT # 指定容器启动的时候的命令,可以追加命令
ONBUILD # 当构建一个被继承的DockerFile这个时候就会运行ONBUILD命令。
COPY # 类似ADD,将文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战:创建一个自己的centos
FROM centos
MAINTAINER 1999singlesingle_xu1999@163.com
ENV MYPATH /usr/local
WORKDIR MYPATH
CMD echo "----end----"
CMD /bin/bash
docker build -f mydockerfile-centos -t mycentos:0.1 .
实战:Dockerfile制作tomcat镜像
FROM centos
MAINTAINER 1999singlesingle_xu1999@163.com
COPY readme.md /usr/local/readme.md
ADD jdk-8u151-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-10.0.0.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR JAVA_HOME/lib/dt.jar:PATH:CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-10.0.0/bin/startup.sh && tail -F /usr/local/apache-tomcat-10.0.0/bin/logs/catalina.out\
构建镜像(以dockerfile命名,就不需要用 -f mydockerfile)\
docker build -t diytomcat .
Docker网络
简介
- 本机回环地址
- 腾讯云内网地址
- docker0地址
docker是如果处理容器网络访问的?
启动tomcat容器\
docker run -d -P --name tomcat01 tomcat
查看容器内IP
90:eth0if91
再次查看主机IP
91:eth0if90
再启动一个tomcat02
启动tomcat容器\
docker run -d -P --name tomcat02 tomcat
发现,又多了一对网卡。veth-pair就是一对的虚拟设备接口,一段连着协议,一段彼此相连。正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟网络设备。
docker使用的是linux的桥接,宿主机中是一个docker容器的网桥docker0,docker中所有的网络接口都是虚拟的。只要容器删除,对应的网桥就会消失。
容器互联--link
tomcat02 直接ping tomcat01失败
--link\
docker run -d -P --name tomcat03 --link tomcat02 tomcat
\
成功\
docker exec -it tomcat03 ping tomcat02
\
失败\
docker exec -it tomcat02 ping tomcat03\
查看tomcat03容器的hosts
--link就是再hosts配置中增加了tomcat02的ip地址
(docker现在已经不建议使用--link)
自定义网络
查看所有网络\
docker network ls
网络模式
bridge:桥接(docker默认)
none:不配置网络
host:和宿主机共享网络
container:容器网络互连(用的少,局限性大)
测试
直接启动的命令 --net bridge,而这个就是我们的docker0\
docker run -d -P --name tomcat01 --net bridge tomcat\
docker0特点:默认;域名不能访问;可以使用--link打通连接\
\
可以自定义网络\
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
将tomcat-net-01、tomcat-net-02放在mynet中\
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
\
查看mynet网络元数据\
docker network inspect mynet\
测试容器网络互联\
docker exec -it tomcat-net-01 ping tomcat-net-02
docker exec -it tomcat-net-02 ping tomcat-net-01\
都成功,自定义网络可以直接ping容器名
网络连通
再创建一个tomcat01\
。。。\
将tomcat01与mynet连通(一个容器两个ip)\
docker network connect mynet tomcat01