docker
Docker为什么会出现
开发-上线,两套环境
而环境配置是十分麻烦的,实现开发即运维,将环境直接打包在一起,这样就不需要重新配置环境
类比软件安装:java - apk - 发布(应用商店) - 下载安装 - 使用apk
Docker使用:java - jar(环境) - 打包项目带上环境(镜像) - (Docker仓库:商店) - 下载镜像 - 直接运行即可!
Docker的思想来自于集装箱!
JRE - 多个应用(端口冲突) - 原来都是交叉的!
隔离:Docker核心思想!打包装箱!每个箱子都是隔离的
比如:水果和生化武器
Docker通过隔离机制,可以将服务器利用到极致!
与虚拟机区别
虚拟机:在window中装一个Wmware,通过这个软件我们可以虚拟化出来一台或者多台电脑!笨重!
虚拟机缺点:资源占用十分多;冗余步骤多;启动很慢;
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
容器化技术不是模拟一个完整的操作系统,Docker镜像小巧,且秒级启动
比较Docker和虚拟机:
- 传统虚拟机,虚拟出一种硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器 是将应用直接运行在宿主机的内核上,没有自己的内核,也没有虚拟硬件,所以更加轻便
- 每个容器间是相互隔离的,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
-
应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
-
更便捷的升级和扩缩容
使用Docker后,我们部署应用就和搭积木一样
-
更简单的系统运维
-
更高效的计算资源利用
一个物理机上可以运行很多的容器实例
Docker基本组成
镜像(image):好比一个模板,可以通过这个模板创建容器
容器(container):在容器上可以独立运行一个或者一组应用
仓库(repository):存放镜像的地方!分为公有仓库和私有仓库
安装
Docker Documentation 官方文档非常详细!
docker run hello-world
- 在本机寻找hello-world镜象
- 本机没找到就从doker hub上下载
- 下载镜像到本地进行运行
Docker是怎么工作的?
Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问
DockerServer接收到Docker-Client的指令,就会执行这个命令
Docker常用命令

