From 8626d137385031e829d3d2ecd9196a7601bfd9a8 Mon Sep 17 00:00:00 2001 From: Baohua Yang Date: Fri, 8 May 2015 20:10:01 +0800 Subject: [PATCH] Add the compose chapter --- README.md | 4 + SUMMARY.md | 15 +++ _images/compose.png | Bin 0 -> 43963 bytes compose/README.md | 4 + compose/commands.md | 142 +++++++++++++++++++++++++++ compose/install.md | 63 ++++++++++++ compose/intro.md | 10 ++ compose/usage.md | 7 ++ compose/yaml_file.md | 223 +++++++++++++++++++++++++++++++++++++++++++ fig/README.md | 2 +- fig/cli_ref.md | 2 +- fig/env_ref.md | 2 +- fig/install.md | 4 +- fig/intro.md | 18 ++-- 14 files changed, 482 insertions(+), 14 deletions(-) create mode 100644 _images/compose.png create mode 100644 compose/README.md create mode 100644 compose/commands.md create mode 100644 compose/install.md create mode 100644 compose/intro.md create mode 100644 compose/usage.md create mode 100644 compose/yaml_file.md diff --git a/README.md b/README.md index 4756136..7539f7b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ v0.4 * [亚马逊图书](http://www.amazon.cn/%E5%9B%BE%E4%B9%A6/dp/B00R5MYI7C/ref=lh_ni_t?ie=UTF8&psc=1&smid=A1AJ19PSB66TGU) ## 主要版本历史 +* 0.5: 2015-? + * 添加 Compose 项目 + * 添加 Machine 项目 + * 添加 Swarm 项目 * 0.4: 2015-05-08 * 添加 Etcd 项目 * 添加 Fig 项目 diff --git a/SUMMARY.md b/SUMMARY.md index a6aff09..678670a 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -69,6 +69,20 @@ * [联合文件系统](underly/ufs.md) * [容器格式](underly/container_format.md) * [网络](underly/network.md) +* [Docker Compose 项目](compose/README.md) + * [简介](compose/intro.md) + * [安装](compose/install.md) + * [使用](compose/usage.md) + * [命令说明](compose/commands.md) + * [YAML 模板文件](compose/yaml_file.md) +* [Docker Machine 项目](machine/README.md) + * [简介](machine/intro.md) + * [安装](machine/install.md) + * [使用](machine/usage.md) +* [Docker Swarm 项目](swarm/README.md) + * [简介](swarm/intro.md) + * [安装](swarm/install.md) + * [使用](swarm/usage.md) * [Etcd 项目](etcd/README.md) * [简介](etcd/intro.md) * [安装](etcd/install.md) @@ -98,3 +112,4 @@ * [WordPress](appendix_repo/wordpress.md) * [Node.js](appendix_repo/nodejs.md) * [附录三:有用的资源](appendix_resources/README.md) + diff --git a/_images/compose.png b/_images/compose.png new file mode 100644 index 0000000000000000000000000000000000000000..d753482d16103a7fbf682e1ec9e6ceed5faa084d GIT binary patch literal 43963 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 literal 0 HcmV?d00001 diff --git a/compose/README.md b/compose/README.md new file mode 100644 index 0000000..0892ff7 --- /dev/null +++ b/compose/README.md @@ -0,0 +1,4 @@ +# Docker Compose 项目 +Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。 + +本章将介绍 Compose 项目情况以及安装和使用。 diff --git a/compose/commands.md b/compose/commands.md new file mode 100644 index 0000000..d218ad1 --- /dev/null +++ b/compose/commands.md @@ -0,0 +1,142 @@ +## Compose 命令说明 + +大部分命令都可以运行在一个或多个服务上。如果没有特别的说明,命令则应用在项目所有的服务上。 + +执行 `docker-compose [COMMAND] --help` 查看具体某个命令的使用说明。 + +基本的使用格式是 +```sh +docker-compose [options] [COMMAND] [ARGS...] +``` + +## 选项 + +* `--verbose` 输出更多调试信息。 +* `--version` 打印版本并退出。 +* `-f, --file FILE` 使用特定的 compose 模板文件,默认为 `docker-compose.yml`。 +* `-p, --project-name NAME` 指定项目名称,默认使用目录名称。 + +## 命令 + +### `build` + +构建或重新构建服务。 + +服务一旦构建后,将会带上一个标记名,例如 web_db。 + +可以随时在项目目录下运行 `docker-compose build` 来重新构建服务。 + +### `help` + +获得一个命令的帮助。 + +### `kill` + +通过发送 `SIGKILL` 信号来强制停止服务容器。支持通过参数来指定发送的信号,例如 +```sh +$ docker-compose kill -s SIGINT +``` + +### `logs` + +查看服务的输出。 + +### `port` + +打印绑定的公共端口。 + +### `ps` + +列出所有容器。 + +### `pull` + +拉取服务镜像。 + +### `rm` + +删除停止的服务容器。 + +### `run` + +在一个服务上执行一个命令。 + +例如: + +``` +$ docker-compose run ubuntu ping docker.com +``` + +将会启动一个 ubuntu 服务,执行 `ping docker.com` 命令。 + +默认情况下,所有关联的服务将会自动被启动,除非这些服务已经在运行中。 + +该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照期望创建。 + +两个不同点: +* 给定命令将会覆盖原有的自动运行命令; +* 不会自动创建端口,以避免冲突。 + +如果不希望自动启动关联的容器,可以使用 `--no-deps` 选项,例如 + +``` +$ docker-compose run --no-deps web python manage.py shell +``` + +将不会启动 web 容器所关联的其它容器。 + +### `scale` + +设置同一个服务运行的容器个数。 + +通过 `service=num` 的参数来设置数量。例如: + +``` +$ docker-compose scale web=2 worker=3 +``` + +### `start` + +启动一个已经存在的服务容器。 + +### `stop` + +停止一个已经运行的容器,但不删除它。通过 `docker-compose start` 可以再次启动这些容器。 + +### `up` + +构建,(重新)创建,启动,链接一个服务相关的容器。 + +链接的服务都将会启动,除非他们已经运行。 + +默认情况, `docker-compose up` 将会整合所有容器的输出,并且退出时,所有容器将会停止。 + +如果使用 `docker-compose up -d` ,将会在后台启动并运行所有的容器。 + +默认情况,如果该服务的容器已经存在, `docker-compose up` 将会停止并尝试重新创建他们(保持使用 `volumes-from` 挂载的卷),以保证 `docker-compose.yml` 的修改生效。如果你不想容器被停止并重新创建,可以使用 `docker-compose up --no-recreate`。如果需要的话,这样将会启动已经停止的容器。 + +## 环境变量 + +环境变量可以用来配置 Compose 的行为。 + +以`DOCKER_`开头的变量和用来配置 Docker 命令行客户端的使用一样。如果使用 boot2docker , `$(boot2docker shellinit)` 将会设置它们为正确的值。 + +### `COMPOSE_PROJECT_NAME` + +设置通过 Compose 启动的每一个容器前添加的项目名称,默认是当前工作目录的名字。 + +### `COMPOSE_FILE` + +设置要使用的 `docker-compose.yml` 的路径。默认路径是当前工作目录。 + +### `DOCKER_HOST` + +设置 Docker daemon 的地址。默认使用 `unix:///var/run/docker.sock`,与 Docker 客户端采用的默认值一致。 + +### `DOCKER_TLS_VERIFY` + +如果设置不为空,则与 Docker daemon 交互通过 TLS 进行。 + +### `DOCKER_CERT_PATH` + +配置 TLS 通信所需要的验证(`ca.pem`、`cert.pem` 和 `key.pem`)文件的路径,默认是 `~/.docker` 。 diff --git a/compose/install.md b/compose/install.md new file mode 100644 index 0000000..8d1e084 --- /dev/null +++ b/compose/install.md @@ -0,0 +1,63 @@ +## 安装 + +安装 Compose 之前,要先安装 Docker,在此不再赘述。 + +### PIP 安装 +这种方式最为推荐。 + +执行命令。 +```sh +$ sudo pip install -U docker-compose +``` + +安装成功后,可以查看 `docker-compose` 命令的用法。 +```sh +$ docker-compose -h +Fast, isolated development environments using Docker. + +Usage: + docker-compose [options] [COMMAND] [ARGS...] + docker-compose -h|--help + +Options: + --verbose Show more output + --version Print version and exit + -f, --file FILE Specify an alternate compose file (default: docker-compose.yml) + -p, --project-name NAME Specify an alternate project name (default: directory name) + +Commands: + build Build or rebuild services + help Get help on a command + kill Kill containers + logs View output from containers + port Print the public port for a port binding + ps List containers + pull Pulls service images + rm Remove stopped containers + run Run a one-off command + scale Set number of containers for a service + start Start services + stop Stop services + restart Restart services + up Create and start containers +``` + +之后,可以添加 bash 补全命令。 +```sh +$ curl -L https://raw.githubusercontent.com/docker/compose/1.2.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose + +``` + +### 二进制包 +发布的二进制包可以在 [https://github.com/docker/compose/releases](https://github.com/docker/compose/releases) 找到。 + +下载后直接放到执行路径即可。 + +例如,在常见的 Linux 平台上。 + +``` +$ sudo curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose +$ sudo chmod a+x /usr/local/bin/docker-compose +``` + + diff --git a/compose/intro.md b/compose/intro.md new file mode 100644 index 0000000..46fe5a8 --- /dev/null +++ b/compose/intro.md @@ -0,0 +1,10 @@ +## 简介 +Compose 项目目前在 [Github](https://github.com/docker/compose) 上进行维护,目前最新版本是 1.2.0。 + +Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。 + +Dockerfile 可以让用户管理一个单独的应用容器;而 Compose 则允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 `project`,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。 + +![](../_images/compose.png) + +该项目由 Python 编写,实际上调用了 Docker 提供的 API 来实现。 diff --git a/compose/usage.md b/compose/usage.md new file mode 100644 index 0000000..78621c4 --- /dev/null +++ b/compose/usage.md @@ -0,0 +1,7 @@ +## 使用 + +### 术语 +首先介绍几个术语。 + +* 服务(service):一个应用容器,实际上可以运行多个相同镜像的实例。 +* 项目(project):由一组关联的应用容器组成的一个完整业务单元。 diff --git a/compose/yaml_file.md b/compose/yaml_file.md new file mode 100644 index 0000000..d70b029 --- /dev/null +++ b/compose/yaml_file.md @@ -0,0 +1,223 @@ +## YAML 模板文件 + +默认的模板文件是 `docker-compose.yml`,其中定义的每个服务都必须通过 `image` 指令指定镜像或 `build` 指令(需要 Dockerfile)来自动构建。 + +其它大部分指令都跟 `docker run` 中的类似。 + +如果使用 `build` 指令,在 `Dockerfile` 中设置的选项(例如:`CMD`, `EXPOSE`, `VOLUME`, `ENV` 等) 将会自动被获取,无需在 `docker-compose.yml` 中再次设置。 + +### `image` + +指定为镜像名称或镜像 ID。如果镜像在本地不存在,`Compose` 将会尝试拉去这个镜像。 + +例如: +```sh +image: ubuntu +image: orchardup/postgresql +image: a4bc65fd +``` + +### `build` + +指定 `Dockerfile` 所在文件夹的路径。 `Compose` 将会利用它自动构建这个镜像,然后使用这个镜像。 + +``` +build: /path/to/build/dir +``` + +### `command` + +覆盖容器启动后默认执行的命令。 + +```sh +command: bundle exec thin -p 3000 +``` + +### `links` + +链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 `(SERVICE:ALIAS)` 格式都可以。 + +```sh +links: + - db + - db:database + - redis +``` + +使用的别名将会自动在服务容器中的 `/etc/hosts` 里创建。例如: + +```sh +172.17.2.186 db +172.17.2.186 database +172.17.2.187 redis +``` + +相应的环境变量也将被创建。 + +### `external_links` +链接到 docker-compose.yml 外部的容器,甚至 并非 `Compose` 管理的容器。参数格式跟 `links` 类似。 + +``` +external_links: + - redis_1 + - project_db_1:mysql + - project_db_1:postgresql +``` + + +### `ports` + +暴露端口信息。 + +使用宿主:容器 `(HOST:CONTAINER)`格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。 + +``` +ports: + - "3000" + - "8000:8000" + - "49100:22" + - "127.0.0.1:8001:8001" +``` + +*注:当使用 `HOST:CONTAINER` 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 `YAML` 将会解析 `xx:yy` 这种数字格式为 60 进制。所以建议采用字符串格式。* + + +### `expose` + +暴露端口,但不映射到宿主机,只被连接的服务访问。 + +仅可以指定内部端口为参数 + +```sh +expose: + - "3000" + - "8000" +``` + +### `volumes` + +卷挂载路径设置。可以设置宿主机路径 (`HOST:CONTAINER`) 或加上访问模式 (`HOST:CONTAINER:ro`)。 + +```sh +volumes: + - /var/lib/mysql + - cache/:/tmp/cache + - ~/configs:/etc/configs/:ro +``` + +### `volumes_from` + +从另一个服务或容器挂载它的所有卷。 + +```sh +volumes_from: + - service_name + - container_name +``` + +### `environment` + +设置环境变量。你可以使用数组或字典两种格式。 + +只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。 + +``` +environment: + RACK_ENV: development + SESSION_SECRET: + +environment: + - RACK_ENV=development + - SESSION_SECRET +``` + +### `env_file` +从文件中获取环境变量,可以为单独的文件路径或列表。 + +如果通过 `docker-compose -f FILE` 指定了模板文件,则 `env_file` 中路径会基于模板文件路径。 + +如果有变量名称与 `environment` 指令冲突,则以后者为准。 + +```sh +env_file: .env + +env_file: + - ./common.env + - ./apps/web.env + - /opt/secrets.env +``` + +环境变量文件中每一行必须符合格式,支持 `#` 开头的注释行。 + +```sh +# common.env: Set Rails/Rack environment +RACK_ENV=development +``` + +### `extends` +基于已有的服务进行扩展。例如我们已经有了一个 webapp 服务,模板文件为 `common.yml`。 +```sh +# common.yml +webapp: + build: ./webapp + environment: + - DEBUG=false + - SEND_EMAILS=false +``` + +编写一个新的 `development.yml` 文件,使用 `common.yml` 中的 webapp 服务进行扩展。 +```sh +# development.yml +web: + extends: + file: common.yml + service: webapp + ports: + - "8000:8000" + links: + - db + environment: + - DEBUG=true +db: + image: postgres +``` +后者会自动继承 common.yml 中的 webapp 服务及相关环节变量。 + + +### `net` + +设置网络模式。使用和 `docker client` 的 `--net` 参数一样的值。 + +``` +net: "bridge" +net: "none" +net: "container:[name or id]" +net: "host" +``` + +### `dns` + +配置DNS服务器。它可以是一个值,也可以是一个列表。 + +``` +dns: 8.8.8.8 +dns: + - 8.8.8.8 + - 9.9.9.9 +``` + +`working_dir, entrypoint, user, hostname, domainname, mem_limit, privileged` + +这些都是和 `docker run` 对应的一个值。 + +``` +working_dir: /code +entrypoint: /code/entrypoint.sh +user: postgresql + +hostname: foo +domainname: foo.com + +mem_limit: 1000000000 +privileged: true +``` diff --git a/fig/README.md b/fig/README.md index 2a47bcf..b75df69 100644 --- a/fig/README.md +++ b/fig/README.md @@ -1,2 +1,2 @@ #Fig -在你的应用里面添加一个 `fig.yml` 文件,并指定一些简单的内容,执行 `fig up` 它就能帮你快速建立起一个容器。 \ No newline at end of file +在你的应用里面添加一个 `fig.yml` 文件,并指定一些简单的内容,执行 `fig up` 它就能帮你快速建立起一个容器。目前已经正式更名为 [Compose](../compose/README.md)。 diff --git a/fig/cli_ref.md b/fig/cli_ref.md index a6c9bb3..a2bf8f1 100644 --- a/fig/cli_ref.md +++ b/fig/cli_ref.md @@ -138,4 +138,4 @@ $ fig scale web=2 worker=3 `DOCKER_CERT_PATH` -配置 `ca.pem` 的路径, `cert.pem` 和 `key.pem` 文件用来进行TLS验证.默认路径是 `~/.docker` 。 \ No newline at end of file +配置 `ca.pem` 的路径, `cert.pem` 和 `key.pem` 文件用来进行TLS验证.默认路径是 `~/.docker` 。 diff --git a/fig/env_ref.md b/fig/env_ref.md index 96e9f92..4592756 100644 --- a/fig/env_ref.md +++ b/fig/env_ref.md @@ -28,4 +28,4 @@ Fig 使用 Docker 链接来暴露一个服务的容器给其它容器。每一 `name_NAME` -完整合格的容器名称,例如: `DB_1_NAME=/myapp_web_1/myapp_db_1` \ No newline at end of file +完整合格的容器名称,例如: `DB_1_NAME=/myapp_web_1/myapp_db_1` diff --git a/fig/install.md b/fig/install.md index 9a81d3a..c4a099f 100644 --- a/fig/install.md +++ b/fig/install.md @@ -12,12 +12,12 @@ $(boot2docker shellinit) 关于 `Ubuntu` 还有 `其它的平台` 的安装,可以参照 [Ubuntu 安装指南(中文)](../install/ubuntu.md) 以及 [官方安装手册(英文)](https://docs.docker.com/installation/)。 -下一步,安装 Fig : +下一步,安装 Fig : ``` curl -L https://github.com/docker/fig/releases/download/1.0.1/fig-`uname -s`-`uname -m` > /usr/local/bin/fig; chmod +x /usr/local/bin/fig ``` -**如果你的 Docker 是管理员身份安装,以上命令可能也需要相同的身份。* +**如果你的 Docker 是管理员身份安装,以上命令可能也需要相同的身份。* 目前 Fig 的发行版本只支持 OSX 和 64 位的 Linux 系统。但因为它是用 Python 语言写的,所以对于其它平台上的用户,可以通过 Python 安装包来完成安装(支持的系统同样适用)。 diff --git a/fig/intro.md b/fig/intro.md index bec3994..1ceb589 100644 --- a/fig/intro.md +++ b/fig/intro.md @@ -11,7 +11,7 @@ RUN pip install -r requirements.txt 在 `fig.yml` 文件中指定应用使用的不同服务,让它们能够在一个独立的环境中一起运行: -``` +``` web: build: . command: python app.py @@ -28,7 +28,7 @@ db: ![Docker](../_images/fig-example-large.gif) -Fig 可用的命令有: +Fig 可用的命令有: * 启动、停止,和重建服务 * 查看服务的运行状态 @@ -38,7 +38,7 @@ Fig 可用的命令有: ##快速上手 我们试着让一个基本的 Python web 应用运行在 Fig 上。这个实验假设你已经知道一些 Python 知识,如果你不熟悉,但清楚概念上的东西也是没有问题的。 -首先,[安装 Docker 和 Fig](install.md) +首先,[安装 Docker 和 Fig](install.md) 为你的项目创建一个目录 @@ -46,7 +46,7 @@ Fig 可用的命令有: $ mkdir figtest $ cd figtest ``` -进入目录,创建 `app.py`,这是一个能够让 Redis 上的一个值自增的简单 web 应用,基于 Flask 框架。 +进入目录,创建 `app.py`,这是一个能够让 Redis 上的一个值自增的简单 web 应用,基于 Flask 框架。 ``` from flask import Flask @@ -63,9 +63,9 @@ def hello(): if __name__ == "__main__": app.run(host="0.0.0.0", debug=True) ``` -在 `requirements.txt` 文件中指定应用的 Python 依赖包。 +在 `requirements.txt` 文件中指定应用的 Python 依赖包。 -``` +``` flask redis ``` @@ -94,11 +94,11 @@ web: redis: image: redis ``` -这里指定了两个服务: +这里指定了两个服务: * web 服务,通过当前目录的 `Dockerfile` 创建。并且说明了在容器里面执行`python app.py ` 命令 ,转发在容器里开放的 5000 端口到本地主机的 5000 端口,连接 Redis 服务,并且挂载当前目录到容器里面,这样我们就可以不用重建镜像也能直接使用代码。 -* redis 服务,我们使用公用镜像 [redis](https://registry.hub.docker.com/_/redis/)。 -* +* redis 服务,我们使用公用镜像 [redis](https://registry.hub.docker.com/_/redis/)。 +* 现在如果执行 `fig up` 命令 ,它就会拉取 redis 镜像,启动所有的服务。 ```