Docker简介
- Docker 是一个应用打包、分发、部署的工具,可以使应用部署更加轻量,可移植,可扩展,可以理解为一个轻量的虚拟机
- 打包:就是把你软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包
- 分发:你可以把你打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装
- 部署:拿着“安装包”就可以一个命令运行起来应用,自动模拟出一模一样的运行环境,不管是在Windows/Mac/Linux
- docker架构图
- docker client: 即docker命令行工具
- docker host: 宿主机,docker daemon的运行环境服务器
- docker daemon: docker的守护进程,docker client通过命令行与docker daemon交互
- image: 镜像,可以理解为安装包,可以方便的进行传播和安装
- container: 容器,镜像的运行实例,每个软件运行环境都是独立的,隔离的
- registry: 镜像仓库,可以从镜像仓库拉取和推送镜像
底层原理
docker底层使用了一些linux内核的特性,namespace
,cgroups
,unionFS
namespace
- namespace,也叫命名空间,名称空间,它表示一个标识符的可见范围。一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。这样,在一个新的名字空间中可定义任何标识符,它不会与任何已有的标识符发生冲突,因为已有的定义都处于其他命名空间中
- docker使用linux namespace构建隔离的环境,它由以下namespace组成
- pid:隔离进程
- net:隔离网络
- ipc:隔离IPC
- mnt:隔离文件系统挂载
- uts:隔离hostname
- user:隔离uid/gid
cgroups
- cgroups,是控制组群(control groups)的简写,是用来限制、控制与分离一个进程组的资源(如CPU、内存、磁盘输入输出等)
- cgroups功能:
- 资源限制:设置内存限制,包括虚拟内存
- 优先级:一些资源可以得到大量的CPU或磁盘IO吞吐量
- 结算:用来度量系统实际用了多少资源
- 控制:冻结组或检查点和重启动
unionFS
- unionFS(Union file systems)是一种分层、轻量级并且高性能的文件性能,支持对文件系统的修改作为一次提交来一层层的叠加。docker的镜像与容器就是分层存储,可用的存储引擎呦aufs,overlay等
镜像
- 镜像是一份用来创造容器的配置文件,而容器可以视作最小型的一个操作系统
- docker的镜像和容器都使用了unionFS做分层存储,镜像作为只读层是共享的,而容器在镜像之上附加了一层可写层,最大程度地减少了空间的浪费
- 镜像的相关命令
- 镜像拉取:
docker pull node:alpine
- 查看镜像信息:
docker inspect node:alpine
- 列出所有镜像:
docker images
- 镜像打包:
docker build -t docker-app:v1.0.0
-t
:设置镜像名字和版本号
- 镜像拉取:
Dockerfile
- Dockerfile是docker构建镜像的配置文件,比如一个简单的Dockerfile如下
FROM node:16 MAINTAINER songlh ADD . /app WORKDIR /app RUN npm install pnpm -g RUN pnpm install CMD pnpm run dev
- 常用指令
FROM
:表示基于一个已有的基础镜像,FROM <image> [AS <name>]
MAINTAINER
:声明dockerfile镜像构建的作者ADD
:表示把宿主机的文件或目录加入到镜像的文件系统,ADD [--chown=<user>:<group>] <src>... <dest>
RUN
: 在镜像中执行命令,由于ufs的文件系统,它会在当前镜像的顶层新增一层,RUN <command>
CMD
: 指定容器如何启动,一个Dockerfile中只允许有一个CMDWORKDIR
:设置工作目录ENV
:设置环境变量
容器
docker run
:创建容器docker run -p 8080:8080 --name docker-hello docker-app:v1.0.0
表示基于docker-app镜像的v1.0.0版本创建一个容器并在本地的8080端口运行,容器名字叫docker-hellp
-p host-port:container-port
:宿主机与容器端口映射,方便容器对外提供服务--name
:为容器指定名称-d
:后台运行--rm
:当停止容器时自动清除容器
docker stop
:停止容器docker rm
:删除容器docker exec -it container-name
:进入容器环境docker ps
:列出所有容器docker port
:查看容器端口映射docker stats
:查看容器资源占用
目录挂载
- 按照目前已有知识,如果改了项目代码不会立刻生效,需要重新build和run,很麻烦,而且容器产生的数据,如果容器删除了就会没有,目录挂载就是为了解决这些问题
- 目前的挂载方式
bind mount
:直接把宿主机目录映射到容器内,适合挂载代码目录和配置文件,可挂载到多个容器上volume
:由容器创建和管理,创建在宿主机,所以删除容器不会丢失,官方推荐,更高效,Linux文件系统,适合存储数据库数据。可挂载到多个容器上tmpfs mount
:适合存储临时文件,存储在宿主机内存中。不可多容器共享
bind mount
bind mount
是通过-v
参数来绑定宿主机目录,比如将外部的html文档挂载到Nginx容器的根目录下docker run -v ~/html:/usr/share/nginx/html -p 81:80 -d --name nginx_bind nginx:latest
- 这种方式的缺点就是被挂载的宿主机目录(或文件)不受保护,任何容器都可以随意修改
volume
- volume也是一个文件,但是这个文件是在docker的管控范围内,docker可以通过挂载的设定来控制容器对volume的读写权限
- 通过
docker volume create volume-name
创建一个Volume,实际上是在docker的/var/lib/docker/volumes/
文件夹内创建一个相同名字的文件夹来保存数据 - 比如设置一个只能读取volume
docker run --mount type=volume,source=nginx-volume,destination=/usr/share/nginx/html,readonly -p 82:80 -d --name nginx_volume nginx:latest
tmpfs mount
- tmpfs挂载是临时的,仅保留在主机内存中。当容器停止时,tmpfs挂载被移除,写入的文件不会被持久化
docker run --mount type=tmpfs,destination=/usr/share/nginx/html -p 83:80 -d --name nginx-tempfs nginx:latest
- tmpfs因为不是持久化,一般不使用
容器通信
- 容器间的通信根据媒介可以分为:volume共享通信、网络通信
- 根据通信范围可以分为:同主机通信、跨主机通信
网络通信
- Docker的网络通信模型分为以下几种,在安装Docker以后,会默认创建三种网络,可以通过
docker network ls
查看- bridge:为每一个容器分配、设置IP等,并将容器连接到一个
docker0
虚拟网桥,默认为该模式 - host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
- none:容器有独立的
network namespace
,但并没有对其进行任何网络设置,如分配veth pair
和网桥连接,IP等 - overlay:可以连接多个docker守护进程或者满足集群服务之间的通信,适用于不同宿主机上的docker容器之间的通信
- macvlan: 可以为docker容器分配MAC地址,使其像真实的物理及一样运行
- bridge:为每一个容器分配、设置IP等,并将容器连接到一个
- Docker内置的
bridge network
,也就是docker0接口所属的network,所有未指定network的容器,默认连接到此network中,其网段未172.17.0.1/16
,所以两个未进行任何连接操作的容器是可以通过IP地址互相通信的,因为他们同在一个network下,但通信只能通过IP地址进行,不可以通过容器名通信 - 创建自定义网络:
docker network create custom_network
- 查看网络模式:
docker network ls
- 通过自定义网络创建容器:
docker run -di --name docker-app --net custom_network docker-app:v1.0.0
- 查看容器的网络信息:
docker inspect 容器名称|ID
,然后在NetworkSettings
节点中可以看到 - 为容器连接新的网络:
docker network connect 网络名称 容器名称
- 断开网络:
docker network disconnect 网络名称 容器名称
docker-compose
- docker-compose是用于定义和运行多容器Docker应用程序的工具。通过compose,您可以使用YML文件来配置应用程序需要的所有服务,然后使用一个命令就可以从YML文件配置中创建并启动所有服务
- 使用分三步
- 使用Dockerfile定义应用程序的环境
- 使用docker-compose.yml定义构成应用程序的服务,这样它们可以在隔离环境中一起运行
- 最后,执行docker-compose up命令启动并运行整个应用程序
- 比如运行一个web项目和redis,可以编写一个如下的
docker-compose.yml
文件version: "3" services: app: build: ./ ports: - 80:8080 volumes: - ./:/app redis: image: redis:5.0.13 volumes: - redis:/data volumes: redis:
- version:指定本yml依从的compose哪个版本指定的
- build: 指定构建镜像上下文路径
- image:指定启动容器的镜像
- volumes:卷挂载路径设置,如果跨多个服务并重用挂载卷,可以在volumes关键字中命名挂载卷
- ports:暴露端口信息