第一本 Docker 书
第1章 简介
容器(container) 和 管理程序虚拟化(hypervisor virtualization) 不同:
- HV, 通过中间层将一台或多台独立的机器虚拟运行于物理硬件之上
- Container, 直接运行在操作系统内核之上的用户空间
容器只能运行与底层宿主机相同或相似的操作系统。
Docker 是为改变容器的复杂性。
1.1 Docker 简介
Docker 是一个能够把开发的应用程序自动部署到容器的开源引擎。所以说是和容器相关联。
Docker 在虚拟化的容器执行环境中增加了一个应用程序部署引擎。
1.1.1 提供一个简单、轻量的建模方式
Docker 依赖于”写时复制”模型。
1.1.2 职责的逻辑分离
1.1.3 快速、高效的开发生命周期
1.1.4 鼓励使用面向服务的架构
1.2 Docker 组件
核心组件:
- Docker 客户端和服务器,也称为 Docker 引擎
- Docker 镜像
- Registry
- Docker 容器
1.2.1 Docker 客户端和服务器
Docker 是一个客户端/服务器(C/S)架构的程序。
Docker 提供了一个命令行工具 docker 以及一整套 RESTFUL API 来与守护进程交互。
1.2.2 Docker 镜像
用户基于镜像来运行自己的容器。
可以把镜像当做容器的”源代码”.
1.2.3 Registry
Docker 用 Registry 来保存用户构建的镜像。
Registry 分为公有和私有两种。
可在 Docker Hub 上保存自己的私有镜像。
1.2.4 容器
Docker 可以帮用户构建和部署容器,用户只需要把自己的应用程序或服务打包放进容器即可。
Docker 容器是:
- 一个镜像格式
- 一系列标准的操作
- 一个执行环境
Docker 借鉴了集装箱的概念,集装箱运输货物,Docker 运输软件。Docker 是运输工, 对容器进行操作。
每个容器都包含一个软件镜像,也就是容器的”货物”.
所有容器都按照相同的方式将内容”装载”进去,
1.3 能用 Docker 做什么
容器可以为各种测试提供很好的沙盒环境.
1.4 Docker 与配置管理
Docker 很轻量: 镜像是分层的,可以对其进行迅速的迭代.
Docker 一个显著特点就是,对不同的宿主机、应用程序和服务,可能会表现出不同的特性与架构。
1.5 Docker 的技术组件
第2章 安装 Docker
2.1 安装 Docker 的先决条件
2.2 在 Ubuntu 和 Debian 中安装 Docker
2.2.1 检查前提条件
1. 内核
使用:
1 |
|
若下载新内核,可使用命令加载新内核:
1 |
|
2. 检查 Device Mapper
使用 Device Mapper 作为存储驱动。
Device Mapper 支持”自动精简配置”(thin-provisioning)的概念,可以在一种文件系统中存储多台虚拟设备(Docker镜像中的层).
确认是否安装:
1 |
|
或:
1 |
|
或:
1 |
|
2.2.2 安装 Docker
到官网查看.
2.2.3 Docker 与 UFW
UWF 即 Uncomplicated Firewall.
Docker 使用一个网桥来管理容器中的网络。
默认情况下,UFW 会丢弃所有转发的数据包,因此需要在 UFW 中启用数据包的转发.
修改 /etc/default/ufw
文件:
1 |
|
改为:
1 |
|
重新加载:
1 |
|
2.9 Docker 守护进程
用户可以使用 docker daemon
命令控制 Docker 守护进程。
守护进程监听 /var/run/docker.sock
这个 UNIX套接字文件,来获取来自客户端的 Docker 请求。
2.9.1 配置 Docker 守护进程
用 -H
标志调整守护进程绑定监听接口的方式, 可以使用 -H
标志指定不同的网络接口和端口配置:
1 |
|
使用 -D
参数来输出 Docker 守护进程的详细信息:
1 |
|
2.10 升级 Docker
1 |
|
2.11 Docker 用户界面
第3章 Docker 入门
3.1 确保 Docker 已经就绪
1 |
|
3.2 运行我们的第一个容器
docker run
命令提供了 Docker 容器的创建到启动的功能。
可以使用 docker help run
获取命令列表。
使用 man
页, man docker-run
1 |
|
-i
参数保证容器中 STDIN 是开启的。
-t
参数告诉 Docker 为要创建的容器分配一个伪 tty 终端.
ubuntu
是用来告诉 Docker 基于什么镜像来创建容器,ubuntu
镜像是一个常备镜像,也可以称为”基础”(base) 镜像,由 Docker 公司提供,保存在 Docker Hub Registry 上。
Docker 会检查本地是否存在 ubuntu
镜像,如果没有,Docker 就会连接官方维护的 Docker Hub Registry, 查看 Docker Hub 中是否存在该镜像,Docker 一旦找到该镜像,就会下载到本地。
随后,Docker 在文件系统内部用这个镜像创建了一个新容器,该容器拥有自己的网络、IP地址,以及一个用来和宿主机进行通信的桥接网络接口。
/bin/bash
是我们告诉 Docker 在容器中运行的命令。
3.3 使用第一个容器
我进入的界面为:
1 |
|
这里 root
为 root 账户,895508d7a56f
为容器 ID(即主机名). 其为一个完整的 Ubuntu 系统。
获取主机名:
1 |
|
查看容器的网络配置:
1 |
|
使用 exit
命令可以退出容器。
docker ps -a
查看当前系统中容器的列表。
docker ps -l
列出最后一个运行的容器。
有三种方式可以唯一指定容器:
- 短 UUID
- 长 UUID
- 名称
3.4 容器命名
Docker 会为我们创建的每一个容器自动生成一个随机的名称。
使用 --name
标志来指定名称:
1 |
|
一个合法的名称只能包括 [a-zA-Z0-9.-]
很多 Docker 命令中,都可以用容器的名称来替代容器 ID.
容器的命名是唯一的。
用 docker rm
可删掉容器。
3.5 重新启动已经停止的容器
启动停止的容器:
1 |
|
重新启动用 docker restart
使用 docker create
创建一个容器但不运行它.
3.6 附着到容器上
Docker 容器重新启动的时候,会沿用 docker run
命令时指定的参数来运行。
也可以用 docker attach
命令重新附着到该容器的会话上:
1 |
|
3.7 创建守护式容器
除交互式运行的容器(interactive container) 还有守护式容器(daemonized container), 其没有交互式会话。
1 |
|
使用 -d
参数,即放入后台运行。
3.8 容器内部都在干些什么
使用 docker logs
获取容器的日志.
1 |
|
可加入 -f
选项:
1 |
|
获取最后十行:
1 |
|
加上时间戳:
1 |
|
3.9 Docker 日志驱动
使用 --log-drive
选项:
1 |
|
使用 syslog
时会警用 docker logs
命令,并将所有容器的日志输出都重定向到 Syslog
.
若使用 none
则禁用日志。
3.10 查看容器内的进程
使用 docker top
命令:
1 |
|
3.11 Docker 统计信息
docker stats
显示一个或多个容器的统计信息:
1 |
|
3.12 在容器内部运行进程
可以再容器内运行的进程有两种类型:
- 后台任务
- 交互式任务
使用 docker exec
命令:
1 |
|
就是对一个正在运行的容器使用。
3.13 停止守护式容器
使用 docker stop
命令:
1 |
|
交互式可以通过 exit
想要快速停止某个容器,使用 docker kill
:
显示最后 x 个容器:
1 |
|
3.14 自动重启容器
使用 --restart
标志,磨人的行为是 Docker 不会重启容器。
1 |
|
另一个 on-failure
参数,即在退出状态码为非 0 值时重启,且可指定重启次数:
1 |
|
3.15 深入容器
docker inspect
获取更多容器信息:
1 |
|
使用 -f
或 --format
标志选定查看结果:
可指定多个容器.
3.16 删除容器
使用 docker rm
命令:
1 |
|
可传递 -f
参数。
删除所有容器:
1 |
|
第4章 使用 Docker 镜像和仓库
4.1 什么是 Docker 镜像
Docker 镜像是由文件系统叠加而成。
最低端是一个引导文件系统 bootfs.
当一个容器启动后,它会被移到内存中,而引导文件系统则会被卸载(unmount).
Docker 镜像的第二层是 root 文件系统 rootfs, 其位于引导文件系统之上。
Docker 利用联合加载技术(union mount), 即一次同时加载多个文件系统,但是在外面看起来只能看到一个文件系统。
联合加载会将各层文件系统叠加到一起,这样最终的文件系统会包含所有底层的文件和目录。
Docker 将这样的文件系统称为镜像。一个镜像可以放到另一个镜像的顶部。位于下面的镜像称为父镜像(parent image), 最底层的镜像称为基础镜像(base image).
当从一个镜像启动容器时,Docker 会在该镜像最顶层加载一个读写文件系统,我们在 Docke 中运行的程序就是在这个读写层中执行。
每个只读镜像层都是只读,并且以后永远不会变化。
写时复制(copy on write)机制,想修改一个文件,这个文件首先会从该读写层下面的只读层复制到该读写层,该文件的只读版本依然存在,但是被读写层中的该文件副本所隐藏。
4.2 列出镜像
列出主机上可用的镜像, 使用 docker images
:
1 |
|
本地镜像都保存在 Docker 宿主机的 /ver/lib/docker
目录下.
镜像从仓库下载,镜像保存在仓库中,仓库存在于 Registry 中。
每个镜像仓库都可以存放很多镜像.
使用 docker pull
命令来拉取仓库中的镜像。
可以通过在仓库名后面加上一个冒号和标签名来指定该仓库中的某一镜像:
1 |
|
一个镜像可以有多个标签。
Docker Hub 中有两种类型的仓库:
- 用户仓库(user repository), 都是由 Docker 用户创建的, 其命名由用户名和仓库名两部分组成
- 顶层仓库(top-level repository), 由 Docker 内部的人来管理, 其命名只包含仓库名
4.3 拉取镜像
如:
1 |
|
4.4 查找镜像
使用 docker search
命令来查找所有 Docker Hub 上公共的可用镜像。
1 |
|
4.5 构建镜像
两种方法:
- docker commit
- docker build 和 Dockerfile 文件
使用Dockerfile
更加灵活.
4.5.1 创建 Docker Hub
登录到 Docker Hub, 使用 docker login
命令:$ sudo docker login
用户的个人认证信息会被保存在 $HOME/.docker/config.json
中。
4.5.2 用 Docker 的 commit 命令创建镜像
1 |
|
4aab3ce3cb76
是容器的 ID, jamtur01
是目标镜像仓库, apache2
是镜像名.
docker commit
提交的只是创建容器的镜像与容器的当前状态之间有差异的部分。
可以在提交镜像时指定更多的数据(包括标签):
1 |
|
-m
选项是创建镜像的提交信息。
-a
选项是该镜像的作者信息。
webserver
是标签名。
可以使用 docker inspect
命令来查看新创建的镜像的详细信息:
1 |
|
4.5.3 用 Dockerfile 构建镜像
一般不推荐使用 docker commit
来构建镜像。
Dockerfile 使用基本的基于 DSL(Domain Specific Language) 语法的指令来构建一个 Docker 镜像。
第一个 Dockerfile
创建的用来保存 Dockerfile 的目录称为构建环境(build environment), Docker 则称此环境为上下文(context)或构建上下文(build context),
Docker 会在构建镜像时将构建上下文和该上下文中的文件和目录上传到 Docker 守护进程。
例子:
1 |
|
Dockerfile 由指令和参数构成。
每条指令,如 FROM
, 都必须为大写字母, 而且后面要跟随一个参数.
每条指令都会创建一个新的镜像层并对镜像进行提交。
运行流程:
- Docker从基础镜像运行一个容器。
-执行一条指令,对容器做出修改。
-执行类似docker commit的操作,提交一个新的镜像层。
-Docker再基于刚提交的镜像运行一个新容器。
-执行Dockerfile中的下一条指令,直到所有指令都执行完毕
Dockerfile 中的注释是 #
开头的行.
MAINTAINER
指令告诉 Docker 该镜像的作者是谁,以及作者的电子邮件地址。
RUN
指令会在当前镜像中运行指定的命令. 每条 RUN
指令都会创建一个新的镜像层。
默认情况下,RUN
指令会在 shell 里使用 /bin/sh -c
来执行。
若在不支持 shell 的平台上,使用 exec
格式的 RUN
指令:
1 |
|
这里的 -y
参数是 yes
的意思。
EXPOSE
指令,告诉 Docker 该容器内的应用程序将会使用容器的指定端口。
可以指定多个 EXPOSE
指令来向外部公开多个端口。
4.5.4 基于 Dockerfile 构建新镜像
执行 docker build
命令时,Dockerfile 中的所有指令都会被执行并且提交,并且在该命令成功结束后返回一个新镜像。
使用 -t
选项为新镜像设置仓库和名称以及标签:
1 |
|
如果没有制定任何标签,Docker 将会自动为镜像设置一个 latest
标签.
最后一个 .
告诉 Docker 到本地目录中找 Dockerfile 文件,也可指定一个 Git 仓库的源地址来指定 Dockerfile 的位置.
1 |
|
-f
参数指定文件:
1 |
|
构建目录中的 .dockerignore
类似于 .gitignore
4.5.5 指令失败时会怎样
4.5.6 Dockerfile 和构建缓存
它会将之前的镜像层看做缓存,意思是第二次 docker build
时,会接着从上次结束时运行。
忽略缓存功能,使用 docker build --no-cache
1 |
|
4.5.7 基于构建缓存的 Dockerfile 模板
一般在 Dockerfile 文件顶部使用相同的指令集模板:
1 |
|
ENV
指令用于在镜像中设置环境变量。
模板实际上就是自己常用的配置。
4.5.8 查看新镜像
深入探求镜像是如何被构建出来的,使用 docker history
1 |
|
4.5.9 从新镜像启动容器
1 |
|
-d
选项告诉 Docker 以分离(detached)的方式在后台运行。
-p
选项,用来控制 Docker 在运行时应该公开哪些网络端口给外部(宿主机).
Docker 可以通过两种方法来在宿主机上分配端口:
- Docker 可以在宿主机上随机选择一个位于 32768~61000 的比较大的端口号来映射到容器的 80 端口上
- 可以在 Docker 宿主机中指定一个具体的端口号来映射到容器中的 80 端口上
docker run
命令会在 Docker 宿主机上随即打开一个端口,连接到容器中的 80 端口上。
可用 docker ps
命令查看容器的端口分配情况:
1 |
|
也可通过 docker port
命令来查看容器的端口映射情况:
1 |
|
使用 -p
选项指定容器中的端口映射到 Docker 宿主机的某一特定端口上:
1 |
|
前者是宿主机端口,后者是容器端口。
将端口绑定限制在特定的网络接口(即IP地址)上:
1 |
|
其将容器内的 80 端口绑定到本地宿主机的 127.0.0.1 这个 IP 的 80 端口上. 不指定如 80 就是随机端口。
使用 -P
参数将 Dockerfile 中通过 EXPOSE
指令指定的端口公开:
1 |
|
并绑定到随机端口。
有了这个端口号,就可以使用本地宿主机的 IP 地址连接到运行中的容器.
4.5.10 Dockerfile 指令
[清单](http://docs.docker.com/ reference /builder/)
CMD
用于指定一个容器启动时要运行的命令.
1 |
|
后面为参数.
这是存储在一个数组结构中.
docker run
命令后若指定要运行的命令, 会覆盖 Dockerfile 中的 CMD 指令.
在 Dockerfile 中只能指定一条 CMD 命令.
ENTRYPOINT
docker run
命令行中指定的任何参数都会被当做参数再次传递给 ENTRYPOINT
指令中指定的命令.
如:
1 |
|
然后:
1 |
|
其中 -g "daemon off;"
就会传递给 ENTEYPOINT
可用 docker run
的 --entrypoint
选项来覆盖 ENTRYPOINT
指令.
WORKDIR
用来从镜像创建一个容器时,在容器内部设置一个工作目录,ENTRYPOINT
和 /
或 CMD
指定的程序会在这个目录下执行.
可以设置不同的工作目录:
1 |
|
可以通过 -w
选项在运行时设置工作目录:
1 |
|
ENV
用于设置环境变量:
1 |
|
也可通过 docker run
命令的 -e
参数来传递环境变量:
1 |
|
USER
指定该镜像以什么样的用户去执行:
1 |
|
可以指定用户名或 UID 以及组或 GID:
1 |
|
默认用户为 root, 可以用 docker run
的 -u
选项覆盖.
VOLUME
作用
在没有在 docker run
时使用 -v
选项时, 创建一个隐藏数据卷.
什么是隐藏数据卷
也就是没有指定宿主机上面的某一个目录, 因此自动在 /var/lib/docker/volumes
目录下自动创建的一个卷.
VOLUME 的作用
比如我们在 Dockerfile 中写 VOLUME [ "/Blog" ]
, 并且在 run 的时候没有添加 -v
选项, 那么在容器创建后, 会生成 /Blog
这个目录, 以及在 /var/lib/docker/volumes
下生成一个卷, 这两个相互映射.
用来向基于镜像创建的容器添加卷, 一个卷是可以存在于一个或者多个容器内的特定的目录.
特点:
- 卷可以在容器间共享和重用
- 一个容器可以不是必须和其他容器共享卷
- 对卷的修改是立时生效的
- 对卷的修改不会对更新镜像产生影响
- 卷会一直存在知道没有任何容器再使用它.
卷功能可以让我们将内容添加到镜像而不提交.
1 |
|
为基于此镜像创建的任何容器创建一个名为 /opt/project
的挂载点.
docker cp
允许从容器复制文件和复制文件到容器上.
指定多个卷:
1 |
|
ADD
用来将构建环境下的文件和目录复制到镜像中.
1 |
|
前者为原文件位置,后者为目的文件位置.
源文件位置也可以是 URL.
Docker 通过目的地址参数末尾的字符来判断文件源是目录还是文件:
- 目的地址以
/
结尾, 则为目录 - 不以, 则为文件
如果将压缩文件指定为源文件,会将其解压:
1 |
|
目前 Docker 还不支持以 URL 方式指定的源文件位置中使用归档文件.
ADD
指令会使构建缓存无效.
COPY
类似于 ADD
, 但 COPY
只关心在构建上下文中复制本地文件,而不会 extraction 和 decompression.
1 |
|
文件源路径必须是一个与当前构建环境相对的文件或者目录, 本地文件都放到和 Dockerfile 同一个目录下,不能复制该目录之外的任何文件.
LABEL
用于为 Docker 镜像添加元数据. 元数据以键值对的形式展现:
1 |
|
推荐将所有元数据都放到一条 LABEL 指令中.
然后通过 docker inspect
命令来查看 Docker 镜像中的标签信息.
STOPSIGNAL
用来设置停止容器时发送什么系统调用给容器. 这个信号必须是内核系统调用表中合法的数或者 SIGNAME 格式中的信号名称.
ARG
用来定义可以在 docker build
命令运行时传递给构建运行时的变量, 只需在构建时使用 --build-arg
参数, 用户只能在构建时指定在 Dockerfile 文件中定义过的参数:
1 |
|
第二条指定了默认值:
1 |
|
不要使用 ARG
来传递证书或者密钥.
Docker 预定义了一组 ARG 变量:
1 |
|
ONBUILD
为镜像添加触发器(trigger). 当一个镜像被用作其他镜像的基础镜像时, 该镜像中的触发器将会被执行.
触发器会在构建过程中插入新指令, 我们可以认为这些指令是紧跟在 FROM 之后指定的:
1 |
|
ONBUILD
指令可以在镜像上运行 docker inspect
查看.
ONBUILD
触发器会按照父镜像中指定的顺序执行, 并且只能被继承一次.
有部分指令不能用在 ONBUILD
中, 防止递归调用.
4.6 将镜像推送到 Docker Hub
使用 docker push
命令:
1 |
|
应该要先登录, 用 docker login
自动构建(Automated Builds)
将 Github 或 BitBucket 中含有 Dockerfile 文件的仓库连接到 Docker Hub 即可. 具体参考书籍.
4.7 删除镜像
使用 docker rmi
:
1 |
|
每一个 Deleted:
行都代表一个镜像层被删除.
4.8 运行自己的 Docker Registry
Registry 就相当于 repository.
4.8.1 从容器运行 Registry
从容器安装一个 Registry:
1 |
|
启动一个运行 Registry 应用 2.0 版本的容器.
4.8.2 测试新 Registry
先通过 docker images
找到镜像 ID:
1 |
|
然后用 Registry 给镜像打上标签:
1 |
|
最后通过 docker push
将其推送到 Registry 中, 为了指定新的 Registry 的地址, 需要在镜像名前加上主机名和端口前缀:
1 |
|
使用其构建新容器:
1 |
|
4.9 其他可选的 Registry 服务
第5章 在测试中使用 Docker
5.1 使用 Docker 测试静态网站
将 Docker 作为本地 Web 开发环境是 Docker 的一个最简单的应用场景。
要想保持 Docker 容器的活跃状态,需要其中运行的进程不能中断,默认情况下,Nginx 会以守护进程的方式启动,这会导致容器只是短暂运行,在守护进程被 fork 后,发起守护进程的原始进程就会退出,这时容器就停止运行了.
5.1.2 构建 Sample 网站和 Nginx 镜像
5.1.3 从 Sample 网站和 Nginx 镜像构建容器
1 |
|
这里的 -v
选项允许我们将宿主机的目录作为卷,挂载到容器里。
两个目录用 :
分隔,前者为宿主机目录,后者为容器目录,如果容器目录不存在,Docker 会自动创建一个。
可以通过在目录后面加上 rw
或 ro
来指定容器内目录的读写状态:
1 |
|
卷的概念
卷是在一个或者多个容器内被选定的目录,可以绕过分层的联合文件系统,为 Docker 提供持久数据或者共享数据。
对卷的修改会立即生效,并绕过镜像,当提交或者创建镜像时,卷不被包含在镜像里。
卷是从宿主机而来。
5.1.4 修改网站
直接修改本地宿主机的 website 目录下的 index.html 文件, 也就是卷内的文件:
1 |
|
5.2 使用 Docker 构建并测试 Web 应用程序
Sinatra 是一个基于 Ruby 的 Web 应用框架,它包含一个 Web 应用库,以及简单的领域专用语言 (DSL) 来构建 Web 应用。
Sinatra 非常适合用来创建一个小型的示例应用进行测试。
5.2.1 构建 Sinatra 应用程序
5.2.4 将 Sinatra 应用程序连接到 Redis 容器
两种比较现实的连接 Docker 容器的方法是:
- Docker Networking, Docker 1.9 及更新版本推荐使用
- Docker link, Docker 1.9 之前版本推荐使用
Docker Networking 和 Docker link 的区别:
- Docker Networking 可以将容器连接到不同宿主机上的容器
- 通过 Docker Networking 连接的容器可以在无需更新连接的情况下,对停止、启动或者重启容器。
- 使用 Docker Networking, 不必事先创建容器再去连接它。同样不必关心容器的运行顺序。
5.2.5 Docker 内部连网
在安装 Docker 时,会创建一个新的网络接口,名字是 docker0.
每个 Docker 容器都会在这个接口上分配一个 IP 地址。
启动 IPv6, 在运行 Docker 守护进程时加上 --ipv6
标志.
接口本身的地址是这个 Docker 网络的网关地址,也是所有 Docker 容器的网关地址。
Docker 会默认使用 172.17.x.x 作为子网地址,除非被占用,Docker 就会在 172.16~172.30 这个范围内尝试创建子网.
Docker 每创建一个容器就会创建一组互联的网络接口,其中一端作为容器里的 eth0 接口,而另一端统一命名为 vethec6a 这种名字,作为宿主机的一个端口.
通过把每个 veth* 接口绑定到 docker0 网桥,Docker 创建了一个虚拟子网,这个子网由宿主机和所有的 Docker 容器共享。
从容器内跟踪路由:
1 |
|
查看宿主机的 IPTables NAT 配置:
1 |
|
Docker 默认会把公开的端口绑定到所有的网络接口上。
如果重启容器,Docker 会改变容器的 IP 地址.
5.2.6 Docker Networking
容器之间的连接用网络创建,被称为 Docker Networking.
Docker Networking 允许用户创建自己的网络,容器可以通过这个网上互相通信.
使用 Docker Networking 需先创建一个网络,然后在这个网络下启动容器:
1 |
|
create
后接名称.
查看新创建的网络:
1 |
|
列出当前系统中的所有网络:
1 |
|
删除一个 Docker 网络:
1 |
|
添加容器:
1 |
|
--net
标志指定了新容器将会在哪个网络中运行。
Docker 会感知所有在这个网络下运行的容器,并且通过 /etc/hosts
文件将这些容器的地址保存到本地 DNS 中。
app
网络内部的任何主机都可以使用 hostname.app
形式来被解析。
在宿主机下如:
1 |
|
将已有容器连接到 Docker 网络
1 |
|
这里 app
为网络名称,db2
为容器名称.
断开一个容器与指定网络的链接
1 |
|
一个容器可以同时隶属多个 Docker Networking.
通过 Docker link 连接容器
1 |
|
--link
标志,用于创建两个容器间的客户-服务链接。其需要两个参数,前者是要链接的容器的名称,后一个是这个链接的别名。这里 webapp
是客户,redis
是”服务”.
通过把容器链接在一起,可以让客户容器直接访问任意服务容器的公开端口.
只有使用 --link
标志链接到这个容器的容器才能连接到这个端口。
可以把多个容器链接在一起:
1 |
|
在运行容器时指定 --add-host
选项,可以在 /etc/hosts
文件中添加相应的记录:
1 |
|
在容器中可以用 env
命令查看新创建的环境变量的信息.
5.2.7 使用容器连接来通信
5.3 Docker 用于持续集成
即在多开发者的持续集成测试场景中使用 Docker.
第6章 使用 Docker 构建服务
6.1 构建第一个应用
6.1.1 JekyII 基础镜像
6.1.2 构建 Jekyll 基础镜像
6.1.5 启动 Jekyll 网站
启动一个叫做 james_blog
的新容器, 把本地的 james_blog 目录作为 /data/
卷挂载到容器里:
1 |
|
卷在 Docker 宿主机的 /var/lib/docker/volumes
目录中, 可以通过 docker inspect
命令查看某个卷的具体位置.
如果想在另一个容器里使用 /var/www/html/
卷里编译好的网站, 可以建立一个新的链接到这个卷的容器:
1 |
|
--volumes-from
标志, 把指定容器里的所有卷都加入新创建的容器里.
卷 这个概念感觉实际上就是挂载, 你在 Docker 里面修改了这个 卷 里的内容, 宿主机上面的目录也会更新.
6.1.7 备份 Jekyll 卷
如:
1 |
|
上面命令的解释为, --rm
参数表明会在容器的进程运行完毕后, 自动删除容器, --volumes-from james_blog
指定从哪个容器中获取 volumes, -v $(pwd):/backup
将当前目录 (即用来存备份文件的目录) 挂载到容器中的 /backup
目录下, ubuntu
是 image 的名称, tar cvf /backup/james_blog_backup.tar /var/www/html
是将 /var/www/html
打包为 /backup/james_blog_backup.tar
文件.
6.1.8 扩展 Jekyll 示例网站
6.2 使用 Docker 构建一个 Java 应用服务
6.2.1 WAR 文件的获取程序
6.3 多容器的应用栈
docker run
中的 -h
标志, 用于指定容器的主机名.
6.4 不使用 SSH 管理 Docker 容器
传统上讲, 通过 SSH 登入运行环境或者虚拟机来管理服务.
在 Docker 里, 大部分容器都只运行一个进程, 所以不能使用这种访问方法.
需要登入容器时, 可以使用 nsenter
工具.
nsenter 可以进入一个已经存在的容器的 shell, 即便这个容器没有运行 SSH 或任何类似目的的守护进程. 可以通过 Docker 容器安装 nsenter:
1 |
|
具体见书.
第7章 Docker 编配和服务发现
Docker Compose 是 Docker 的编配工具.
7.1 Docker Compose
使用 Docker Compose, 可以用一个 YAML 文件定义一组要启动的容器, 以及容器运行时的属性. Docker Compose 称这些容器为 “服务”.
7.1.1 安装 Docker Compose
三种方法:
- 直接安装
- Docker Toolbox
- Python Pip
如:
1 |
|
具体见书.
7.1.2 获取示例应用
7.1.3 docker-compose.yml 文件
执行 docker-compose up
命令, Compose 会启动这些容器, 使用指定的参数来执行, 并将所有日志输出合并到一起.
示例 docker-compose.yml
文件:
1 |
|
links
指定了要连接到服务的其他服务.
可以在 Docker Compose 官网查看 docker-compose.yml 所有可用指令列表. 位置
7.1.4 运行 Compose
创建并启动服务:
1 |
|
为了保证服务是唯一的, Compose 将 docker-compose.yml 文件中指定的服务名称加上目录名作为前缀, 并分别使用数字作为后缀.
Compose 之后接管了每个服务输出的日志, 输出的日志每一行都使用缩短的服务名称最为前缀, 并交替输出在一起.
服务和 Compose 交替运行, 这意味着, 如果使用 Ctrl+C
来停止 Compose 运行, 也会停止运行的服务.
可以在运行 Compose
时指定 -d
标志, 其将以守护进程来运行服务.
1 |
|
7.1.5 使用 Compose
可以用 docker-compose ps
命令来查看服务的运行状态:
1 |
|
使用 docker-compose help +命令
来查看相关用法.
docker-compose stop
可以停止正在运行的服务.
docker-compose kill
强制杀死服务.
使用 docker-compose start
命令重启.
docker-compose rm
来删除这些服务.
7.3 Docker Swarm
Docker Swarm 是一个原生的 Docker 集群管理工具.
Swarm 将一组 Docker 主机作为一个虚拟的 Docker 主机来管理.
7.3.1 安装 Swarm
拉取 Docker 公司提供的 swarm
镜像即可:
1 |
|
运行 Swarm 的所有 Docker 节点都必须运行统一个版本的 Docker.
7.3.2 创建 Swarm 集群
集群中的每台主机上都运行着一个 Swarm 节点代理 , 每个代理都将改主机上的相关 Docker 守护进程注册到集群中.
和节点代理相对的是 Swarm 的管理者, 用于对集群进行管理.
通过集群发现后端 (discovery backend, 如 Docker Hub) 来实现集群注册. 默认为 Docker Hub.
在 Docker Hub 中注册一个集群, 然后返回一个集群 ID, 之后使用这个集群 ID 向集群添加额外的节点.
1 |
|
此命令会返回一个 字符串, 即集群 ID.
运行 Swarm 代理:
1 |
|
使用 join
并用 --addr
传递本机 IP 地址.
token://b811b0bc438sifjvajhfiakfidjcbaj83hai
这一串就是指定2集群 ID.
查看代理节点的列表:
1 |
|
可在任意安装了 Docker 的主机上执行.
创建 Swarm 集群管理者:
1 |
|