Docker 是一种轻量级的容器化技术,通过将应用程序及其运行所需的最小依赖包封装在一起,并共享主机操作系统的内核,使得 Docker 容器比传统的虚拟机更加高效,资源消耗更少.
为什么要使用Docker
你有没有想过一个问题,为什么这个程序在我这里可以运行在他那里就不能运行了?没错就是依赖问题,Docker 可以通过将程序的整个运行环境,包括所有依赖项,打包成一个镜像从而解决了‘在我这能跑但在他那不能跑’的问题,并且一次打包到处运行的特性让你不必再为依赖冲突或环境不一致而烦恼.
此外,Docker这种容器化技术提供了独立的运行空间,使得每个容器的应用程序和依赖项彼此独立,不会与其他容器或主机系统发生冲突.
Docker相关术语介绍
在Docker中有服务端与客户端的概念(也就是常说的C\S架构),有三大基本组件:Docker镜像(Docker image)、Docker仓库(Docker registry)、Docker容器(Docker container).
Docker 镜像
Docker 镜像是 Docker 容器运行时的只读模板,类似于面向对象编程中的类:镜像定义了容器的行为和环境,而容器则是镜像的实例.
每一个镜像由一系列的层组成.Docker 使用 UnionFS(联合文件系统)将这些层组合成一个单一的镜像.每个镜像由多个只读层组成,每层都是对文件系统的一次快照或修改.正是因为这些层的存在,Docker 才会如此轻量.
当你修改一个 Docker 镜像时,比如升级某个应用程序的版本,一个新层会被创建.新的更改会以叠加的方式添加为新的一层,而不会修改已有的层.这样,原先的镜像保持不变,新的镜像只是在原有镜像的基础上添加了新的一层.正是因为这个特性每一次更新只需要升级层并不用重新发布整个镜像,这使得分发Docker镜像变得简单快速.
Docker 仓库
Docker仓库是用来存储Docker镜像的.Dokcer仓库有私有库和公有仓库的概念。公有Docker仓库是Docker Hub,用于存储和提供很多镜像的集合.私有的仓库是我们在内网搭建的一个私网Docker仓库,用于内网用户访问.
Docker 容器
虽然可以类比为文件夹,但 Docker 容器更像是一个独立的运行环境,它包含了某个应用程序所需的所有依赖和配置。每一个 Docker 容器都是从 Docker 镜像创建的.可以对Dokcer容器执行运行、启动、停止、移动和删除等操作.每一个 Docker 容器都是独立且隔离的运行环境,确保应用程序之间不会相互干扰.Docker 容器是 Docker 平台的核心运行部分.
Docker 的网路模式
host 模式
容器将与宿主机共用网络栈,这意味着容器不会有独立的网络命名空间,容器中的服务会直接使用宿主机的 IP 地址和端口.
container 模式
新建的容器将与指定的已有容器共享同一个网络命名空间,这意味着它们可以共享 IP 地址和网络配置.
none 模式
容器没有分配任何网络接口.这种模式下,容器没有网络连接,需要手动为 Docker 容器添加网络接口、IP 地址等.
bridge 模式
此模式是Docker的默认的网络配置,此模式会为每一个容器分配一个网络命令空间,并将一个主机上的Docker容器连接到一个虚拟网桥上.
Docker 的数据存储方式
Docker的管理数据的方式有以下两种:
(1)数据卷
(2)容器卷(绑定挂载)
数据卷
数据卷是由 Docker 管理的,实际存储在主机文件系统的某个目录中.使用数据卷时,你需要将它与容器内的某个目录进行挂载(形式为数据卷:容器内目录).如果在运行容器时没有显式指定数据卷的名称,Docker 会自动创建一个匿名卷,他的生命周期与容器相关联(容器删除对应的匿名卷也会清除).
数据卷的生命周期独立于容器,换言之,即使容器被删除,数据卷仍然会保留.数据卷可以在多个容器之间共享和重用,从而实现数据的持久化和共享.
# 创建数据卷
➜ ~ docker volume create dzd # 创建一个名为 dzd 的数据卷
# 创建运行容器并把数据卷dzd挂载到/data 目录下
➜ ~ docker run -d --name dzd -v dzd:/data $ubuntu #$ubuntu这个是ubuntu22.04的镜像,因为名字过于冗长,我把他定义成一个变量使用.在以后的笔记中会有提到
# 创建运行容器并把匿名卷挂载到/app/data目录下
➜ ~ docker run -d -v /app/data $ubuntu # Docker 会自动创建一个匿名卷,并挂载到容器的 /app/data 目录
➜ ~ docker ps -l #这个指令可以查看自动生成的容器名称
# 查看现有的数据卷
➜ ~ docker volume ls # 列出所有创建的 Docker 数据卷
# 删除数据卷
➜ ~ docker volume rm dzd # 删除名为 dzd 的数据卷
# 参数作用说明
-d # 使用 -d 选项启动容器时,Docker 会在后台运行容器,而不会附着在终端上
-v # -v 选项用于将 Docker 数据卷或主机目录挂载到容器内的指定目录中
--name #指定容器的名称
容器卷
对于 Docker 容器中的数据存储,数据卷和容器卷的原理相似.数据卷由 Docker 自动管理,存储位置由 Docker 处理,具有独立于容器的生命周期,适合持久化和共享数据.容器卷则是通过将宿主机文件系统上的目录直接挂载到容器内实现的,这种方式更加灵活,适用于需要直接访问或修改宿主机文件的场景.然而,容器卷依赖于宿主机的文件系统结构,使用时需要特别注意权限和路径的正确性.
在我看来,数据卷和容器卷的区别在于:数据卷是由 Docker 自动管理的存储,而容器卷(绑定挂载)则是直接挂载宿主机的实际目录到容器中.
# 创建并使用容器卷
➜ ~ docker run -d --name dzd -v /data:/data $ubuntu #把宿主机的/data/目录映射到容器的/data目录
# 对于删除容器卷来说没有这个必要因为本身也是物理的一个目录.如果你想删除请参照下边
➜ ~ rm -rf 目录 #这是一个相当危险的指令,他会递归删除目录里边的所有内容包括目录本身,且不给你后悔的机会.使用的时候一定要慎重
Docker 容器的管理
创建容器
方法一:
# 创建容器
➜ ~ docker run <镜像名> /bin/echo 'dfjkdfdl' #创建一个容器,因为没有命名会自动命名,执行完自动退出
# 查看所有容器
➜ ~ docker ps -a
方法二:创建一个自定义名称的容器
➜ ~ docker run --name dzd -t -i $ubuntu /bin/bash #创建一个名为dzd的容器并分配一个终端与容器交互
# 参数作用说明
-t #分配一个伪终端
-i #保持标准输入流的开放,可以与容器交互
删除容器
➜ ~ docker ps -a #查看所有停止或启动的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0411e8a4b3b4 swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ubuntu:22.04 "bash" 27 minutes ago Exited (0) 26 minutes ago dzd
➜ ~ docker rm dzd或ID #根据ps -a中的这个字段CONTAINER ID里边的值
➜ ~ docker rm -f 容器名称或ID #用于删除正在运行中的容器
➜ ~ docker run --rm $ubuntu /bin/echo 'ni hao' #运行及删除
ni hao
进入与退出容器
exit #退出容器
➜ ~ docker start dzd #启动容器
➜ ~ docker attach dzd #进入容器(必须在容器启动状态下)
root@0460de09aa02:/#
# 还可使用nsenter进入容器,我太懒了有兴趣的朋友可自行查阅
Docker 容器的运行
创建Dokcer容器之后,需要将容器运行起来,运行容器的命令如下.
➜ ~ docker run -d -p 2000:2222 $ubuntu #这个镜像是一个命令行,并不是一个持久化进程,所以执行完会立即退出.
➜ ~ docker run -d -P $ubuntu
# 端口参数说明
docker -p #需要手动指定端口映射,宿主机端口:容器端口
docker -P #参数用于自动将容器内的所有公开端口随机映射到主机上的高位端口(大于 32768 的端口),随机指定端口号
Docker 容器常用管理命令
dokcer start/stop/restart/kill
功能:启动、停止、重启、杀掉容器
实例操作:
➜ ~ docker start dzd
➜ ~ docker stop dzd
➜ ~ docker restart dzd
➜ ~ docker kill -s kill dzd #-s参数表示向容器发送信号
dokcer run
功能:创建并启动一个新的容器
常用参数如下:
-d:后台运行容器,并返回容器ID
-i:以交互模式运行容器,多与-t参数同时使用
-t:给容器分配一个伪终端,多与-i参数同时使用
–name:给容器指定一个名称
-m:指定容器使用内存最大值
–net:指定容器使用的网络类型
–link:链接到另一个容器
实例操作:
# 前边提到过的参数不在演示
➜ ~ docker run -m 512m -d --name dzd -v /data:/data $ubuntu #限制容器最多512MB
# 网络类型
➜ ~ docker run -m 512m --network -d --name dzd -v /data:/data $ubuntu #对于这些网络类型的具体配置还未验证
bridge container host none
# 对于link参数来说,现在已经不太常用,这里只是做一个了解
Docker rm
功能:删除容器
常用参数如下:
-f:强制删除一个运行中的容器
-l:删除指定链接
-v:删除与容器关联的卷
实例操作:
➜ ~ docker rm -v dzd #删除与容器的关联卷
Docker exec
功能:在运行的容器中执行命令
常用参数如下:
-d:在后台运行
-i:保持输入流打开
-t:分配一个伪终端
实例操作:
➜ ~ docker exec -it dzd /bin/bash /data/dzd.sh #在容器中,使用/bin/bash 这个解释器运行在/data下的dzd.sh这个脚本
➜ ~ docker exec -it dzd /bin/bash #给容器dzd分配一个终端
Docker ps
功能:列出容器(正在运行)
常用参数如下:
-a:列出所有容器,包括停止的
-f:根据条件显示内容
-l:列出最近创建的容器
-n:列出最近创建指定个数的容器
-q:只显示容器ID
-s:显示总文件大小
实例操作:
# 我觉得有ps -a和-l或n参数就够用了
Docker inspect
功能:获取容器内部元数据
常用参数如下:
-f:指定返回值格式或模版文件
-s:显示总文件大小
–type:为指定类型返回JSON
实例操作:
➜ ~ docker inspect exciting_bhabha #这里边包含各种信息,例如容器的状态等等
Docker port
功能显示指定容器端口映射信息
实例操作:
➜ / docker port objective_blackburn #显示端口映射,因为未指定容器名称,系统取的
Docker commit
功能:用已存在的容器重新创建一个新的镜像
常用参数:
-a:提交给作者
-c:使用Dockerfile指令创建镜像(配置选项的默认行为)
-m:提交时附上使用说明文字
-p:在提交时,将容器暂停
实例操作:
➜ / docker commit -a 'dzd' -c "CMD [\"/bin/bash\"]" -m 'zhe shi yi ge kong jing xiang' dzd dzd_image
# 这条指令会使用/bin/bash创建这个镜像,就是说当你使用这个镜像创建运行一个新容器时,容器会执行/bin/bash命令
Docker cp
功能:用于容器与宿主机之间复制文件
实例操作:
➜ / docker cp /hy.sh dzd:/ #把/下的hy.sh复制到容器dzd的/目录下
Successfully copied 2.56kB to dzd:/
Docker login/logout
功能:用于登录与登出镜像仓库(如果未指定仓库地址,默认为官方仓库Docker Hub)
常用参数:
-u:登录用户名
-p:登录密码
➜ docker login -u 用户名 -p 密码
➜ docker logout
- Docker pull/push
实例操作:
➜ docker pull nginx #拉取镜像
➜ docker push 镜像名称 #上传镜像
Docker images
功能:显示系统本地容器镜像
常用参数如下:
-a:列出所有镜像
–digests:显示镜像的摘要信息
-f:显示满足条件的镜像
–format:指定返回值的模版文件
–no-trunc:显示完整的镜像信息
-q:只显示镜像ID
➜ / docker images #列出本地所有镜像
➜ / docker images -q #只显示镜像ID
# 以此类推
Docker rmi
功能:删除镜像
常用参数如下:
-f:强制删除
实例操作:
➜ / docker rmi -f dzd_image