敲黑板
docker
客户端/服务器架构
- 所有的容器操作都需要通过 dockerd 守护进程中转到 OCI(容器运行时)执行, dockerd 一旦崩溃, 所有依赖 dockerd 的容器都会失控, dockerd 会持续占用系统资源.
- docker 默认以 root 用户运行 dockerd, 如果容器逃逸, 攻击者可以直接获取主机的 root 权限,风险极高.
podman
无守护进程架构
- 容器操作采用直接调用 OCI(容器运行时) 的模式, 每个容器操作都是独立的进程, 互不依赖. 无单点故障, 资源占用更低.
- Rootless 原生, 基于 linux 的用户命名空间、挂载命名空间等原生能力, 实现无需 root 权限的容器运行. 普通用户可直接创建和管理容器, 容器内的
根用户仅映射到主机的普通用户.
安装
Package docker-ce is not available, but is referred to by another package.
如果提示未发现可用的 docker-ce 包时,检查系统镜像源是否正确(如果不能翻墙时, 使用国内的镜像源修改 /etc/apt/source.list)
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/json: dial unix /var/run/docker.sock: connect: permission denied
执行 docker 相关命令时提示, 表示 docker 权限不足
使用 sudo 命令运行 docker 命令
将当前用户加入到 docker 组中
1 | [root@localhost ~]# cat /etc/group | grep docker |
1 | groupadd docker # 添加 docker 用户组 |
概念
架构

命令

镜像
是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)
镜像由多个层组成, 每层叠加之后, 从外部看来就如一个独立的对象
UnionFS 联合文件系统
镜像加速
/etc/docker/daemon.json 配置文件修改默认镜像源
1 | { |
镜像操作
镜像的操作命令可直接用在 docker 或 docker image 命令后面
- images 查看本地镜像列表, 作用同
image ls- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤镜像
- reference 按镜像名称过滤
- label 按标签过滤
- before/since 按创建时间或镜像版本号过滤, 按镜像版本号过滤时不包含当前条件中的镜像版本
- dangling 按悬空镜像过滤
- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤镜像
1 | docker images -f "reference=hello-world:*" # 查看指定名称的所有版本的镜像 |
- history 查看镜像的历史信息
- rmi 删除本地镜像, 作用同
image rm
1 | docker rmi -f $(docker images -aq) |
search [OPTIONS] TERM 从镜像仓库查找镜像
- -f, --filter string 过滤指定条件的镜像
- --format string 使用指定格式显示镜像
- --limit int 搜索结果的数量限制
load|import 从归档文件导入镜像
save [OPTIONS] IMAGE [IMAGE…] 保存多个镜像到归档文件
1 | [root@localhost ~]# docker [image] save -o bak.tar centos01:v1 centos02:v1 # 归档一个或多个镜像文件 |
commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] 基于容器创建一个镜像
build 从 Dockerfile 构建镜像
pull [OPTIONS] NAME[:TAG|@DIGEST] 从远程仓库拉取镜像
push [OPTIONS] NAME[:TAG] 将镜像上传到镜像仓库
tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] 创建一个指向 源镜像 的 目标镜像标签
1 | # 创建一个指向 源镜像 的 目标镜像标签 |

