概述
Docker 为什么出现
- 部署环境太过麻烦,容易出现开发和生产不一致
- 通过将项目和环境进行统一打包,在服务器上可以自动部署相同环境和项目
Docker 与 虚拟机
- 虚拟机:
- 虚拟一台完整电脑!笨重!
- Docker:
- 所有容器使用同一个操作系统内核(基于Docker安装的所在系统)
- 应用运行在不同容器中,相互独立
- 每个容器都有自己的系统环境文件
Docker 作用
- 打包镜像发布测试,一键运行
- 不同服务的环境高度一致
- 内核级别虚拟化,可以运行多个容器实例,性能高
Docker 组成
- 镜像(image):
- Docker 镜像就好比是模板,通过这个模板可以创建多个容器(与操作系统镜像同理)
- 容器(container):
- Docker 容器,就好比是一个独立的操作系统,应用就运行在容器中
- 通过镜像创建的容器只包含了应用和应用所需的环境,操作系统内核还是使用的 Docker 所在的操作系统内核。
- 仓库(registry):
安装
Linux
- 从 Docker 仓库安装
- Docker 引擎官方文档:(ubuntu)https://docs.docker.com/engine/install/ubuntu/
- 卸载旧版本:
1
| sudo apt-get remove docker docker-engine docker.io containerd runc
|
- 更新软件包
- 安装软件包
1 2 3 4 5
| sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release
|
- 添加 Docker 的官方 GPG 密钥
1 2
| sudo mkdir -m 0755 -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
- 设置 Docker 仓库
1 2 3
| echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
- 更新软件包
- 安装 Docker Engine、containerd 和 Docker Compose
1
| sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
- 查看 Docker 版本信息
原理
底层原理
- Docker 是一个 Client-Server 结(C/S)构的系统
- Docker 的守护进程运行在主机上,通过 Socket 从客户端访问(守护进程:在后台运行的特殊进程,很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭)
- Docker-Server 接收到 Docker-Client 指令,就会执行这个命令
镜像原理
镜像是什么
- 镜像是一个 独立软件包 ,包含某个软件所需要的所有内容,包括代码、运行时的库、环境变量和配置文件
UnionFS(联合文件系统)
Union文件系统(UnionFS),是一种分层、可移植并且高性能的文件系统。
- 文件系统:每个程序的相关文件就称为一个文件系统
- 统一管理:同时管理多个文件系统,不同容器使用相同文件系统可以进行复用(下载时不会下载),减少资源消耗
- 联合挂载:他可以将多个文件系统层叠在一起(一层一层往上加),挂载到统一目录下,作为容器的完整文件系统(联合挂载点)
- 容器包含
- 一个基础镜像层(包含操作系统的文件系统和一些基础的工具和应用程序)
- 其他镜像层
- 增量层(容器中新增的文件和目录)
镜像加载原理
镜像的加载是分层进行加载的,按照联合文件系统规则,将不同文件系统进行分批下载层叠起来,最终形成所需的完整文件系统
镜像运行的流程
命令
参考文档:https://docs.docker.com/reference/
帮助命令
1 2 3
| docker version # 显示 docker 的版本信息 docker info # 显示 docker 的系统信息,包括镜像和容器数量 docker [命令] --help # 帮助命令
|
镜像命令
本地查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker images # 查看本地主机上的镜像
# 列名解释 REPOSITORY # 镜像的仓库源 TAG # 镜像的标签 IMAGE ID # 镜像的id CREATED # 镜像的创建时间 SIZE # 镜像的大小
# 可选参数 -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像的id
|
仓库搜索
1 2 3 4
| docker search [镜像名] # 在 docker 仓库中搜索镜像
# 可选参数 docker search [镜像名] --filter=STARS=3000 # 搜索镜像 STARS 大于 3000 的
|
下载镜像
1 2 3 4 5 6
| docker pull [镜像名] # 下载镜像 docker pull [镜像地址] # 下载镜像
# 可选参数 docker pull [镜像名] [:版本号] # 下载指定版本镜像
|
删除镜像
1 2 3
| docker rmi -f [容器id] # 删除指定镜像 docker rmi -f [容器id_1] [容器id_2] # 删除多个镜像 docker rmi -f $(dockeer images -aq) # 删除所有镜像
|
容器命令
新建容器、启动
- 使用 -d 后台运行方式,必须要有一个前台进程,docker 没有发现应用,就会自动停止
- nginx 容器启动后,发现自己没有提供服务,就会立即停止,就是没有程序了
1 2 3 4 5 6 7 8 9 10 11
| docker run [可选参数] [镜像名] [命令]
# 可选参数 --name="容器名" # 容器名字 -d # 后台方式运行,不会进入容器,不能交互(常用于在容器内部运行长期任务或守护进程,容器中运行了命令后立即返回主机命令行) -it [容器名] [执行的shell] # 使用交互方式创建容器,会进入容器,可进行交互(可以和容器进行交互,常用于进入容器内部进行操作,如在容器中启动 Bash Shell) -p(大写) # 指定容器端口 [-p 主机端口:容器端口] [-P ip:主机端口:容器端口] [-P 容器端口] -P(小写) # 随机指定端口 --rm # 容器退出时删除容器 -e ["环境变量名=环境变量值"] # 设置容器的环境变量 -v [linux目录地址:容器中目录地址] # 将容器中的目录同步到 linux 服务器对应目录上,在 linux 上即可修改容器中文件
|
进入正在运行的容器
1 2
| docker exec -it [容器id] [/bin/bash] # 进入正在运行的容器,并开启一个新的终端(常用) docker attach [容器id] # 进入正在运行的容器,打开正在执行的终端(如果容器没有运行的终端,就无法进入)
|
修改容器名称
1
| docker rename [旧容器名称] [新容器名称] # 修改容器名称
|
从容器中拷贝文件到主机
1
| docker cp [容器id] : [容器内路径] [目的地主机路径] # 从容器中拷贝文件到主机(从主机端进行执行)
|
退出容器
1 2
| exit # 停止容器并退出 ctrl + p + q # 容器不停止,退出
|
查看运行容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| --------------start------------------------------------ docker ps # 列出所有正在运行的容器
# 可选参数 -a # 列出停止的容器和正在运行的容器(所有容器) -n=[数字] # 列出最近创建的n个容器 -q # 只显示编号 ---------------end-------------------------------------
---------------start----------------------------------- docker container ls # 列出所有正在运行的容器(有更多参数和选项)
# 可选参数 -a # 列出停止的容器和正在运行的容器(所有容器) ---------------end-------------------------------------
|
删除容器
1 2
| docker rm [容器id] # 删除指定容器(不能删除运行中的容器,强制删除用 -f) docker rm -f $(docker ps -aq) # 删除所有容器
|
启动、停止容器
1 2 3 4
| docker start [容器id] # 启动容器 docker restart [容器id] # 重启容器 docker stop [容器id] # 停止当前正在运行容器 docker kill [容器id] # 强制停止当前正在运行容器
|
提交容器
1
| docker commit -a="用户名" -m="描述信息" [容器id] [镜像别名:版本号] # 将运行的容器提交成为一个镜像
|
查看容器数据卷
1 2
| docker volume ls # 查看 linux 服务器中容器挂载的所有数据卷 docker volume inspect 数据卷名 # 查看 linux 服务器中容器挂载数据卷的信息
|
操作命令
查看容器日志
1 2
| docker logs -f -t [容器id] # 查看全部日志 docker logs -f -t --tail [日志数量] [容器id] # 查看最近数量日志
|
查看容器内存
1 2
| docker stats # 查看各容器当前所占内存 docker stats [容器id] # 查看指定容器当前所占内存
|
查看容器进程
1
| docker top [容器id] # 查看容器所有进程
|
查看容器的相关数据
1
| docker inspect [容器id] # 查看容器的镜像配置信息
|
容器数据卷
- 名词解释【数据卷】:数据卷通常指的是一个独立的存储设备或分区,可以将数据从应用程序和主机系统中分离开来,实现数据在不同环境和应用程序之间的共享和传递。
- 作用:将数据与容器进行分离,实现数据的共享
- 原理:将容器内的目录同步到 Linux 服务器上对应目录,修改 linux 对应目录内容,容器中对应目录也改变
- 容器删除挂载到本地的数据卷将不受影响
指定数据卷位置
1 2
| docker run -it -v linux目录地址:容器中目录地址 镜像名 /bin/bash # 将容器内的目录同步到 Linux 服务器上对应目录 docker run -it -v linux目录地址:容器中目录地址 -v linux目录2:容器中目录2 镜像名 /bin/bash # 同时挂载多个目录
|
默认数据卷位置
说明:默认不指定 linux 服务器中挂载容器数据卷的位置,其数据卷默认放置在 /var/lib/docker/volumes/数据卷名/_data
1 2
| docker run -d -v 容器中目录地址 镜像名 # 【匿名挂载】将容器数据卷挂载到 linux 中默认位置,但是卷名是一串不可读字符 docker run -d -v 卷名:容器中目录地址 镜像名 # 【具名挂载】将容器数据卷挂载到 linux 中默认位置,可以通过卷名查看数据卷信息
|
设置容器对卷的权限
1 2
| docker run -d -v 卷名:容器中目录地址:ro 镜像名 # 【ro】容器只读卷内容 docker run -d -v 卷名:容器中目录地址:rw 镜像名 # 【rw】容器可读可写卷内容
|
数据卷容器
说明
- 数据卷容器本身不会存储数据,但它会将一个或多个数据卷挂载到容器中,从而实现容器与主机之间的数据共享。
- 当其他容器通过挂载这些数据卷来访问这些数据时,实际上是访问了这个数据卷容器中挂载的卷中的数据。
- 数据卷容器的作用是管理这些数据卷,包括创建、删除和管理数据卷的生命周期。
- 因此,删除数据卷容器不会影响已经挂载了这些数据卷的其他容器。
用法
- 容器挂载了数据卷(挂载方式同上)
- 创建其他容器时,使用目标容器上挂载的数据卷【目标容器就是数据卷容器】
1 2
| docker run -it --name docker01 -v test 镜像名 # 新建容器 docker01 ,容器中 test 目录挂载匿名数据卷 docker run -it --name docker02 --volumes-from docker01 镜像名 # 新建容器 docker02 , docker02 在容器中创建与 docker01 相同目录,并挂载同一数据卷
|
DockerFile
dockerFile 是一种文本格式的脚本文件,用于构建 Docker 镜像。
编写 dockerfile 的指令
指令都需要大写
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| FROM # 基础镜像,构建新镜像所基于的基础镜像 MAINTAINER # 镜像是谁写的,姓名+邮箱 RUN # 镜像构建的时候需要运行的命令 ADD # 复制文件,用来将构建环境(linux服务器)中的文件复制到镜像中,可以自动解压缩 tar 包(如jdk/tomcat压缩包) COPY # 复制文件,和 ADD 类似,但是不会自动解压缩 WORKDIR # 工作目录,用来指定容器中的工作目录【工作目录:在此目录下执行命令或程序,这个目录就叫工作目录】 VOLUME # 给容器挂载数据卷,将容器中的目录挂载到主机上 EXPOSE # 容器对外开放的端口,用来指定容器运行时需要对外开放的端口 CMD # 容器启动时要运行的命【如果 Dockerfile 中有多个 CMD 指令,则只有最后一个生效】【docker run 命令中提供了命令,那么新命令会覆盖 CMD 定义命令的命令】 ENTRYPOINT # 容器启动时要运行的命令【如果 Dockerfile 中有多个 ENTRYPOINT 指令,则只有最后一个生效】【docker run 命令中提供了新命令,那么新命令会追加到 ENTRYPOINT 定义命令之后执行】 ONBUILD # 构架一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令。触发指令 ENV # 环境变量,用来设置容器中的环境变量 USER # 指定用户,用来指定在容器中执行命令时使用的用户名或 UID ARG # 参数,用来在构建镜像时传递参数,可以在构建过程中使用这些参数
|
通过 dockerfile 创建镜像指令
如果 dockerfile 文件名定义为 Dockerfile 则在工作目录构建镜像时,不需要指定 dockerfile文件名
1
| docker build -f dockerfile文件名 -t 镜像名[:版本号] . # 注意最后有一个点 .
|
查看镜像的构建流程
1
| docker history 镜像名id(名) # 可以查看镜像的构建顺序
|
发布镜像
发布到 DockerHub
- DockerHub 注册账号 https://hub.docker.com/
- linux 登录 DockerHub
1
| docker login -u 用户名 # 输入用户名登录
|
- 提交镜像
1
| docker push 自定义镜像名[:版本号] # 命名规则 【用户名/自定义镜像名:版本号】
|
- 退出登录
docker logout
发布到阿里云镜像服务
- 登录阿里云 https://www.aliyun.com/
- 目录
- 产品
- 容器与中间件
- 容器镜像服务 ACR
- 管理控制台
- 个人实例
- 镜像仓库
- 创建镜像仓库
- 根据创建的仓库下操作指南,登录和提交镜像
打包镜像(离线版)
将 Docker 镜像保存到本地文件中,以及从本地文件中加载 Docker 镜像
1 2
| docker save -o 地址/压缩包名.tar 镜像名:版本号 # 将镜像打包到指定压缩包 docker load -i 压缩包名.tar # 从压缩包中添加 docker 镜像
|
Docker网络
原理
容器间和宿主主机可以相互通信
- docker 容器和宿主主机之间可以相互 ping 通
- docker 容器之间也可以相互通信
容器间通信的原理
docker 容器之间可以相互通信的原理,是使用了 veth-pair 技术
veth-pair:成对 的虚拟以太网设备(Virtual Ethernet Device),其中一个设备连接到 Linux 系统的网络命名空间中,另一个设备则连接到另一个网络命名空间中。这使得两个网络命名空间之间可以进行通信。
网络命名空间:每一个网络命名空间都有自己独立的网络资源,互相之间隔离,就像在不同的主机上一样。
- linux 上安装好了docker之后,linux 就会有一个
docker0 的虚拟网桥,该网桥连接了主机上的物理网卡和所有运行的 Docker 容器。【网桥:用于连接多个网络,实现不同网络间的数据转发】
- 容器实例化之后,容器内会有一个
虚拟网卡 veth1-1,同时宿主主机 linux 上也会新添一个 虚拟网卡 veth1-2,这两个网卡是通过 veth-pair 技术实现的,因此两个网卡可以相互通信
虚拟网卡 veth1-2 通过 docker0 虚拟网桥 可以与宿主主机linux物理网卡进行通信。
- 其他 docker 容器在宿主主机上生成的
虚拟网卡 veth,通过 docker0 虚拟网桥 可以相互通信,信息再通过 veth-pair 传输到容器中
- 容器删除后,相关的
veth-pair 都会自动删除
- -link
- 作用:不通过ip,使用容器名进行数据传输或ping
- 原理:在容器1中修改host文件,将向容器名2的请求,转发到容器2的ip
- 已经不建议使用
1 2
| docker run -d -P --name 容器名1 --link 容器名2 镜像名 # 配置通过容器名进行数据传输 docker exec -it 容器名1 ping 容器名2 # 测试传输数据【成功】
|
自定义网络
优势:
- 同一网络下的容器可以相互通信
- 通信方式可以直接使用容器名,不用使用IP
1 2
| docker network ls # 查看所有网络 docker network inspect 网络名 # 查看网络的配置信息
|
1 2 3 4
| # 容器使用指定网络 docker run -d --name 容器名 镜像名 # 启动容器默认使用 bridge 网络【如下】 docker run -d --name 容器名 --net bridge 镜像名 # 等同于不指定网络的默认启动方式【如上】【宿主主机默认网络名 bridge】 docker run -d --name 容器名 --net 网络名 镜像名 # 使用自定义网络
|
1 2 3 4 5 6 7 8 9 10 11 12
| # 创建网络 docker network create --driver bridge(网络模式) --subnet 192.168.0.0/16 --gateway 192.168.0.1 网络名称
# 参数说明 --subnet # 定义子网范围 【192.168.0.0/16】192.168.0.0——192.168.255.255 --gateway # 定义网关
# 网络模式 bridge # 桥接模式(默认) none # 不配置网络 host # 和linux共享网络 container # 容器间网络连通(用的少)
|
网络连通
作用:一个网络中的容器,希望与另一个网络的容器通信
原理:给容器配置另一个网络,即:一个容器配置两个或多个不同网段的IP
1
| docker network connect 网络名 容器名 # 将容器添加到新网络中
|
Docker Compose
Docker Swarm
CI/CD Jenkins