概述

Docker 为什么出现

  1. 部署环境太过麻烦,容易出现开发和生产不一致
  2. 通过将项目和环境进行统一打包,在服务器上可以自动部署相同环境和项目

Docker 与 虚拟机

  1. 虚拟机:
    1. 虚拟一台完整电脑!笨重!
  2. Docker:
    1. 所有容器使用同一个操作系统内核(基于Docker安装的所在系统)
    2. 应用运行在不同容器中,相互独立
    3. 每个容器都有自己的系统环境文件

Docker 作用

  1. 打包镜像发布测试,一键运行
  2. 不同服务的环境高度一致
  3. 内核级别虚拟化,可以运行多个容器实例,性能高

Docker 组成

  1. 镜像(image):
    • Docker 镜像就好比是模板,通过这个模板可以创建多个容器(与操作系统镜像同理)
  2. 容器(container):
    1. Docker 容器,就好比是一个独立的操作系统,应用就运行在容器中
    2. 通过镜像创建的容器只包含了应用和应用所需的环境,操作系统内核还是使用的 Docker 所在的操作系统内核。
  3. 仓库(registry):
    • 存放镜像的地方,类似于 github

安装


Linux

  1. 从 Docker 仓库安装
  2. Docker 引擎官方文档:(ubuntu)https://docs.docker.com/engine/install/ubuntu/
  3. 卸载旧版本:
    1
    sudo apt-get remove docker docker-engine docker.io containerd runc
  4. 更新软件包
    1
    sudo apt-get update
  5. 安装软件包
    1
    2
    3
    4
    5
    sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
  6. 添加 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
  7. 设置 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
  8. 更新软件包
    1
    sudo apt-get update
  9. 安装 Docker Engine、containerd 和 Docker Compose
    1
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  10. 查看 Docker 版本信息
    1
    docker version

原理


底层原理

  1. Docker 是一个 Client-Server 结(C/S)构的系统
  2. Docker 的守护进程运行在主机上,通过 Socket 从客户端访问(守护进程:在后台运行的特殊进程,很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭)
  3. Docker-Server 接收到 Docker-Client 指令,就会执行这个命令

镜像原理


镜像是什么

  • 镜像是一个 独立软件包 ,包含某个软件所需要的所有内容,包括代码、运行时的库、环境变量和配置文件

UnionFS(联合文件系统)

Union文件系统(UnionFS),是一种分层、可移植并且高性能的文件系统。

  1. 文件系统:每个程序的相关文件就称为一个文件系统
  2. 统一管理:同时管理多个文件系统,不同容器使用相同文件系统可以进行复用(下载时不会下载),减少资源消耗
  3. 联合挂载:他可以将多个文件系统层叠在一起(一层一层往上加),挂载到统一目录下,作为容器的完整文件系统(联合挂载点)
  4. 容器包含
    1. 一个基础镜像层(包含操作系统的文件系统和一些基础的工具和应用程序)
    2. 其他镜像层
    3. 增量层(容器中新增的文件和目录)

镜像加载原理

镜像的加载是分层进行加载的,按照联合文件系统规则,将不同文件系统进行分批下载层叠起来,最终形成所需的完整文件系统


镜像运行的流程



命令

参考文档: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]     # 查看容器的镜像配置信息


容器数据卷

  1. 名词解释【数据卷】:数据卷通常指的是一个独立的存储设备或分区,可以将数据从应用程序和主机系统中分离开来,实现数据在不同环境和应用程序之间的共享和传递。
  2. 作用:将数据与容器进行分离,实现数据的共享
  3. 原理:将容器内的目录同步到 Linux 服务器上对应目录,修改 linux 对应目录内容,容器中对应目录也改变
  4. 容器删除挂载到本地的数据卷将不受影响

指定数据卷位置

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. 当其他容器通过挂载这些数据卷来访问这些数据时,实际上是访问了这个数据卷容器中挂载的卷中的数据。
  3. 数据卷容器的作用是管理这些数据卷,包括创建、删除和管理数据卷的生命周期。
  4. 因此,删除数据卷容器不会影响已经挂载了这些数据卷的其他容器。

用法

  1. 容器挂载了数据卷(挂载方式同上)
  2. 创建其他容器时,使用目标容器上挂载的数据卷【目标容器就是数据卷容器】
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

  1. DockerHub 注册账号 https://hub.docker.com/
  2. linux 登录 DockerHub
    1
    docker login -u 用户名    # 输入用户名登录
  3. 提交镜像
    1
    docker push 自定义镜像名[:版本号]   # 命名规则 【用户名/自定义镜像名:版本号】
  4. 退出登录 docker logout

发布到阿里云镜像服务

  1. 登录阿里云 https://www.aliyun.com/
  2. 目录
    1. 产品
    2. 容器与中间件
    3. 容器镜像服务 ACR
    4. 管理控制台
    5. 个人实例
    6. 镜像仓库
    7. 创建镜像仓库
      • 选择本地仓库
  3. 根据创建的仓库下操作指南,登录和提交镜像

打包镜像(离线版)

将 Docker 镜像保存到本地文件中,以及从本地文件中加载 Docker 镜像

1
2
docker save -o 地址/压缩包名.tar 镜像名:版本号        # 将镜像打包到指定压缩包
docker load -i 压缩包名.tar # 从压缩包中添加 docker 镜像

Docker网络


原理

容器间和宿主主机可以相互通信

  1. docker 容器和宿主主机之间可以相互 ping 通
  2. docker 容器之间也可以相互通信

容器间通信的原理

docker 容器之间可以相互通信的原理,是使用了 veth-pair 技术

veth-pair成对 的虚拟以太网设备(Virtual Ethernet Device),其中一个设备连接到 Linux 系统的网络命名空间中,另一个设备则连接到另一个网络命名空间中。这使得两个网络命名空间之间可以进行通信。
网络命名空间:每一个网络命名空间都有自己独立的网络资源,互相之间隔离,就像在不同的主机上一样。

  1. linux 上安装好了docker之后,linux 就会有一个 docker0 的虚拟网桥,该网桥连接了主机上的物理网卡和所有运行的 Docker 容器。【网桥:用于连接多个网络,实现不同网络间的数据转发】
  2. 容器实例化之后,容器内会有一个 虚拟网卡 veth1-1,同时宿主主机 linux 上也会新添一个 虚拟网卡 veth1-2,这两个网卡是通过 veth-pair 技术实现的,因此两个网卡可以相互通信
  3. 虚拟网卡 veth1-2 通过 docker0 虚拟网桥 可以与宿主主机linux物理网卡进行通信。
  4. 其他 docker 容器在宿主主机上生成的 虚拟网卡 veth,通过 docker0 虚拟网桥 可以相互通信,信息再通过 veth-pair 传输到容器中
  5. 容器删除后,相关的 veth-pair 都会自动删除

  1. 作用:不通过ip,使用容器名进行数据传输或ping
  2. 原理:在容器1中修改host文件,将向容器名2的请求,转发到容器2的ip
  3. 已经不建议使用
1
2
docker run -d -P --name 容器名1 --link 容器名2 镜像名    # 配置通过容器名进行数据传输
docker exec -it 容器名1 ping 容器名2 # 测试传输数据【成功】

自定义网络

优势:

  1. 同一网络下的容器可以相互通信
  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/16192.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