从容器构建镜像
1 | docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] # 从容器构建镜像, 提交到本地仓库 |
- -a, --author 提交作者
- -m, --message 提交信息
- -p, --pause 提交过程中是否中断容器运行, 默认为 true
1 | [root@localhost ~]# docker images # 显示所有镜像 |
从 Dockerfile 构建镜像
. 上下文路径
--add-host 添加主机映射信息
--build-arg 通过命令行设置构建镜像过程中的参数, 可以覆盖
ARG设置的参数-f, --file 指定配置文件, 默认
${PWD}/Dockerfile-t 指定新创建的镜像名称和标签
--no-cache 构建镜像时不使用缓存
--compress 使用 gzip 压缩构建上下文环境
--label 设置镜像元数据
--network 设置构建过程中
RUN指令的网络模式-t, --tag 添加镜像的标签(name:tag)
1 | docker build -f /path/to/Dockerfile --build-arg NODE_ENV=production -t name:tag . |
容器
容器独立运行的一个或一组应用,是镜像运行时的实体, 它可以被启动、开始、停止、删除. 每个容器之间都是相互隔离的, 保证安全的平台
- 应用容器化 将应用整合到容器中并且运行起来的这个过程
1 | [root@localhost ~]# docker ps -a # 查看所有容器信息 |
容器操作
容器的操作命令可直接用在 docker 或 docker container 命令后面
create 创建新容器
run 创建并启动一个容器
start|stop|kill 启动|停止容器
pause 暂停容器
restart 重启容器
rename 重命名容器
events 获取 docker 服务器的实时事件
diff 显示容器文件系统的前后变化
ps 查看容器列表, 作用同
container ls- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤容器
- id 按 id 过滤
- name 按容器名称过滤
- label 按标签过滤
- exited 按退出码过滤
- status 按状态过滤, 包含 created, restarting, running, removing, paused, exited, dead
- ancestor 按创建容器的镜像过滤
- before/since 按创建时间过滤
- network 按容器连接的网络过滤
- publish/expose 按容器发布或暴露的端口过滤
- health 按容器基于它们的健康状态过滤
- isolation 仅支持 windows 守护进程
- is-task 按容器是否时服务的任务过滤
- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤容器
inspect 查看容器详细信息, 作用同
container inspectlogs 输出容器运行日志
- -f, --follow 实时输出容器运行日志
- -n, --tail 查看指定行数
- -t, --timestamps 输出日志添加时间戳
- --since string 输出指定时间开始的日志, ‘2022-01-02T13:23:37Z’ 或者 ‘45m’
- --until string 输出截止到指定时间的日志, ‘2022-01-02T13:23:37Z’ 或者 ‘45m’
port 查看容器映射端口
wait 阻塞一个或多个容器直到停止运行, 并打印容器的退出码
1 | [root@localhost ~]# docker wait centos01 # 阻塞一个或多个容器直到停止运行, 并打印容器的退出码 |
- export [OPTIONS] CONTAINER 导出容器的文件系统到归档文件
1 | [root@localhost ~]# docker [image] export -o bak.tar centos01 # 导出容器的文件系统到归档文件 |
- rm 删除容器
1 | [root@localhost ~]# docker rm -f $(docker ps -aq) # 删除所有容器 |
- stats 统计容器使用情况
1 | [root@localhost ~]# docker stats |
运行
如果本地不存在镜像时则先从远程拉取镜像(docker pull 镜像名)
1 | docker run --name 'helloWorld' -it 镜像名 在启动的容器里执行的命令 |
--add-host list 添加主机 ip 映射
-a, --attach 附加到标准输出中
-d, --detach 后台方式运行
--cpus 指定容器运行时的 cpu 数量
--cpuset-cpus string 绑定 cpu,
--cpuset-cpus '0,2,4,6'--user 设置容器用户
--name 容器名称
-h, --hostname 设置容器的主机名
-i, --interactive 即使没有附加也保持 STDIN 打开, 如果需要执行命令则需要开启这个选项
-t, --tty 分配一个伪终端进行执行, 一个连接用户的终端与容器 stdin 和 stdout 的桥梁
-P, --publish-all 将宿主机的随机端口映射到容器使用的端口上
-p, --publish 指定容器的端口
- -p 宿主机端口:容器端口/协议
- -p 容器端口/协议
-e, --env 设置容器运行的环境变量
--env-file 设置容器运行的环境变量文件
--expose 暴露端口号
--mount 挂载文件系统
--tmpfs 挂载临时文件系统
--volumes-from 指定继承的数据卷容器
-v, --volumes 设置容器数据卷映射
-w, --workdir 设置容器内部的工作目录
-l, --label list 设置容器的元数据
--label-file list 设置容器的元数据
--ip 设置容器 IP 地址
--ip6 IPv6 地址
--link 连接到另一个容器
--network 连接到指定的网络, 默认为 docker0
--log-driver string 容器日志驱动
--log-opt 日志设置
--privileged 授予此容器扩展权限
--read-only 只读模式挂在容器文件系统
--restart string 当容器退出后的重启策略
- no, 默认值
- on-failure[:max-retries]
- always
- unless-stopped
--dns list 设置 DNS 服务器
--dns-option list 配置 DNS
--dns-search list 配置 DNS 查询服务器
--domainname string 配置容器 NIS 域名
--entrypoint string 覆盖镜像的默认 ENTRYPOINT
-m, --memory 指定容器运行时的内存大小
--rm 测试时临时运行容器关闭后自动删除容器
1 | docker run -dit -p 6666:80 --name nginx01 --cpuset-cpus '0,2,4,6' --log-driver gelf nginx |
1 | [root@localhost ~]# docker images # 查看本地所有镜像 |
- 示例:最简单的 nginx 服务集群
1 | [root@localhost ~]# docker images # 查看所有镜像 |
进入容器
exec 和 attach
- exec
- 进入容器打开一个新的终端
- 退出容器, 容器正常运行
- attach
- 进入容器打开正在运行的终端
- 退出容器, 容器自动停止
1 | [root@localhost ~]# docker ps -a # 查看所有容器信息 |
- -e 运行容器时指定环境变量
- -w 容器工作目录
1 | [root@localhost ~]# docker exec -it -e PATH=/usr/local/v12.22.1/bin:$PATH centos01 node -v |
文件拷贝 cp
- -a, --archive 复制文档的所有信息
1 | docker cp [宿主机路径] [容器标识]:[容器内路径] # 拷贝宿主机文件到 容器内 目录 |
拷贝宿主机到容器内
1 | # 拷贝宿主机文件到 a441e0564165 /user/local 下 |
拷贝容器内到宿主机
1 | [root@localhost ~]# ls /home/ |
数据卷
卷就是目录或者文件,存在于一个或多个容器中,由 docker 挂载到容器中,卷的设计目的就是数据的持久化,完全独立于容器的生存周期, 因此 Docker 不会在容器删除时删除其挂载的数据
create 创建数据卷
inspect 显示数据卷的详细信息
ls 显示所有数据卷
- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤数据卷
- dangling 按悬空数据卷过滤
- driver 按数据卷驱动名称过滤
- label 按数据卷标签过滤
- name 按数据卷名称过滤
- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤数据卷
rm 删除数据据按
prune 移除所有未使用的本地数据卷
特点
- 卷中的更改可以直接生效
- 数据卷可在容器之间共享数据
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
数据卷类型
默认挂载数据卷的权限为 RW
可以在挂载数据卷时指定数据卷的权限 -v [source/path]:[destination/path]:[rw]
- --mount 不指定 type 选项默认为 volume
- -v 不能建立 tmpfs mounts
| 对比项 | –volume 或 -v | –mount type=bind |
|---|---|---|
| 若是主机路径不存在 | 自动建立 | 命令报错 |
| 对比项 | bind mount | volume |
|---|---|---|
| Source 位置 | 用户指定 | /var/lib/docker/volumes/ |
| Source 为空 | 覆盖 dest 为空 | 保留 dest 内容 |
| Source 非空 | 覆盖 dest 内容 | 覆盖 dest 内容 |
| Source 种类 | 文件或目录 | 只能是目录 |
| 可移植性 | 一般(自行维护) | 强(docker 托管) |
| 宿主直接访问 | 容易(仅需 chown) | 受限(需登陆 root 用户)* |
volume mounts
指定 docker 挂载区域, Docker 管理宿主机文件系统的一部分(/var/lib/docker/volumes)
1 | docker volume create [OPTIONS] [VOLUME] # 创建数据卷 |
bind mounts
是宿主机任意文件系统, 可以存储在宿主机系统的任意位置
1 | docker run --mount type=bind,source=${PWD}/${CONTAINER_NAME}/app,destination=/app centos01 /bin/bash |
tmpfs mounts
临时挂载到宿主机系统的内存中, 不会写入宿主机的文件系统
1 | docker run --mount type=tmpfs,tmpfs-size=512M,destination=/path/in/container |

