Docker 是什么
Docker 是一个开源的应用容器平台(PaaS),基于 Go 语言开发,并遵从 Apache2.0 协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何的宿主机器上。容器使用沙箱的机制,容器之间互相隔离,而且容器性能开销极低,并且可以在不同宿主环境之间互相迁移。
Docker 的优势在于:
- 更高效的利用系统资源
- 更快的启用时间
- 一致的运行环境
- 持续交付和部署
- 更轻松的迁移
- 更轻松地维护和扩展
Docker 原理
Docker 是基于 linux 内核实现的,它利用了多种 Linux 操作系统的机制来实现容器之间的互相隔离。
Namespace
linux 提供了一种叫 命名空间(Namespace)的机制,可以给进程、用户、网络等分配一个命名空间,这个命名空间下的资源都是独立命名的。
比如 PID namespace,也就是进程的命名空间,它会使命名空间内的这个进程 id 变为 1,而 linux 的初始进程的 id 就是 1,所以这个命名空间内它就是所有进程的父进程了。
IPC namespace 限制只有这个命名空间内的进程可以相互通信,不能和命名空间外的进程通信。
而 Mount namespace 会创建一个新的文件系统,命名空间内的文件访问都是在这个文件系统之上。
类似这样的 namespace 一共有 6 种:
- PID(Process Identification) namespace:进程 ID 的命名空间,提供进程隔离能力
- IPC(Inter-Process Communication) namespace:进程通信的命名空间,提供进程间通信的隔离能力
- MNT(Mount) namespace:文件系统挂载的命名空间,提供磁盘挂载点和文件系统的隔离能力
- Net(Network) namespace:网络的命名空间,提供网络隔离能力
- User namespace:用户和用户组的命名空间,提供用户隔离能力
- UTS(UNIX Timesharing System) namespace:主机名和域名的命名空间,提供主机名隔离能力
Docker 通过这 6 种命名空间,可以实现资源的隔离。
Control Group(CGroup)
linux 提供了一种叫 控制组(Control Group, CGroup)的机制可以通过给 控制组 指定参数,来限制控制组可以获取到的资源。比如 cpu 用多少、内存用多少、磁盘用多少。
创建容器的时候先创建一个 控制组,指定资源的限制,然后把容器进程加到这个 控制组 里,就不会有容器占用过多资源的问题了。
Docker 通过控制组的机制,可以限制容器对资源的访问,即资源访问限制。
UnionFS
联合文件系统(Union File System,UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。镜像可以通过分层来进行继承,基于基础镜像,可以制作各种具体的应用容器。这样如果有多个容器内做了文件修改,只要创建不同的层即可,底层的基础镜像是一样的。
Docker 通过 UnionFS 的这种分层的镜像存储,写时复制(Copy-on-Write)的机制,极大的减少了文件系统的磁盘占用。
Docker 的架构
Docker 的架构图如下:
Docker 的一些基本概念:
- Docker 守护进程(Docker daemon, dockerd): Docker 守护进程(dockerd)侦听 Docker API 请求并管理 Docker 对象,如镜像、容器、网络和 volumes。守护进程还可以与其他守护进程通信以管理 Docker 服务。
- Docker 客户端(docker): Docker 客户端(docker)是许多 Docker 用户与 Docker 交互的主要方式。当 Docker 用户使用诸如
docker run之类的命令时,客户端将这些命令发送到 dockerd,dockerd 执行这些命令。Docker 命令使用 Docker API 。Docker 客户端可以与多个守护进程通信。 - Docker 对象(Docker objects): Docker 对象是在使用 Docker 过程中控制与管理的一些对象。
- 镜像(Docker images): 镜像是一个只读的模板,包含创建 Docker 容器的说明。通常,一个镜像基于另一个镜像,并带有一些额外的定制内容。例如,Docker 用户可以构建一个基于 ubuntu 镜像的镜像,但是安装有 Apache web 服务器和应用程序,以及运行应用程序所需要的配置详细信息。Docker 用户可以创建自己的镜像,也可以只使用其他人创建并在 Docker registry 中发布的镜像。
- 容器(Docker containers): 容器是镜像的可运行实例。Docker 用户可以使用 Docker API 或者 CLI 管理容器。默认情况下,容器与其他容器及其主机相对良好地隔离。Docker 用户可以控制容器的网络、存储或其他底层子系统与其他容器或主机的隔离程度。容器由其映像以及创建或启动时提供给它的任何配置选项定义。移除容器后,未存储在持久存储中的对其状态的任何更改都将消失。
- Docker volumes: Volume 提供了将容器的特定文件系统路径连接回主机的能力(数据持久化的能力)。如果挂载(mounting)了容器中的目录,则在主机上也可以看到该目录中的更改。如果我们跨容器重新启动挂载相同的目录,我们将看到相同的文件。
- Docker 桌面端(Docker Desktop): Docker Desktop 是一款适用于 Mac、Windows 或 Linux 环境的易于安装的应用程序,使 Docker 用户能够构建和共享容器化应用程序和微服务。Docker 桌面端包括 Docker 守护进程(dockerd)、Docker 客户端(docker)、Docker Compose、Docker Content Trust、Kubernetes 和凭证助手(Credential Helper)。
- Docker 仓库(Docker repository): Docker 仓库可看成一个 Docker 镜像的控制中心。每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过
<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。 - Docker registry: Docker registry 是 Docker 镜像存储的地方,Docker 用户可以在 Docker registry 获取和发布镜像。默认是 Docker Hub。
- 主机(Docker Host): 一个物理主机或者虚拟机,用于运行 Docker 守护进程和容器。
- Docker Compose:Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
- Dockerfile 文件: Dockerfile 是一个基于文本的指令脚本,它使用简单的语法定义创建镜像并运行镜像所需的步骤。Dockerfile 中的每个指令在镜像中创建一个层(layer)。更改 Dockerfile 并重建镜像时,仅重建已更改的层。
- docker-compose.yml 文件: docker-compose.yml 是
docker compose命令的参数配置文件。 - .dockerignore 文件: .dockerignore 文件表明了在 Dockerfile 文件 的 COPY 指令中需要缓存的文件。
Docker 和 虚拟机 的区别
虚拟机:虚拟机是通过 Hypervisor (虚拟机管理系统,常见的有 VMWare workstation、VirtualBox),虚拟出网卡、cpu、内存等虚拟硬件,再在其上建立虚拟机,每个虚拟机是个独立的操作系统,拥有自己的系统内核。
容器:容器是利用 namespace 机制将文件系统、进程、网络、设备等资源进行隔离,利用 cgroup 机制对权限、cpu资源进行限制,最终让容器之间互不影响,容器无法影响宿主机。

| 对比项 | Docker(容器化) | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级别 | 分钟级别 |
| 硬盘使用 | 一般为MB | 一般为GB |
| 性能 | 接近原生 | 弱于原生 |
| 系统支持量级 | 单机支持上千个容器 | 一般支持几十个 |
| 隔离性 | 进程级别的隔离 | 系统级别隔离 |
| 安全性 | 与宿主机共享内核、文件系统等资源,一旦容器内的用户从普通用户权限提升为 root 权限,有可能对其他容器、宿主机造成影响 | 虚拟机租户 root 权限和宿主机的 root 虚拟机权限是分离的,甚至使用了硬件隔离,可以防止虚拟机突破和彼此交互 |
我们可以看到,Docker 的技术优势体现在 _效率_ 、 _性能_ 和 资源消耗 上,在 安全性 和 隔离级别 上与虚拟机相比较弱。
Docker 开始教程
在开始之前,首先需要先 下载并安装 Docker。Docker 是 Docker Inc.(原 dotCloud 公司) 的产品,它包括了 Docker EE (企业版)和 Docker CE(社区版)。需要注意的是,Docker 的开源代码仓库叫做 Moby。
clone
首先,克隆一个仓库
Getting Started 项目是一个简单的 Github 仓库,它包含了你需要编译镜像并作为容器运行的所有内容。
通过在一个容器中运行 Git 来克隆这个仓库。
1 | docker run --name repo alpine/git clone https://github.com/docker/getting-started.git |
build
现在,编译镜像
一个 Docker 镜像是一个只为容器服务的私有的文件系统,它提供了容器所需要的所有文件与代码。
1 | cd getting-started |
run
运行你的第一个容器
基于你上一步编译的镜像启动一个容器。运行一个容器会以它私有的资源启动应用程序,与机器的其他部分安全的隔离开来。
1 | docker run -d -p 80:80 --name docker-tutorial docker101tutorial |
你会发现我们使用了一些参数。这里包含了这些参数的一些信息:
-d - 以独立模式(在后台中)运行容器。-p 80:80 - 将容器中的80端口与主机的80端口一一映射。打开网络浏览器并导航到 http://localhost:80 来访问教程应用。如果已经有服务监听了 80 端口,你可以指定另一个端口。例如,指定 -p 3000:80 然后通过 http://localhost:3000 来访问应用。--name docker-tutorial - 给容器起一个名字 docker-tutorialdocker101tutorial - 指出使用的镜像。
share
现在保存并分享你的镜像
保存并分享你的镜像到 Docker Registry(默认 Registry 为 Docker Hub,需要通过 docker login 命令登录)来使其他用户可以容易地在任何目标机器下载和运行镜像。
1 | docker tag docker101tutorial /docker101tutorial |
Docker 常用功能
使用 docker COMMAND --help 可以查看具体 COMMAND 命令的用法和作用。
镜像管理 image
Docker 中经常要做的是将镜像拉取到本地,和镜像相关的有一些常用的操作包括:
登录 Docker registry、拉取镜像、编译镜像、移除镜像 等。
管理镜像的命令都集合在 docker image COMMAND 命令下,包括 build history import inspect save/load ls prune pull/push rm tag。
docker login [OPTIONS] [SERVER] [flags]
登录 Docker registry 或者云后台。如果没有提供 registry 服务器,默认由守护进程定义。
| 参数 | 完整参数 | 作用 |
|---|---|---|
-p |
--password string |
密码 |
-u |
--username string |
用户名 |
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
从 registry 拉取一个镜像或者一个仓库
| 参数 | 完整参数 | 作用 |
|---|---|---|
-a |
--all-tags |
下载仓库中所有已打标签的镜像 |
--disable-content-trust |
跳过镜像认证 (默认为 true) | |
--platform string |
如果服务器支持多平台,则设置平台 | |
-q |
--quiet |
不显示详细输出日志 |
docker build [OPTIONS] PATH | URL | -
根据 Dockerfile 编译镜像
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--file string |
Dockerfile的名字(默认是 ‘PATH/Dockerfile’) |
--network string |
设置运行实例在运行时的网络模式(默认为 default) | |
--no-cache |
编译镜像时不使用缓存 |
docker rmi [OPTIONS] IMAGE [IMAGE...]
移除一个或多个镜像
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--force |
强制移除镜像 |
docker save [OPTIONS] IMAGE [IMAGE...]
保存一个或多个镜像到一个 tar 包中(默认流式输出到 STDOUT)
| 参数 | 完整参数 | 作用 |
|---|---|---|
-o |
--output string |
写入到文件中,而不是STDOUT |
docker load [OPTIONS]
从一个 tar 包或者 STDIN 加载一个镜像
| 参数 | 完整参数 | 作用 |
|---|---|---|
-i |
--input string |
从 tar 包读取,而不是 STDIN |
-q |
--quiet |
不显示详细输出日志 |
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
从一个 tar 包导入容器创建一个文件系统镜像
| 参数 | 完整参数 | 作用 |
|---|---|---|
-c |
--change list |
对创建的镜像应用 Dockerfile 指令 |
-m |
--message string |
为导入的镜像设置提交消息 |
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
显示一个或多个 Docker 对象(包括镜像、容器、volume 等)的详细信息
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--format string |
将输出字符串以给定的 Go 模板形式格式化 |
docker history [OPTIONS] IMAGE
显示镜像的历史
| 参数 | 完整参数 | 作用 |
|---|---|---|
--format string |
使用 Go 模板优化显示镜像 | |
-H |
--human |
以人类可读的格式打印大小和日期(默认为 true) |
-q |
--quiet |
仅仅显示镜像 ID |
docker image ls [OPTIONS] [REPOSITORY[:TAG]]
列出所有镜像
| 参数 | 完整参数 | 作用 |
|---|---|---|
-a |
--all |
显示所有镜像(默认隐藏中间的镜像) |
--digests |
显示摘要 | |
-f |
--filter filter |
根据提供的条件过滤输出 |
--format string |
使用 Go 模板优化显示镜像 |
容器管理 container
管理容器是 Docker 中最常见的操作,包括 查看容器列表、查看容器详情、创建容器、在容器中运行命令、启动容器、暂停容器、停止容器、移除容器 等。
管理容器的命令都集合在 docker container COMMAND 命令下,常用的命令包括:ps|ls|list create/rm exec run start/stop pause/unpause logs、export、inspect、kill 等。
docker ps [OPTIONS]
查看所有容器
| 参数 | 完整参数 | 作用 |
|---|---|---|
-a |
--all |
显示所有容器(默认只显示运行中的容器) |
-f |
--filter filter |
基于提供的条件过滤输出 |
-n |
--last int |
显示最后创建的 n 个容器(包括所有状态) |
-l |
--lastest |
显示最后创建的容器(包括所有状态) |
-s |
--size |
显示总文件大小 |
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
创建一个新的容器
| 参数 | 完整参数 | 作用 |
|---|---|---|
-c |
--cpu-shares int |
CPU占用(相对比重) |
--cpus decimal |
CPU数量 | |
-e |
--env list |
设置环境变量 |
-h |
--hostname strin |
容器主机名 |
-i |
--interactive |
保持 STDIN 打开,即使未连接(以交互模式运行容器) |
-m |
--memory bytes |
内存限制 |
-p |
--publish list |
发布一个容器的端口到主机 |
-t |
--tty |
分配一个伪TTY |
-u |
--user string |
用户名或者UID(格式:<name/uid>[:group/gid]) |
-v |
--volume list |
绑定挂载一个 volume |
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
在一个运行的容器中运行命令
| 参数 | 完整参数 | 作用 |
|---|---|---|
-d |
--detach |
以后台模式执行命令 |
-e |
--env list |
设置环境变量 |
-i |
--interactive |
保持 STDIN 打开,即使未连接(以交互模式运行容器) |
-t |
--tty |
分配一个伪TTY |
-u |
--user string |
用户名或者UID(格式:<name/uid>[:group/gid]) |
-w |
--workdir string |
在容器中的工作目录 |
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
在一个新容器中运行命令(根据镜像生成新的容器并运行命令,相当于 docker create + docker exec )
| 参数 | 完整参数 | 作用 |
|---|---|---|
-c |
--cpu-shares int |
CPU占用(相对比重) |
--cpus decimal |
CPU数量 | |
-d |
--detach |
以后台模式运行容器并打印容器 ID |
-e |
--env list |
设置环境变量 |
-h |
--hostname strin |
容器主机名 |
-i |
--interactive |
保持 STDIN 打开,即使未连接(以交互模式运行容器) |
-m |
--memory bytes |
内存限制 |
--name string |
给容器起名 | |
-p |
--publish list |
发布一个容器的端口到主机 |
-t |
--tty |
分配一个伪TTY |
-u |
--user string |
用户名或者UID(格式:<name/uid>[:group/gid]) |
-v |
--volume list |
绑定挂载一个 volume |
docker start [OPTIONS] CONTAINER [CONTAINER...]
启动一个或多个容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
停止一个或多个容器
| 参数 | 完整参数 | 作用 |
|---|---|---|
-t |
--time int |
停止前等待的秒数(默认 10) |
docker pause CONTAINER [CONTAINER...]
暂停一个或多个容器的所有进程
docker rm [OPTIONS] CONTAINER [CONTAINER...]
移除一个或多个容器
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--force |
强制移除一个运行着的容器(使用 SIGKILL) |
-l |
--link |
移除特定的链接 |
-v |
--volumes |
移除与容器相关的匿名 volumes |
docker logs [OPTIONS] CONTAINER
获取一个容器的日志
| 参数 | 完整参数 | 作用 |
|---|---|---|
--details |
展示日志详情 | |
-f |
--follow |
跟踪日志输出 |
--since string |
需要展示日志的开始时间(例如,2013-01-02T13:23:37Z)或相对开始时间(例如,42m 代表42分钟内) | |
-n |
--tail string |
显示日志末尾的行数(默认 所有) |
-t |
--timestamps |
展示时间戳 |
--until string |
需要展示日志的截止时间(例如,2013-01-02T13:23:37Z)或相对截止时间(例如,42m 代表42分钟内) |
发布镜像 pull/push
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
创建一个标签 TARGET_IMAGE 指向 SOURCE_IMAGE
docker push [OPTIONS] NAME[:TAG]
将一个镜像或仓库 NAME 推送到 registry
| 参数 | 完整参数 | 作用 |
|---|---|---|
-a |
--all-tags |
推送仓库中所有已打标签的镜像 |
--disable-content-trust |
跳过镜像签名 (默认为 true) | |
-q |
--quiet |
不显示详细输出日志 |
数据持久化 volume
默认的 Docker 引擎可以通过两种方式来将宿主的数据挂载到容器中 named volume、bind mounts。

named volume
named volume 可以视为一个简单的数据桶,Docker 维护磁盘上的物理位置,Docker 用户只需要记住 volume 的名称。当使用 volume 时,Docker 会确保提供正确的数据。
我们需要首先通过 docker volume create 创建一个 volume,然后在 docker create 或者 docker run 创建容器的时候通过 -v 参数指定要使用的 volume 名称和路径。
docker volume create [OPTIONS] [VOLUME]
创建一个 volume
| 参数 | 完整参数 | 作用 |
|---|---|---|
-d |
-driver string |
表明 volume 的驱动名(默认 local) |
--label list |
设置 volume 的元数据 | |
-o |
--opt map |
设置驱动特殊参数(默认 map[]) |
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
显示一个或多个 volume 的详细信息
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--format string |
将输出字符串以给定的 Go 模板形式格式化 |
bind mounts
通过 bind mounts,我们可以控制主机上的确切的挂载点。bind mounts 可以用来持久化数据,但它通常用于向容器中提供额外的数据。
1 | docker run -dp 3000:3000 \ |
bind mounts 也是通过在 docker create 或者 docker run 创建容器的时候通过 -v 参数来指定绑定的路径,如上所示 "$(pwd):/app" 即为需要绑定挂载的主机路径。使用 bind mounts 在本地开发设置中非常常见。优点是开发机器不需要安装所有的构建工具和环境。只需一个 docker 运行命令,开发环境就可以启动了。
其他持久化方案
bind mounts 和 named volume 是 Docker 引擎附带的两种主要持久化方案。但是,还有其他 volume 驱动程序可用于支持其他用例(SFTP、Ceph、NetApp、S3等)。
网络管理 network
默认情况下,容器之间是互相隔离无法通信的,两个相关的容器只能通过 _网络_ 来进行通信。
与 _网络_ 相关的命令可以通过 docker network COMMAND 来调用,包括 connect/disconnect create inspect ls prune rm
docker network create [OPTIONS] NETWORK
创建一个网络
| 参数 | 完整参数 | 作用 |
|---|---|---|
--attachable |
允许手动附加容器 | |
--aux-address map |
网络驱动使用的辅助 IPv4 或 IPv6(默认 map[]) | |
-d |
--driver string |
管理网络的驱动(默认 bridge) |
-o |
--opt map |
设置驱动的特殊选项(默认 map[]) |
docker network connect [OPTIONS] NETWORK CONTAINER
将一个容器连接到一个网络
| 参数 | 完整参数 | 作用 |
|---|---|---|
--ip |
IPv4地址 | |
--ip6 |
IPv6地址 |
docker network disconnect [OPTIONS] NETWORK CONTAINER
将一个容器从一个网络断开
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--force |
强制将一个容器从一个网络断开 |
docker network rm NETWORK [NETWORK...]
移除一个或多个网络
多镜像应用 compose
Docker Compose 是一个开发用于帮助定义和共享多容器应用程序的工具。使用 Compose,我们可以创建一个 YAML 文件来定义服务,并且使用一个命令,可以将所有容器同时启动或销毁。
Compose 需要使用 docker-compose COMMAND 或者 docker compose COMMAND 来调用,常用的命令有 build config create/rm up/down start/stop/restart images kill pause/unpause pull/push exec run ps logs port 等。
docker compose up [OPTIONS] [SERVICE...]
创建并启动所有容器
| 参数 | 完整参数 | 作用 |
|---|---|---|
--build |
在启动容器前先编译镜像 | |
-d |
--detach |
独立模式,在后台运行容器 |
--no-recreate |
如果容器已经存在,不重建。与 --force-recrete冲突 |
|
-V |
--renew-anon-volumes |
重新创建匿名volume而不是从之前的容器中检索数据 |
-t |
--timeout int |
在连接容器或容器已经运行时,使用此超时时间(以秒为单位)关闭容器。(默认值为10) |
docker compose down [OPTIONS]
停止并移除所有容器、网络
| 参数 | 完整参数 | 作用 |
|---|---|---|
--remove-orphans |
删除 Compose 文件中未定义的服务中的容器 | |
rmi string |
删除服务使用到的镜像,”local”仅仅删除没有指定tag的镜像(”local”/“all”) | |
-t |
--timeout int |
停止前等待的秒数(默认 10) |
-v |
--volumes volumes |
删除在 Compose 文件的 volume 部分中声明的 named volumes 和附加到容器的匿名 volumes。 |
插件管理 plugin
Docker 可以通过 docker plugin COMMAND 来管理插件,包括以下命令:
| 命令 | 作用 |
|---|---|
create |
从 rootfs 和配置文件创建插件。插件数据目录必须包含 config.json 和 rootfs 目录。 |
disable |
禁用一个插件 |
enable |
启用一个插件 |
inspect |
显示一个或多个插件的详细信息 |
install |
安装一个插件 |
ls |
列出所有插件 |
push |
发布一个插件到 registry |
rm |
移除一个或多个插件 |
set |
变更一个插件的设置项 |
upgrade |
更新一个已存在的插件 |
安全管理 secret/scan
Docker Scan 是一个安全扫描工具,可以扫描本地的镜像中的安全漏洞,Docker Scan 是与 Snyk 合作来提供漏洞扫描服务的,所以必须登录 Docker Hub 账号。
docker scan [OPTIONS] IMAGE
对镜像进行安全漏洞扫描
| 参数 | 完整参数 | 作用 |
|---|---|---|
-f |
--file string |
与镜像相关的 Dockerfile,提供更多详细的结果 |
--json |
以 JSON 格式输出结果 |
Docker Secret 用于在 Swarm mode 集群中安全的管理密码、密钥证书等敏感信息,并允许在多个 Docker 容器实例之间共享访问指定的秘密信息。docker secret 只能从 Docker Swarm 模式的 manager 节点调用,如果在本机进行试验,需要先执行 docker swarm init 命令。secret 创建之后可以在 docker service create 中通过 --secret 参数使用,或者在 Compose 文件中使用。
| 命令 | 作用 |
|---|---|
create |
从文件或者 STDIN 创建一个 secret |
inspect |
显示一个或多个 secret 的详细信息 |
ls |
列出所有的 secret |
rm |
移除一个或多个 secret |
集群管理 swarm
Docker Swarm 是 Docker 公司推出的用来管理 docker 集群的平台,

Swarm 包括几个基本的概念
- swarm :集群管理工具
- node:节点,一个节点就是docker集群中的一个实例,我们可以在单台服务器上运行一个或多个节点
- service:应用编排
- task:应用实例
一个 Swarm 由一个或多个 Docker 节点组成。所有节点通过可靠的网络相连。节点会被配置为管理节点(Manager)或工作节点(Worker)。管理节点负责集群控制面(Control Plane),进行诸如监控集群状态、分发任务至工作节点等操作。工作节点接收来自管理节点的任务并执行。Swarm 的配置和状态信息保存在一套位于所有管理节点上的分布式 etcd 数据库中。该数据库运行于内存中,并保持数据的最新状态。关于该数据库最棒的是,它几乎不需要任何配置,作为 Swarm 的一部分被安装,无须管理。关于集群管理,最大的挑战在于保证其安全性。搭建 Swarm 集群时将不可避免地使用 TLS,因为它被 Swarm 紧密集成。关于应用编排,Swarm 中的最小调度单元是服务。它是随 Swarm 引入的,在 API 中是一个新的对象元素,它基于容器封装了一些高级特性,是一个更高层次的概念。当容器被封装在一个服务中时,我们称之为一个任务或一个副本,服务中增加了诸如扩缩容、滚动升级以及简单回滚等特性。
与 Swarm 相关的 docker 命令包括 docker swarm docker node docker service docker stack 等。
Docker Swarm 与 Kubernetes 对比
Docker Swarm 是 Docker 公司于 2015 年初发布的一款容器编排工具。Kubernetes 是 2014年中发布的一款容器编排工具,并得到了 Google 和 RedHat 的支持。
Docker Swarm 优势:
- 架构简单,部署运维成本较低
- 启动速度快
Docker Swarm 劣势:
- 无法提供更精细的管理
- 网络问题
- 容器可靠性
Kubernetes 优势:
- 管理更趋于完善稳定
- 健康机制完善
- 轻松应对复杂的网络问题
Kubernetes 劣势:
- 配置、搭建稍显复杂,学习成本高
- 启动速度稍逊
Dockerfile 参考
Dockerfile 的用法详见 Dockerfile reference。
镜像是通过 Dockerfile 来描述的,Dockerfile 遵循以下格式:
1 | # parser directive |
解析指令(parser directive)
解析器指令是可选的,并且会影响后续处理 Dockerfile 的方式。解析器指令不会将层添加到构建中,并且不会显示为构建步骤。解析器指令以# directive=value 的方式使用。 一个指令只能使用一次。
- syntax:定义用于构建 Dockerfile 的 Dockerfile 语法的位置,仅在使用 BuildKit 后端时可用,在使用经典构建器后端时被忽略。
- escape:设置用于转义 Dockerfile。 如果未指定,则默认转义字符为
\。
指令(INSTRUCTION)
Dokcer 是分层存储的,修改的时候会创建一个新的层,所以这里的每一行(每个指令)都会创建一个新的层。
- ENV: 用于声明环境变量
- ARG:必须在 FROM 指令之前声明,指定镜像参数,相当于
docker build命令中的--build-arg <varname>=<value>参数 - ONBUILD:向镜像添加一个触发指令,当镜像用作另一个构建的基础时,该触发指令将在以后执行。触发器将在下游构建的上下文中执行,就像它是在下游 Dockerfil e中的 FROM 指令之后立即插入的一样。
- FROM:初始化一个新的构建阶段并为后续指令设置 基本镜像,一个 Dockerfile 文件必须以 FROM 指令开始。
- WORKDIR:为 RUN、CMD、ENTRYPOINT、COPY、ADD 指令指定当前工作目录
- USER:设置用户名(或UID)和可选的用户组(或GID),以用作当前阶段剩余时间的默认用户和组。给定的用户将作为 RUN 、ENTRYPOINT、CMD 指令的用户
- VOLUME:创建具有指定名称的装载点,并将其标记为保存来自本地主机或其他容器的外部装载 volume。
- LABEL:为镜像添加元数据
- ADD:复制新文件,目录或者远程文件 URL,将其从原地址添加到镜像中的地址
- COPY:复制新文件,目录,将其从原地址添加到镜像中的地址
- EXPOSE:声明当前容器要监听的网络端口
- RUN:将在当前镜像之上的新层中执行任何命令并提交结果
- CMD:容器启动的时候执行的命令,一个 Dockerfile 文件只有最后一个 CMD 指令会生效。
- ENTRYPOINT:将一个容器配置为可执行的运行
- STOPSIGNAL:设置退出时将会被发送到容器的系统调用信号
- HEALTHCHECK:告知 Docker 如何检测一个容器是否运行
- SHELL:可以覆盖默认使用的 SHELL 类型。Linux 默认的 shell 为
["/bin/sh", "-c"]Windows 默认为["cmd", "/S", "/C"]
一个常见的 nodejs 应用的 Dockerfile 如下:
1 | # build stage |
我们把两个镜像的生成过程写到了一个 Dockerfile 里,这是 Docker 支持的多阶段构建。
FROM node:10表示这个镜像是基于node:10来构建的,AS build_image,这是把第一个镜像命名为 build_image。WORKDIR /app表示当前工作目录是 /app 。COPY . /app表示将当前路径下的内容复制到 /app 路径下EXPOSE 8080表示当前容器要访问的网络端口为 8080 端口RUN npm install && npm run build表示在编译的时候(docker build)执行npm install && npm run buildCOPY --from=build_image /app/dist ./dist表示将来自 build_image 镜像的/app/dist路径下的内容复制到./dist路径下RUN npm i -g http-server表示在变异的时候运行npm i -g http-serverCMD http-server ./dist表示在创建容器(docker create)的时候执行http-server ./dist
一个常见的 前端 项目的 Dockerfile 如下:
1 | # build stage |
与 nodejs 项目类似也是编译阶段一个镜像,发布阶段一个镜像。 npm install 和 npm run build 分开的好处是可以在 .dockerignore 文件中添加 node_moudules 从而对依赖包进行缓存。
如果是公网开放的服务,可以在编译后将前端静态资源文件(js、css、ttf、png、jpg、jpeg、gif、svg文件等)上传到云存储服务器,并开启 CDN 服务,这样用户端下载静态资源文件会更快,体验会更好。
Dockerfile 最佳实践
- 不要安装无效软件包
- 应简化镜像中同时运行的进程数,理想状况下,每个镜像应该只有一个进程
- 当无法避免同一镜像运行多进程时,应选择合理的初始化进程(init process)
- 最小化层级
- 最新的 docker 只有 RUN COPY ADD 创建新层,其他指令创建临时层,不会增加镜像大小
- 比如 EXPOSE 指令就不会生成新层
- 多条 RUN 指令可通过连接符成一条指令集以减少层数
- 通过多端构建减少镜像层数
- 最新的 docker 只有 RUN COPY ADD 创建新层,其他指令创建临时层,不会增加镜像大小
- 把多行参数按字母排序,可减少可能出现的重复参数,并且提高可读性
- 编写 Dockerfile 的时候,应该把变更频率低的编译指令优先构建以便放在镜像底层以有效利用 build cache
- 复制文件时,每个文件应独立复制,这确保某个文件变更时,只影响该文件对应的缓存