docker version # 显示docker的版本信息
docker info # 显示docker的系统信息,包括镜像和容器数量
docker 命令 --help # 帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/run/
镜像命令
docker images:查看镜像,-aq:只显示所有镜像的镜像id
docker search 镜像名:搜索镜像,相当于在docker hub上搜索,--filter=STARS=3000:搜索STARS大于等于3000的
docker pull 镜像名:下载镜像,默认下载最新版,可以通过docker pull 镜像名[:tag]指定下载版本
docker rmi -f 镜像id:通过镜像id删除某个镜像
docker rmi -f 镜像id 镜像id 镜像id:通过镜像id删除多个镜像
docker rmi -f $(docker images -aq):删除全部镜像
容器命令
说明:有了镜像才可以创建容器,所以首先需要下载一个centos镜像
docker pull centos
新建容器并启动
docker run [可选参数] image
# 参数说明
# --name="name":容器名字,用来区分容器
# -d :后台方式运行
# -it:使用交互方式运行,进入容器查看内容,/bin/bash,内部很多内容都是不完善的
# -p:指定容器的端口,如8080:8080
# -P:随机指定端口
查看容器
docker ps # 查看正在运行的容器
docker ps -a # 查看运行过的所有容器
docker ps -aq # 查看运行过的所有容器id
docker ps -n=1 # 查看最近创建的一个容器
退出容器
exit # 停止容器并退出
Ctrl + P + Q # 不停止容器并退出
删除容器
docker rm 容器id # 通过容器id删除指定容器,不能删除正在运行的容器
docker rm -f 容器id # 强制删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有容器
启动和停止容器
docker start 容器id # 启动容器
docker reatart 容器id # 重启容器
docker stop 容器id # 停止容器
docker kill 容器id # 强制停止容器
一些其他常用命令
后台启动容器
docker run -d 镜像名
问题:通过 docker run -d 镜像名 来启动容器后,然后发现容器停止了
坑:docker容器要通过使用后台运行,就必须要有一个前台进程!因为如果docker发现容器中没有正在运行的应用,就会自动停止容器
查看日志
docker logs -f -t --tail 10 容器id
查看容器中的进程信息
docker top 容器id
查看容器的元数据
docker inspect 容器id
进入当前正在运行的容器
docker exec -it 容器id /bin/bash # 进入容器后开启新的终端(常用)
docker attach 容器id # 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
只要容器在,容器内的文件就存在,与容器正在运行与否无关!
拷贝是一个手动过程,可以使用 -v 卷的技术实现自动同步
Docker镜像加载原理
联合文件系统(UnionFS)
UnionFS是一种分层、轻量级并且高性能的文件系统,它支持 对文件系统的修改 作为一次提交来一层层叠加,同时可以挂载到同一个虚拟文件系统下
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,UnionFS会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
-
bootfs(boot file system) 主要包含bootloader和kernel,bootloader主要用来引导加载kernel,加载完成后,内存的使用权交给内核,此时系统也会卸载bootfs
-
rootfs(root file system),在bootfs之上,就是典型的Linux系统目录(/dev,/etc等)
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库,因为底层直接用Host的kernel,自己只需要提供rootfs
容器数据卷
什么是容器数据卷?
如果数据都在容器中,那么容器删除,数据就会丢失!
需求:数据可以持久化
需要容器之间有一个数据共享的技术!Docker容器中产生的数据,同步到本地!这就是卷技术,将容器内的目录挂载到Linux
总结:为了容器的持久化和同步操作,容器间也是可以数据共享的
使用数据卷
方式一:直接使用命令来挂载 -v
1)同时指定主机目录和容器目录
docker run -it -v 主机目录:容器内目录 容器id /bin/bash
挂载后通过docker inspect 容器id可以查看挂载信息,具体地,“Mounts”中“Source”为主机内地址,“Destination”为容器内地址
2)不指定主机目录,具名挂载和匿名挂载
docker run -it -v 容器内目录 容器id /bin/bash # 匿名挂载
docker run -it -v 卷名:容器内目录 容器id /bin/bash # 具名挂载
docker volume ls # 查看所有的卷,没有名字的就叫做匿名卷,即匿名挂载
docker volume inspect 卷名 # 查看卷的详细信息,发现挂载目录默认为"/var/lib/docker/volume/卷名/_data"
平时主要使用具名挂载,一般不使用匿名挂载
# 如何判断是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
# 通过 -v 容器内路径:ro/rw 改变读写权限
# ro(readonly):只读,只能通过宿主机操作,容器内部是无法操作的
# rw(readwrite):可读可写
docker run -it -v 主机目录:容器内目录:ro/rw 容器id /bin/bash
方式二:通过Dockerfile挂载
VOLUME ["volume01","volume02"] # 两个"volume01","volume02"匿名挂载卷
然后通过docker inspect 容器id就可以查看挂载信息
这种方式使用的非常多,因为我们通常会构建自己的镜像,如果没有在构建镜像时挂载,就需要手动使用-v命令挂载
数据卷容器
实现容器间的数据共享:--volumes-from 数据卷容器
删除容器,但是只要存在一个容器,数据就不会丢失,这类似一种备份机制
- 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止
- 但是一旦持久化了本地,这个时候,本地的数据是不会删除的
Dockerfile
Dockerfile就是用来构建docker镜像的命令脚本
镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层
脚本文件名建议为Dockerfile
构建步骤:
- 编写一个Dockerfile文件
docker build构建一个镜像docker run运行镜像docker push发布镜像(DockerHub、阿里云镜像仓库)
官方镜像很多都是基础包,很多功能没有,我们通常会自己搭建自己的镜像
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 从上到下顺序执行
#表示注释- 每一个指令都会创建 提交一个新的镜像层
FROM # 基础镜像,一切从这里开始
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT # 指定容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 Dockerfile 时运行,是一个触法指令,了解即可
COPY # 类似ADD,将文件拷贝到镜像中
ENV # 构建时设置环境变量
网络
docker0
宿主机 是能 ping 通容器的
容器间公用一个路由器 docker0(宿主机),所有容器不指定网络的情况下,都是 docker0 路由的,docker会给容器分配一个默认的可用IP

-
Docker使用的是Linux的桥接,宿主机
docker0是Docker容器的网桥 -
Docker中所有的网络接口都是虚拟的,这样转发效率高(内网传递文件)
-
只要容器删除,对应的一对网桥就没了
--link
--link:容器间使用 服务名替代IP 来解决网络连通问题,注意这个是单向的,反向也需要配置
--link操作其实是在hosts配置文件中增加了相应容器服务的配置
现在已经不建议使用--link了,高手都是自定义网络!
docker0存在的问题:它不支持容器名连接访问
自定义网络
通过docker network ls查看所有的Docker网络
网络模式
-
bridge:桥接,Docker(默认,就是上边说的docker0的方式,自定义网络也使用bridge模式)
-
none:不配置网络
-
host:和宿主机共享网络
-
container:容器网络连通(用得少!局限很大)
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
我们自定义的网络Docker都已经帮我们维护好了对应关系,推荐这样使用网络
好处:不同的集群使用不同的网络,保证集群是安全和健康的
网络连通
两个网络下的容器之间是不可以 ping 通的,因为是在两个网段下
docker network connect:连接一个容器到一个网络
连通后就是把容器放到了网络下
原理:一个容器两个ip,比如阿里云服务的公网ip和私网ip都可以访问
结论:假设要跨网络操作别人,就需要使用connect进行连通

浙公网安备 33010602011771号