挂载数据卷
-v 挂载方式
-v 容器内路径 匿名挂载
1 | [root@localhost ~]# docker run -tid --name centos01 -v /centosVolume centos /bin/bash |
-v 卷名:容器内路径 具名挂载
- 如果
不需要对容器内的数据卷挂载点进行写操作时, 使用具名挂载方式备份容器内数据到宿主机中
1 | [root@localhost ~]# docker run -tid --name centos02 -v summary:/myVolume centos /bin/bash |
-v /宿主机路径:容器内路径 指定路径挂载
- 如果
需要对容器内的数据卷挂载点进行写操作时, 使用指定路径挂载方式, 此方式会将宿主机中的数据卷挂载点数据覆盖容器内指定路径
1 | [root@localhost ~]# docker run -tid --name centos03 -v ${PWD}/react-app/:/containerVolume centos /bin/bash |
--mount 挂载方式
--mount 具名挂载
1 | [root@localhost ~]# docker run -tid --name centos04 --mount type=volume,source=applet_ui,destination=/appletVolume centos /bin/bash |
--mount 指定路径挂载
1 | [root@localhost ~]# docker run -tid --name centos05 --mount type=bind,source=${PWD}/applet_uni,destination=/uniVolume centos /bin/bash |
共享数据卷
- --volumes-from 创建数据卷容器共享数据
1 | # 创建容器并挂载数据卷 |
Dockerfile
- .dockerignore 构建上下文忽略文件
Dockerfile 是用来构建 Docker 镜像的一个指令脚本, 脚本中的每条指令执行一次都会在镜像上新建一层
Docker 的多阶段构建特性允许在同一个 Dockerfile 中使用多个 FROM 指令来定义多个构建阶段.
每个阶段都可以从不同的基础镜像开始, 并且可以选择性地将文件从一个阶段复制到另一个阶段. 有助于创建更精简的最终镜像
docker build 时会为每个阶段构建一个临时的中间镜像, 但最终只会输出最后一个阶段的镜像
指令
FROM 构建镜像时的基础镜像层, 可以出现多次以创建多个镜像或者将当前构建作为另一个构建的依赖
- --platform 指定镜像的平台, 用来处理那些支持多平台的镜像, linux/amd64、linux/arm64、windows/amd64
- AS <name> 为当前的构建阶段命名
MAINTAINER(deprecated) 维护者信息, 使用
LABEL指令代替EXPOSE 对外暴露端口, 仅仅是声明容器使用的端口, 并不会自动在宿主机进行端口映射
- 端口声明可以帮助镜像使用者理解这个镜像服务的端口使用, 以方便配置映射
- 使用 -p 参数会忽略此项声明的端口
- 使用 -P 参数会自动将宿主机上的随机端口映射到此项声明的端口
ADD 复制指令, 增强版的
COPY指令, 支持文件解压和远程 URL 资源COPY 复制指令, 从上下文目录中复制文件或者目录到容器里指定路径
- 如果源文件是一个目录, 则复制目录下的所有文件并忽略目录本身
RUN 构建镜像时执行的命令 可以存在多条指令
- RUN [OPTIONS] <command> …
- RUN [OPTIONS] [‘<command>‘, …]
WORKDIR 为
RUN,CMD,ENTRYPOINT,COPY,ADD指定工作目录ARG 构建参数, 作用与 ENV 一致, ARG 中的环境变量仅在
Dockerfile内有效, docker build –build-arg 参数覆盖 ARG 指定定义参数ENV 设置持久化环境变量, 如果只想在构建构建阶段有效使用
ARG指令
1 | # Dockerfile |
- CMD 容器运行时执行的命令, 如果存在多个
CMD指令, 仅最后一个生效 - ENTRYPOINT 容器运行时执行的命令, 参数不会被
docker run的命令行参数覆盖, 如果存在多个ENTRYPOINT指令,仅最后一个生效
1 | ENTRYPOINT '<exec_cmd>' '<param1>' |
- VOLUME 定义匿名数据卷, 在启动容器时会自动挂载到 /var/lib/docker/volumes/
1 | # 出于可移植和分享的考虑, 不支持 具名挂载 和 指定路径挂载 在 Dockerfile 中配置 |
- USER 指定执行后续命令的用户和用户组, 用户名和用户组必须提前存在
- LABEL 给镜像添加元数据
- SHELL 允许重写默认的 shell
- STOPSIGNAL 设置当容器退出时系统调用的指令
- ONBUILD 当前镜像作为其他镜像的基础镜像构建时触发
1 | USER <用户名>[:<用户组>] |
- HEALTHCHECK 指定监控 docker 容器服务的运行状态的方式
CMD 和 ENTRYPOINT
区别
- CMD 情况下, run 后面的参数将作为整体替换
CMD配置项中的命令
1 | # Dockerfile |
1 | # /bin/bash ls -al 命令会整体替换 Dockerfile 中的 CMD 指令 |
- ENTRYPOINT 情况下,
docker run后面的参数将作为 ENTRYPOINT 配置项指令的一部分
1 | # Dockerfile |
1 | # run 后面的参数作为 ENTRYPOINT 配置项命令参数的一部分 |
- CMD 和 ENTRYPOINT 同时存在时, CMD 作为 ENTRYPOINT 配置项命令的一部分, 与书写位置没有关系
1 | # Dockerfile |
| 是否传参 | Dockerfile 配置项指令 | 传参运行 |
|---|---|---|
| Docker 命令 | docker run nginx | docker run nginx /etc/nginx/new.conf |
| 衍生出的实际命令 | nginx -c /etc/nginx/nginx.conf | nginx -c /etc/new.conf |
使用场景
- Dockerfile 应至少指定一个 CMD 或 ENTRYPOINT 指令
- ENTRYPOINT 应在将容器作为可执行文件时定义
- CMD 应该用作为 ENTRYPOINT 命令定义默认参数或在容器中执行临时命令的一种方式
- CMD 使用替代参数运行容器时将被覆盖
| No ENTRYPOINT | ENTRYPOINT entry p1_entry | ENTRYPOINT [‘entry’,’p1_entry’] | |
|---|---|---|---|
| No CMD | error, not allowed | /bin/sh -c entry p1_entry | entry p1_entry |
| CMD [‘cmd’,’p1_cmd’] | cmd p1_cmd | /bin/sh -c entry p1_entry | entry p1_entry cmd p1_cmd |
| CMD [‘p1_cmd’,’p2_cmd’] | p1_cmd p2_cmd | /bin/sh -c entry p1_entry | entry p1_entry p1_cmd p2_cmd |
| CMD cmd p1_cmd | /bin/sh -c cmd p1_cmd | /bin/sh -c entry p1_entry | entry p1_entry /bin/sh -c cmd p1_cmd |
镜像优化
- 合并多个相同作用的指令以减少新建镜像层数
- 使用较小的基础镜像
- 使用 .dockerignore 文件, 从构建上下文中忽略指定的文件
- 在 RUN 之后放置 COPY 指令, 有助于 docker 能够更好的使用缓存功能
- 在安装后删除软件包
- 使用 Docker 镜像缩容工具
应用
- Dockerfile 配置文件
1 | # Dockerfile |
构建镜像
1 | # 构建镜像并指定镜像名称和版本号, 最后的 . 很重要,表示在当前目录下进行构建, 可以使用 |
查看镜像信息
镜像配置信息
1 | [root@localhost workspace]# docker image inspect hello:v1.0 |
镜像历史信息
1 | [root@localhost workspace]# docker image history hello:v1.0 |
查看容器状态
1 | [root@localhost workspace]# docker container inspect hello-v1 |