快速入门: Compose和Rails

本快速入门指南介绍如何使用docker compose配置和运行一个Rails/PostgreSQL app。

定义项目

定义用来构建app的三个文件。首先由于app是运行在包含它的所有依赖的容器内,你需要定义哪些文件需要包括在容器内。这个可以使用Dockerfile来完成。这个Dockerfile包括:

  1. FROM ruby:2.3.3
  2. RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
  3. RUN mkdir /myapp
  4. WORKDIR /myapp
  5. ADD Gemfile /myapp/Gemfile
  6. ADD Gemfile.lock /myapp/Gemfile.lock
  7. RUN bundle install
  8. ADD . /myapp

上面把应用程序代码放到了镜像内,这个镜像将用来运行一个包含Ruby,Bundler和其所有的依赖的容器。

下一步,创建一个只加载Rails的bootstrap Gemfile文件。在后面将由rails new覆盖它。

  1. source ‘https://rubygems.org’
  2. gem ‘rails’, ‘5.0.0.1’

需要一个空的Gemfile.lock文件,构建Dockerfile用到。

  1. touch Gemfile.lock

最后,开始创建docker-compose.yml文件。这个文件描述了你的app由什么服务构建(数据库和web app),如何获取每一个的镜像以及需要链接它们到一起和暴露web app的端口的配置。

  1. version: ‘2’
  2. services:
  3.   db:
  4.     image: postgres
  5.   web:
  6.     build: .
  7.     command: bundle exec rails s -p 3000 -b ‘0.0.0.0’
  8.     volumes:
  9.       – .:/myapp
  10.     ports:
  11.       – "3000:3000"
  12.     depends_on:
  13.       – db

构建项目

准备好那三个文件后,就可以使用docker-compose run来生成Rails skeleton app了:

  1. docker-compose run web rails new . –force –database=postgresql –skip-bundle

首先,compose使用Dockerfile构建web服务的镜像。然后使用那个镜像生成容器,在容器内运行rails new命令。一旦完成,将生成一个全新的app:

  1. $ ls -l
  2.   total 56
  3.   -rw-r–r–   1 user  staff   215 Feb 13 23:33 Dockerfile
  4.   -rw-r–r–   1 user  staff  1480 Feb 13 23:43 Gemfile
  5.   -rw-r–r–   1 user  staff  2535 Feb 13 23:43 Gemfile.lock
  6.   -rw-r–r–   1 root  root   478 Feb 13 23:43 README.rdoc
  7.   -rw-r–r–   1 root  root   249 Feb 13 23:43 Rakefile
  8.   drwxr-xr-x   8 root  root   272 Feb 13 23:43 app
  9.   drwxr-xr-x   6 root  root   204 Feb 13 23:43 bin
  10.   drwxr-xr-x  11 root  root   374 Feb 13 23:43 config
  11.   -rw-r–r–   1 root  root   153 Feb 13 23:43 config.ru
  12.   drwxr-xr-x   3 root  root   102 Feb 13 23:43 db
  13.   -rw-r–r–   1 user  staff   161 Feb 13 23:35 docker-compose.yml
  14.   drwxr-xr-x   4 root  root   136 Feb 13 23:43 lib
  15.   drwxr-xr-x   3 root  root   102 Feb 13 23:43 log
  16.   drwxr-xr-x   7 root  root   238 Feb 13 23:43 public
  17.   drwxr-xr-x   9 root  root   306 Feb 13 23:43 test
  18.   drwxr-xr-x   3 root  root   102 Feb 13 23:43 tmp
  19.   drwxr-xr-x   3 root  root   102 Feb 13 23:43 vendor

如果这个时候或之后编辑了Gemfile,需要重新构建镜像。

  1. docker-compose build

连接数据库

使用如何内容替换config/database.yml文件:

  1. development: &default
  2.   adapter: postgresql
  3.   encoding: unicode
  4.   database: myapp_development
  5.   pool: 5
  6.   username: postgres
  7.   password:
  8.   host: db
  9.  
  10. test:
  11.   <<: *default
  12.   database: myapp_test

开始启动app:

  1. docker-compose up

如果一切正常,将会看到PostgrepSQL的输出,然后再过几秒钟,将看到

  1. myapp_web_1 | [2014-01-17 17:16:29] INFO  WEBrick 1.3.1
  2. myapp_web_1 | [2014-01-17 17:16:29] INFO  ruby 2.2.0 (2014-12-25) [x86_64-linux-gnu]
  3. myapp_web_1 | [2014-01-17 17:16:29] INFO  WEBrick::HTTPServer#start: pid=1 port=3000

最后,在另一个终端创建一个数据库:

  1. docker-compose run web rails db:create

现在app已经运行在主机的3000端口。
虚拟化技术

快速入门: Compose和Django

这个快速入门指南将演示如何使用docker compose来配置和运行一个简单的Django/PostgrepSQL app。

定义项目组件

需要为这个项目创建一个Dockerfile,一个Python依赖文件和一个docker-compose.yml文件。
1.创建一个空的项目目录。
可以以容易记忆的名称命名项目。这个目录是你的应用程序镜像的上下文。此目录应该只包含用来构建镜像的资源。
2.在项目目录中创建一个新的Dockerfile文件。
Dockerfile通过一个或多个构建命令来定义应用程序镜像内容。一旦构建完成,可以在容器运行这个镜像。
3.添加如下内容到Dockerfile文件。

  1. FROM python:2.7
  2.  ENV PYTHONUNBUFFERED 1
  3.  RUN mkdir /code
  4.  WORKDIR /code
  5.  ADD requirements.txt /code/
  6.  RUN pip install -r requirements.txt
  7.  ADD . /code/

这个Dockerfile从一个Python 2.7 base镜像开始构建新镜像。然后添加了一个新的code目录到此镜像。最后安装定义在requirements.txt文件的python依赖。
4.保存并关闭Dockerfile。
5.在项目目录创建requirements.txt文件。
在Dockerfile中的RUN pip install -r requirements.txt命令需要用到这个文件。
6.添加如下内容到requirements.txt.

  1. Django
  2.  psycopg2

7.保存并关闭requirements.txt文件。
8.在项目目录中创建一个docker-compose.yml文件。
这个docker-compose.yml文件描述组成你的app的服务。在这个示例中那么服务是web server和database。这个compose文件也描述了这些服务使用哪个docker镜像,它们如何链接到一起以及它们可能需要挂载到容器内的数据卷。最后这个docker-compose.yml文件描述这些服务暴露了哪个端口。
9.添加如何内容到docker-compose.yml文件。

  1. version: ‘2’
  2.  services:
  3.    db:
  4.      image: postgres
  5.    web:
  6.      build: .
  7.      command: python manage.py runserver 0.0.0.0:8000
  8.      volumes:
  9.        – .:/code
  10.      ports:
  11.        – "8000:8000"
  12.      depends_on:
  13.        – db

这个文件定义了两个服务:db服务和web服务。
10.保存并关闭docker-compose.yml文件。

创建一个Django项目

在本步骤中,我们通过构建在上一步骤中定义的镜像来创建一个Django项目。
1.切换到项目目录的根目录。
2.使用docker-compose命令创建一个Django项目。

  1. docker-compose run web django-admin.py startproject composeexample .

指示compose使用了web服务的镜像和配置文件在容器中运行django-admin.py start project composeexample命令。由于web镜像还不存在,compose就按照在docker-compose.yml中的build: .行定义的在当前目录构建镜像。
一旦web服务镜像构建完成,compose就运行它并在容器内执行django-admin.py startproject命令。这个命令创建了Django项目使用到的一系列文件和目录。
3.当docker-compose命令完成后,列出项目的内容。

  1. $ ls -l
  2.  drwxr-xr-x 2 root   root   composeexample
  3.  -rw-rw-r– 1 user   user   docker-compose.yml
  4.  -rw-rw-r– 1 user   user   Dockerfile
  5.  -rwxr-xr-x 1 root   root   manage.py
  6.  -rw-rw-r– 1 user   user   requirements.txt

如果是在Linux运行的docker,django-admin文件所有者应该是root。这是因为容器以root用户运行。更改这个新文件的所有者。

  1. sudo chown -R $USER:$USER .

如果在Mac或Windows运行的Docker,你应该已经是这些文件的所有者了,包括那些由django-admin生成的文件。

  1. $ ls -l
  2.     total 32
  3.     -rw-r–r–  1 user  staff  145 Feb 13 23:00 Dockerfile
  4.     drwxr-xr-x  6 user  staff  204 Feb 13 23:07 composeexample
  5.     -rw-r–r–  1 user  staff  159 Feb 13 23:02 docker-compose.yml
  6.     -rwxr-xr-x  1 user  staff  257 Feb 13 23:07 manage.py
  7.     -rw-r–r–  1 user  staff   16 Feb 13 23:01 requirements.txt

连接数据库

在本步骤,我们来设置Django数据库的连接。
1.在项目目录中,编辑composeexample/settings.py文件。
2.使用如下行替换DATABASES = …

  1. DATABASES = {
  2.      ‘default’: {
  3.          ‘ENGINE’: ‘django.db.backends.postgresql’,
  4.          ‘NAME’: ‘postgres’,
  5.          ‘USER’: ‘postgres’,
  6.          ‘HOST’: ‘db’,
  7.          ‘PORT’: 5432,
  8.      }
  9.  }

这些设置取决于在docker-compose.yml指定的postgres docker镜像。
3.保存并关闭文件。
4.执行docker-compose up命令。

  1. $ docker-compose up
  2.  Starting composepractice_db_1…
  3.  Starting composepractice_web_1…
  4.  Attaching to composepractice_db_1, composepractice_web_1
  5.  …
  6.  db_1  | PostgreSQL init process complete; ready for start up.
  7.  …
  8.  db_1  | LOG:  database system is ready to accept connections
  9.  db_1  | LOG:  autovacuum launcher started
  10.  ..
  11.  web_1 | Django version 1.8.4, using settings ‘composeexample.settings’
  12.  web_1 | Starting development server at http://0.0.0.0:8000/
  13.  web_1 | Quit the server with CONTROL-C.

在这时候,Django app已经运行在docker主机上的8000端口。
虚拟化技术

Docker Compose入门学习

在本文我们来学习使用docker compose来构建一个简单的Python web应用程序。这个应用程序使用的是Flask框架并在Redis维护一个点击计数器。虽然这个示例使用到了Python,不过即使你不熟悉Python也可以很容易理解这些操作。

第一步:配置

1.创建一个项目目录:

  1. $ mkdir composetest
  2. $ cd composetest

2.在项目目录中创建一个app.py文件并复制下面的内容到这个文件:

  1. from flask import Flask
  2. from redis import Redis
  3.  
  4. app = Flask(__name__)
  5. redis = Redis(host=’redis’, port=6379)
  6.  
  7. @app.route(‘/’)
  8. def hello():
  9.     count = redis.incr(‘hits’)
  10.     return ‘Hello World! I have been seen {} times.n’.format(count)
  11.  
  12. if __name__ == "__main__":
  13.     app.run(host="0.0.0.0", debug=True)

3.在项目目录创建另一个文件requirements.txt并复制下面这些内容:

  1. flask
  2. redis

这个文件定义了应用程序的依赖。

第二步:创建一个Dockerfile

在这个步骤中,我们创建一个Dockerfile用来构建docker镜像。这个镜像包含了Python应用程序所需的所有依赖,包含Python。

在项目目录中,创建一个Dockerfile文件并复制如下内容:

  1. FROM python:3.4-alpine
  2. ADD . /code
  3. WORKDIR /code
  4. RUN pip install -r requirements.txt
  5. CMD ["python", "app.py"]

这个文件解释如下:

  • 从Python 3.4镜像开始构建镜像
  • 添加当前的目录到镜像中的/code目录
  • 设置工作目录为/code
  • 安装Python依赖
  • 设置容器的默认命令为python app.py
  • 第三步:在compose文件中定义服务

    在项目目录中创建docker-compose.yml文件并复制如下内容:

    1. version: ‘2’
    2. services:
    3.   web:
    4.     build: .
    5.     ports:
    6.      – "5000:5000"
    7.     volumes:
    8.      – .:/code
    9.   redis:
    10.     image: "redis:alpine"

    compose文件定义了两个服务,web和redis。web服务部分介绍如下:

  • 使用了一个从当前目录的Dockerfile构建的镜像。
  • 映射容器的5000端口到主机的5000端口。
  • 挂载主机上的项目目录到容器内的/code目录,这样更新代码时就不需要重建镜像了。
  • redis服务使用了从docker hub registry拉取的公共Redis镜像。

    第四步:使用compose构建和运行你的app

    1.从项目目录,启动你的应用程序。

    1. $ docker-compose up
    2.  Pulling image redis…
    3.  Building web…
    4.  Starting composetest_redis_1…
    5.  Starting composetest_web_1…
    6.  redis_1 | [8] 02 Jan 18:43:35.576 # Server started, Redis version 2.8.3
    7.  web_1   |  * Running on http://0.0.0.0:5000/
    8.  web_1   |  * Restarting with stat

    compose拉取一个redis镜像,为你的代码构建了一个镜像并启动你所定义的服务。

    2.在浏览器键入http://0.0.0.0:5000/来查看你的应用程序运行情况。
    3.刷新页面。数字应该会递增了。

    第五步:更新应用程序

    因为使用了数据卷把应用程序代码挂载到了容器里,可以对代码进行更新,然后就会马上看到更新了,而不需要重建镜像。
    1.更新app.py并保存。例如:

    1. return ‘Hello from Docker! I have been seen {} times.n’.format(count)

    2.在浏览器中刷新app。应该能看到更新了。

    第六步:尝试一些其它命令

    如果想让你的服务在后台运行,传递-d参数到docker-compose up并使用docker-compose ps查看现在运行的是什么。

    1. $ docker-compose up -d
    2. Starting composetest_redis_1…
    3. Starting composetest_web_1…
    4.  
    5. $ docker-compose ps
    6. Name                 Command            State       Ports
    7. ——————————————————————-
    8. composetest_redis_1   /usr/local/bin/run         Up
    9. composetest_web_1     /bin/sh -c python app.py   Up      5000->5000/tcp

    docker-compose run命令允许你对你的服务运行一次性的命令。例如,查看web服务有哪些可用的环境变量:

    1. $ docker-compose run web env

    通过docker-compose –help可以查看其它可用的命令。

    如果使用了docker-compose up -d启动应用,当不需要时可能要停止服务:

    1. $ docker-compose stop

    使用down命令可以关掉所有,删除整个容器。传递–volume也会删除由redis容器使用的数据卷:

    1. $ docker-compose down –volumes

    安装Docker Compose

    可以在macOS,Windows和64-bit Linux运行compose。下面介绍如何安装它。
    1.安装Docker Engine:
    这里不再介绍,参考官方文档

  • macOS安装
  • Windows安装
  • Ubuntu安装
  • 其它系统安装
  • 2.如果安装的是Docker Toolbox,它包括了Engine和Compose,所以Mac和Windows用户在这里就安装完成了。其它用户继续。
    3.到https://github.com/docker/compose/releases
    4.按照上面页面的介绍,执行curl命令。
    如下命令下载compose:

    1. $ curl -L "https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

    5.增加执行权限

    1. chmod +x /usr/local/bin/docker-compose

    6.可选地,为bash和zsh shell安装command completion
    7.测试安装

    1. $ docker-compose –version
    2.  docker-compose version: 1.9.0

    其它安装选项

    使用pip安装

    可以使用pip从pypi安装compose。如果使用pip安装,推荐使用virtualenv,因此许多系统的python系统包与docker-compose的依赖冲突。

    1. pip install docker-compose

    注意:需要pip version 6.0或以上版本。

    使用容器安装

    compose也可以运行在容器内,使用一个小的bash脚本。

    1. $ curl -L https://github.com/docker/compose/releases/download/1.9.0/run.sh > /usr/local/bin/docker-compose
    2. $ chmod +x /usr/local/bin/docker-compose

    Docker Compose概述

    Compose是用来定义和运行多个容器docker应用程序的工具。可以使用一个compose文件来配置你的应用程序服务。然后使用一个命令根据配置文件来创建和启动所有的服务。

    Compose非常适合用于开发,测试和临时环境,也包括CI工作流。

    使用compose就三步。
    1.使用Dockerfile定义应用程序的环境,以便可以在任何地方重建环境。
    2.在docker-compose.yml定义服务构建你的应用程序,以便它们能在一个隔离的环境一起运行。
    3.最后,执行docker-compose up然后compose会启动和运行整个app。

    一个docker-compose.yml类似如下:

    1. version: ‘2’
    2. services:
    3.   web:
    4.     build: .
    5.     ports:
    6.     – "5000:5000"
    7.     volumes:
    8.     – .:/code
    9.     – logvolume01:/var/log
    10.     links:
    11.     – redis
    12.   redis:
    13.     image: redis
    14. volumes:
    15.   logvolume01: {}

    compose提供了管理应用程序整个生命周期的命令:

  • 启动,停止和重建服务
  • 查看运行中服务的状态
  • 输出运行中服务的日志
  • 在服务上运行一次性命令
  • 功能

    单台主机多个隔离环境

    compose使用一个项目名称相互隔离环境。可以在几个不同的上下文使用这个项目名称:

  • 在一个开发主机创建单个环境的多个副本(例如,你想为一个项目中的每个功能分支运行一个稳定的副本)
  • 在CI服务器上,为了使构建不会相互干扰,可以将项目名称设置为唯一的内部版本号
  • 在共享主机或开发主机上,为了避免不同的可能使用相同的服务名称的项目互相干扰。
  • 默认项目名称是项目目录的basename。可以通过使用-p命令行选项或COMPOSE_PROJECT_NAME环境变量设置一个自定义项目名称。

    容器创建时保留数据卷数据

    compose保留用于服务的所有数据卷。当执行docker-compose up时,如果找到先前用到数据卷的容器,就把数据卷从旧的容器复制到新的容器。这样确保了你保存到数据卷的数据不会丢失。

    只重建有更新的容器

    compose缓存用于创建容器的配置。当重启一个没有更新的服务时,compose重用现有的容器。重用容器意味着你可以快速改变你的环境。

    compose支持在compose文件中使用变量。可以使用这些变量为不同的环境或不同的用户自定义组件。

    可以使用extends字段或通过创建多个compose文件扩展你的compose文件。

    常见用例

    compose可以以许多不同的方式使用。一些常见的用例如下:

    开发环境

    当正在开发一个软件时,能够在一个隔离的环境运行应用程序并与之交互很重要。compose命令行工具可以用来创建这样的环境并与之交互。

    compose文件提供了一个方法来记录和配置所有的应用程序的服务依赖(数据库,队列,缓存,web服务API等)。使用这个compose命令行工具可以为每个依赖创建和启动一个或多个容器。

    总之,这些功能为开发人员提供了一个方便的方法来开始项目。compose把很多页的开发人员入门指南减小到单个机器可读的compose文件和一些命令。

    自动测试环境

    持续部署或持续集成的一个重要部分是自动测试套件。自动端到端测试依赖运行测试的环境。compose为你的测试套件提供了一个方便的方法来创建和销毁隔离的测试环境。通过在一个compose文件中定义完整的环境,只需要几个命令就可以创建和销毁这些环境。

    1. $ docker-compose up -d
    2. $ ./run_tests
    3. $ docker-compose down

    单主机部署

    compose传统上专注在开发和测试工作流上,不过目前每次发布compose都在使它能够在生产环境在使用有所进展。可以使用compose来部署到一个远程的docker engine。

    Docker命令行参考(40) – docker service update更新服务

    1. Usage:  docker service update [OPTIONS] SERVICE
    2.  
    3. Update a service
    4.  
    5. Options:
    6.       –args string                    Service command args
    7.       –constraint-add value           Add or update placement constraints (default [])
    8.       –constraint-rm value            Remove a constraint (default [])
    9.       –container-label-add value      Add or update container labels (default [])
    10.       –container-label-rm value       Remove a container label by its key (default [])
    11.       –endpoint-mode string           Endpoint mode (vip or dnsrr)
    12.       –env-add value                  Add or update environment variables (default [])
    13.       –env-rm value                   Remove an environment variable (default [])
    14.       –help                           Print usage
    15.       –image string                   Service image tag
    16.       –label-add value                Add or update service labels (default [])
    17.       –label-rm value                 Remove a label by its key (default [])
    18.       –limit-cpu value                Limit CPUs (default 0.000)
    19.       –limit-memory value             Limit Memory (default 0 B)
    20.       –log-driver string              Logging driver for service
    21.       –log-opt value                  Logging driver options (default [])
    22.       –mount-add value                Add or update a mount on a service
    23.       –mount-rm value                 Remove a mount by its target path (default [])
    24.       –name string                    Service name
    25.       –publish-add value              Add or update a published port (default [])
    26.       –publish-rm value               Remove a published port by its target port (default [])
    27.       –replicas value                 Number of tasks (default none)
    28.       –reserve-cpu value              Reserve CPUs (default 0.000)
    29.       –reserve-memory value           Reserve Memory (default 0 B)
    30.       –restart-condition string       Restart when condition is met (none, on-failure, or any)
    31.       –restart-delay value            Delay between restart attempts (default none)
    32.       –restart-max-attempts value     Maximum number of restarts before giving up (default none)
    33.       –restart-window value           Window used to evaluate the restart policy (default none)
    34.       –stop-grace-period value        Time to wait before force killing a container (default none)
    35.       –update-delay duration          Delay between updates
    36.       –update-failure-action string   Action on update failure (pause|continue) (default "pause")
    37.       –update-parallelism uint        Maximum number of tasks updated simultaneously (0 to update all at once) (default 1)
    38.   -u, –user string                    Username or UID
    39.       –with-registry-auth             Send registry authentication details to Swarm agents
    40.   -w, –workdir string                 Working directory inside the container

    通过指定的参数描述更新服务。这个命令必须在manager节点执行。这些参数与docker service create命令的参数一样。

    示例

    更新服务

    1. $ docker service update –limit-cpu 2 redis

    添加和删除挂载

    使用–mount-add 或 –mount-rm选项添加或删除一个服务的bind-mounts或volumes。

    下面的示例创建一个服务并挂载test-data数据卷到/somewhere。下一步是更新服务添加挂载一个other-volume数据卷到/shomewhere-else,最后一步是取消/somewhere挂载点,将会删除test-data数据卷。每个命令返回服务名称。

  • –mount-add接受与service create的–mount选项一样的参数。
  • –mount-rm参数指定的是挂载点的目标路径。
    1. $ docker service create
    2.     –name=myservice
    3.     –mount
    4.       type=volume,source=test-data,target=/somewhere
    5.     nginx:alpine
    6.     myservice
    7.  
    8. myservice
    9.  
    10. $ docker service update
    11.     –mount-add
    12.       type=volume,source=other-volume,target=/somewhere-else
    13.     myservice
    14.  
    15. myservice
    16.  
    17. $ docker service update –mount-rm /somewhere myservice
    18.  
    19. myservice

    Docker命令行参考(39) – docker service scale缩放服务

    1. Usage:  docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS…]
    2.  
    3. Scale one or multiple services
    4.  
    5. Options:
    6.       –help   Print usage

    示例

    缩放一个服务

    docker service scale命令可以按照期望的副本数量放大或缩小服务。命令是立即返回的,不过实际上缩放服务需要一定的时间。要停止服务的所有副本但要保持服务活跃可以设置scale为0。

    例如,下面的命令缩放frontend服务为50个任务。

    1. $ docker service scale frontend=50
    2. frontend scaled to 50

    紧接着运行docker service ls,会看到目前的副本数量。

    1. $ docker service ls –filter name=frontend
    2.  
    3. ID            NAME      REPLICAS  IMAGE         COMMAND
    4. 3pr5mlvu3fh9  frontend  15/50     nginx:alpine

    也可以使用docker service update命令缩放服务。因此下面的命令是等同的:

    1. $ docker service scale frontend=50
    2. $ docker service update –replicas=50 frontend

    缩放多个服务

    docker service scale命令可以一次性缩放多个服务。例如的示例同时缩放backend和frontend服务:

    1. $ docker service scale backend=3 frontend=5
    2. backend scaled to 3
    3. frontend scaled to 5
    4.  
    5. $ docker service ls
    6. ID            NAME      REPLICAS  IMAGE         COMMAND
    7. 3pr5mlvu3fh9  frontend  5/5       nginx:alpine
    8. 74nzcxxjv6fq  backend   3/3       redis:3.0.6

    Docker命令行参考(38) – docker service inspect显示服务详细信息

    1. Usage:  docker service inspect [OPTIONS] SERVICE [SERVICE…]
    2.  
    3. Display detailed information on one or more services
    4.  
    5. Options:
    6.   -f, –format string   Format the output using the given go template
    7.       –help            Print usage
    8.       –pretty          Print the information in a human friendly format.

    查看指定服务的信息。这个命令必须在manager节点上执行。

    默认情下,以JSON数组输出结果。如果指定了格式,就按给定的格式模板格式化每个结果。

    示例

    通过名称或ID查看服务

    例如,有如下服务:

    1. $ docker service ls
    2. ID            NAME      REPLICAS  IMAGE         COMMAND
    3. dmu1ept4cxcf  redis     3/3       redis:3.0.6

    docker service inspect redis和docker service inspect dmu1ept4cxcf都是输出同样的结果:

    1. $ docker service inspect redis
    2. [
    3.     {
    4.         "ID": "dmu1ept4cxcfe8k8lhtux3ro3",
    5.         "Version": {
    6.             "Index": 12
    7.         },
    8.         "CreatedAt": "2016-06-17T18:44:02.558012087Z",
    9.         "UpdatedAt": "2016-06-17T18:44:02.558012087Z",
    10.         "Spec": {
    11.             "Name": "redis",
    12.             "TaskTemplate": {
    13.                 "ContainerSpec": {
    14.                     "Image": "redis:3.0.6"
    15.                 },
    16.                 "Resources": {
    17.                     "Limits": {},
    18.                     "Reservations": {}
    19.                 },
    20.                 "RestartPolicy": {
    21.                     "Condition": "any",
    22.                     "MaxAttempts": 0
    23.                 },
    24.                 "Placement": {}
    25.             },
    26.             "Mode": {
    27.                 "Replicated": {
    28.                     "Replicas": 1
    29.                 }
    30.             },
    31.             "UpdateConfig": {},
    32.             "EndpointSpec": {
    33.                 "Mode": "vip"
    34.             }
    35.         },
    36.         "Endpoint": {
    37.             "Spec": {}
    38.         }
    39.     }
    40. ]
    1. $ docker service inspect dmu1ept4cxcf
    2. [
    3.     {
    4.         "ID": "dmu1ept4cxcfe8k8lhtux3ro3",
    5.         "Version": {
    6.             "Index": 12
    7.         },
    8.         …
    9.     }
    10. ]

    使用pretty-print查看服务

    可以使用–pretty选项以人类可读的格式打印输出,而不是默认的JSON格式输出。

    1. $ docker service inspect –pretty frontend
    2. ID:   c8wgl7q4ndfd52ni6qftkvnnp
    3. Name:   frontend
    4. Labels:
    5.  – org.example.projectname=demo-app
    6. Mode:   REPLICATED
    7.  Replicas:    5
    8. Placement:
    9. UpdateConfig:
    10.  Parallelism: 0
    11. ContainerSpec:
    12.  Image:   nginx:alpine
    13. Resources:
    14. Ports:
    15.  Name =
    16.  Protocol = tcp
    17.  TargetPort = 443
    18.  PublishedPort = 4443

    查找服务的任务数

    –format选项可以用来获取关于服务的指定信息。例如,下面的命令输出redis服务的副本数。

    1. $ docker service inspect –format='{{.Spec.Mode.Replicated.Replicas}}’ redis
    2. 10

    Docker命令行参考(37) – docker service create创建一个服务

    1. Usage:  docker service create [OPTIONS] IMAGE [COMMAND] [ARG…]
    2.  
    3. Create a new service
    4.  
    5. Options:
    6.       –constraint value               Placement constraints (default [])
    7.       –container-label value          Service container labels (default [])
    8.       –endpoint-mode string           Endpoint mode (vip or dnsrr)
    9.   -e, –env value                      Set environment variables (default [])
    10.       –help                           Print usage
    11.   -l, –label value                    Service labels (default [])
    12.       –limit-cpu value                Limit CPUs (default 0.000)
    13.       –limit-memory value             Limit Memory (default 0 B)
    14.       –log-driver string              Logging driver for service
    15.       –log-opt value                  Logging driver options (default [])
    16.       –mode string                    Service mode (replicated or global) (default "replicated")
    17.       –mount value                    Attach a mount to the service
    18.       –name string                    Service name
    19.       –network value                  Network attachments (default [])
    20.   -p, –publish value                  Publish a port as a node port (default [])
    21.       –replicas value                 Number of tasks (default none)
    22.       –reserve-cpu value              Reserve CPUs (default 0.000)
    23.       –reserve-memory value           Reserve Memory (default 0 B)
    24.       –restart-condition string       Restart when condition is met (none, on-failure, or any)
    25.       –restart-delay value            Delay between restart attempts (default none)
    26.       –restart-max-attempts value     Maximum number of restarts before giving up (default none)
    27.       –restart-window value           Window used to evaluate the restart policy (default none)
    28.       –stop-grace-period value        Time to wait before force killing a container (default none)
    29.       –update-delay duration          Delay between updates
    30.       –update-failure-action string   Action on update failure (pause|continue) (default "pause")
    31.       –update-parallelism uint        Maximum number of tasks updated simultaneously (0 to update all at once) (default 1)
    32.   -u, –user string                    Username or UID
    33.       –with-registry-auth             Send registry authentication details to Swarm agents
    34.   -w, –workdir string                 Working directory inside the container

    按指定参数所述创建服务。这个命令必须运行在manager节点上。

    示例

    创建一个服务

    1. $ docker service create –name redis redis:3.0.6
    2. dmu1ept4cxcfe8k8lhtux3ro3
    3.  
    4. $ docker service ls
    5. ID            NAME   REPLICAS  IMAGE        COMMAND
    6. dmu1ept4cxcf  redis  1/1       redis:3.0.6

    创建一个5个副本任务的服务(–replicas)

    使用–replicas参数设置副本服务的副本任务数。下面的命令创建一个5个副本任务的redis服务:

    1. $ docker service create –name redis –replicas=5 redis:3.0.6
    2. 4cdgfyky7ozwh3htjfw0d12qv

    上面的命令设置了服务期望的任务数。虽然命令立即返回了,实际上完成服务部署需要一定的时间。REPLICAS列显示了实际上部署的和期望部署的副本任务数。

    下面的示例中期望的副本数是5,不过副本运行的任务数是3:

    1. $ docker service ls
    2. ID            NAME    REPLICAS  IMAGE        COMMAND
    3. 4cdgfyky7ozw  redis   3/5       redis:3.0.7

    一旦创建了所有的任务且为RUNNING状态,任务的实际数量就等于期望的数量:

    1. $ docker service ls
    2. ID            NAME    REPLICAS  IMAGE        COMMAND
    3. 4cdgfyky7ozw  redis   5/5       redis:3.0.7

    指定滚动更新策略创建一个服务

    1. $ docker service create
    2.   –replicas 10
    3.   –name redis
    4.   –update-delay 10s
    5.   –update-parallelism 2
    6.   redis:3.0.6

    当执行上面的service update命令时,调度器同时更新最大2个任务,间隔更新时间为10s。

    设置环境变量(-e,–env)

    为在一个服务中的所有任务设置环境变量。例如:

    1. $ docker service create –name redis_2 –replicas 5 –env MYVAR=foo redis:3.0.6

    设置服务的metadata(-l,–label)

    一个label是key=value键值对应用到服务的元数据。要为服务设置两个labels,执行:

    1. $ docker service create
    2.   –name redis_2
    3.   –label com.example.foo="bar"
    4.   –label bar=baz
    5.   redis:3.0.6

    添加bind-mounts或volumes

    docker支持两种不同的挂载,允许容器从其他容器或主机操作系统上的文件或目录读取或写入。这些类型是data volumes和bind-mounts。

    bind-mount容器可以直接操作主机上的文件。bind-mount可以是只读或读写。例如,一个容器可能通过绑定挂载主机的/etc/resolv.conf来共享主机的DNS信息或一个容器可能写入日志到主机的/var/log/myContainerLogs目录。如果使用了bind-mounts且你的主机与容器有不同的权限概念,访问控制或其它这样的信息,你可能会遇到可移植性的问题。

    一个命名数据卷是从用于创建容器的镜像和主机分离出容器所需的持久化数据的一个机制。命名数据卷由docker创建和管理,即使当没有容器使用它时,一个命名数据卷仍然会存在。在命名数据卷的数据可以在容器和主机之间共享,也可以在多个容器之间共享。docker使用一个数据卷驱动来创建,管理和挂载数据卷。可以使用docker的相关命令备份或恢复数据卷。

    考虑这样一个情景,你有一个镜像是用来启动一个轻量级的web server的,然后你用这个镜像作为base镜像,把网站的HTML文件复制到这个镜像。每个网站有更新时,你需要更新这个镜像并重新部署容器。一个更好的解决方案是把网站存储到一个命名数据卷中,当容器启动时这个数据卷就会附着到你的web server。要更新这个网站,只需要更新命名数据卷。

    下面的表格是应用到bind-mounts和named volumes的选项:

    选项 必要 描述
    type mount的类型,可以是volume或bind。如果不指定type,默认是volume。

  • volume: 挂载一个数据卷到容器中。
  • bind: 从主机绑定挂载一个目录或文件到容器中。
  • src或source 用在当type=bind时
  • type=volume: src是指定数据卷名称的可选的一种方式(例如,src=my-volume)。如果命名数据卷不存在,则docker会自动创建它。如果没有指定src,则分配一个随机的名称给数据卷,并保证这个名称在主机上是唯一的,不过可能在集群范围不是唯一的。一个随机命名数据卷与容器有相同的生命周期,当容器被销毁时此数据卷也将销毁(销毁取决于service update或当scaling或重新负载均衡服务时)。
  • type=bind: src是必须的,并需要指定文件或目录的绝对路径(例如src=/path/on/host/)。如果文件或目录不存在将会报错。
  • dst 或 destination 或 target 容器内挂载的路径。例如/some/path/in/container/。如果在容器文件系统不存在这个路径,engine将在挂载数据卷或绑定挂载之前先创建这个目录。
    readonly 或 ro Engine挂载绑定和数据卷默认是读写的,除非设置了readonly选项。

  • true或1或no:挂载绑定或数据卷只读。
  • false或0: 挂载绑定或数据卷读写。
  • 绑定传播(Bind Propagation)

    绑定传播指的是在给定的绑定挂载或命名数据卷内创建的挂载是否可以传播到那个挂载的副本。如一个挂载点/mnt,也挂载到/tmp上。传播设置控制在/tmp/a的挂载是否也挂载到/mnt/a。每个传播设置具有递归对应点。在递归情况下,假设/tmp/a也挂载为/foo。传播设置控制/mnt/a和/或/tmp/a是否存在。

    bind-mounts和volume mounts的bind-propagation选项的默认值为rprivate,并只能对bind-mounts可设置。换句话说,命名数据卷不支持绑定传播。

  • shared: 原始挂载的子挂载暴露给副本挂载,副本挂载的子挂载也传播到原始挂载。
  • slave:与shared挂载类似,不过只有一个方向。如果原始挂载暴露一个子挂载,副本挂载可以看到。不过,如果副本挂载暴露一个子挂载,原始挂载无法看到。
  • private:挂载是私有的。在它之内的子挂载不暴露给副本挂载,且副本挂载的子挂载不暴露给原始挂载。
  • rshared:与shared一样,但传播也扩展到嵌套在任何原始或复制挂载点内的挂载点。
  • rslave:与slave相同,但是传播也延伸到嵌套在任何原始或复制挂载点内的挂载点。
  • rprivate:默认值。与private相同,意味着原始或复制挂载点内任何地方的任何挂载点都不会在任一方向传播。
  • 更多信息请查看sharedsubtree

    命名数据卷选项

    下面的选项只能用于命名数据卷(type=volume)。

    选项 描述
    volume-driver 数据卷所使用的数据卷驱动插件名称。默认为local,使用local数据卷驱动时当数据卷不存在时会自动创建。
    volume-label 创建数据卷时应用给它的一个或多个自定义元数据(“labels”)。例如,volume-label=mylabel=hello-world,my-other-label=hello-mars。
    volume-nocopy 默认下,如果附着一个空的数据卷到一个容器,在容器的挂载路径已经存在的文件或目录,Engine将复制这些文件和目录到数据卷中。设置vloume-nocopy将禁止从容器的文件系统复制文件到挂载的空数据卷。
    值是可选的:

  • true或1: 这是默认值。禁止复制。
  • false或0: 启用复制。
  • volume-opt 给定数据卷驱动的特定选项,当创建数据卷时将传递给驱动。选项格式为以逗号分隔的键/值对列表,例如volume-opt=some-option=some-value,some-other-option=some-other-value。

    “–mount”和”–volume”的异同

    –mount选项支持docker run的-v或–volume的大多数选项。除了一些重要的例外:

  • –mount标志可以为每一个数据卷指定一个数据卷驱动及其选项,而不需要提供创建好数据卷。相比之一,docker run使用–volume-driver指定一个用于所有数据卷的数据卷驱动。
  • –mount标志允许你在数据卷创建前为数据卷指定自定义的元数据(“labels”)
  • 当–mount和type=bind一起使用时,host-path必须对应到一个主机上存在的路径。不会为你自动创建路径且当路径不存在时服务创建将失败。
  • –mount标志不允许使用Z或z重新label数据卷,因为这个已经用于selinux了。
  • 使用一个命名数据卷创建服务

    下面的示例使用一个命名数据卷来创建服务:

    1. $ docker service create
    2.   –name my-service
    3.   –replicas 3
    4.   –mount type=volume,source=my-volume,destination=/path/in/container,volume-label="color=red",volume-label="shape=round"
    5.   nginx:alpine

    对于服务的每一个副本,engine从部署任务上的默认的”local”数据卷驱动请求一个名称为”my-volume”的数据卷。如果数据卷不存在,engine就创建一个新的并应用”color”和”shape” labels。

    当任务启动后,数据卷挂载到容器内的/path/in/container。

    要注意那个默认的”local”数据卷是本地范围的数据卷驱动。意思是使用哪里的驱动取决于任务部署的位置。如果运行在容器内的软件没有设计为写入数据到相同位置的并发进程,那么多个容器同时写入单个共享数据卷可能会损坏数据。同时也要考虑容器可能会被swarm编排器重新调度并部署到一个不同的节点。

    使用匿名数据卷创建服务

    下面的命令使用一个挂载到/path/in/container的匿名数据卷创建一个3个副本的服务:

    1. $ docker service create
    2.   –name my-service
    3.   –replicas 3
    4.   –mount type=volume,destination=/path/in/container
    5.   nginx:alpine

    在这个示例中,没有为数据卷指定[source],所以每个任务将创建一个新的数据卷。这保证了每个任务能得到它自己的数据卷且不会与其它任务共享数据卷。当任务被删除时,匿名数据卷同样将被删除。

    使用绑定挂载(bind-mounted)主机目录创建服务

    下面的示例在容器内的/path/in/container绑定挂载主机的目录/path/on/host:

    1. $ docker service create
    2.   –name my-service
    3.   –mount type=bind,source=/path/on/host,destination=/path/in/container
    4.   nginx:alpine

    设置服务模式

    服务模式决定着这是副本服务还是全局服务。一个副本服务指定数量的任务,而全局服务在集群中的每个活跃节点都运行任务。
    下面的命令创建了一个全局服务:

    1. $ docker service create
    2.  –name redis_2
    3.  –mode global
    4.  redis:3.0.6

    指定服务约束(–constraint)

    可以通过定义约束表达式来限制可用于任务调度的节点。多个约束查找节点时,需要满足每个表达式(AND匹配)。 约束可以匹配节点或docker engine的labels,如下:

    节点属性 匹配 示例
    node.id 节点ID node.id == 2ivku8v2gvtg4
    node.hostname 节点主机名 node.hostname != node-2
    node.role 节点角色:manager node.role == manager
    node.labels 用户定义节点labels node.labels.security == high
    engine.labels Docker Engine的labels engine.labels.operatingsystem == ubuntu 14.04

    engine.labels匹配docker engine的lables,如操作系统,驱动等。集群管理员通过使用docker node update命令来添加node.labels以更好使用节点。

    例如,下面的示例限制redis服务的任务只能部署到那么节点的label type等于queue的节点:

    1. $ docker service create
    2.   –name redis_2
    3.   –constraint ‘node.labels.type == queue’
    4.   redis:3.0.6

    添加一个服务到一个现有的网络(–network)

    可以使用overlay网络在集群内连接一个或多个服务。

    首先在manager节点上执行docker network create命令创建一个overlay网络:

    1. $ docker network create –driver overlay my-network
    2.  
    3. etjpu59cykrptrgw0z0hk5snf

    当在swarm模式中创建了一个overlay网络,那么所有的manager节点都已经在这个网络中的。

    当创建一个服务然后传递–network参数来添加服务到这个overlay网络:

    1. $ docker service create
    2.   –replicas 3
    3.   –network my-network
    4.   –name my-web
    5.   nginx
    6.  
    7. 716thylsndqma81j6kkkb5aus

    swarm则扩展my-network到运行着这个服务的每一个节点。

    发布服务端口到集群外部(-p,–publish)

    可以使用–publish参数来把服务端口发布到集群外部:

    1. $ docker service create –publish <TARGET-PORT>:<SERVICE-PORT> nginx

    例如:

    1. $ docker service create –name my_web –replicas 3 –publish 8080:80 nginx

    当发布一个服务端口时,集群路由网使服务在每个节点的目标端口可访问,不管这个运行中的节点是否有服务的任务。

    只发布一个TCP端口或UDP端口

    默认下,当发布一个端口时,它是一个TCP端口。可以指定发布一个UDP端口,而不是或额外的TCP端口。当发布TCP和UDP两个端口时,Docker 1.12.2或之前的版本需要为TCP端口添加前缀/tcp。否则它是可选的。

    TCP only

    下面两个命令是等同的。

    1. $ docker service create –name dns-cache -p 53:53 dns-cache
    2.  
    3. $ docker service create –name dns-cache -p 53:53/tcp dns-cache

    TCP和UDP

    1. $ docker service create –name dns-cache -p 53:53/tcp -p 53:53/udp dns-cache

    UDP only

    1. $ docker service create –name dns-cache -p 53:53/udp dns-cache

    Docker命令行参考(36) – docker swarm join-token管理加入令牌

    1. Usage:  docker swarm join-token [–rotate] (worker|manager)
    2.  
    3. Manage join tokens
    4.  
    5. Options:
    6.       –help     Print usage
    7.   -q, –quiet    Only display token
    8.       –rotate   Rotate join token

    Join tokens是允许一个节点加入集群的密钥。有两种可用的不同的join tokens,一个是用作worker角色,另一个是用作manager角色。在执行swarm join时使用–token来传递token。节点只在它们加入集群时才使用这个token。

    使用swarm join-token可以查看或更换join token。

    为方便起见,可以传递worker或manager到join-token来打印出完整的docker swarm join命令来加入一个新的节点到集群。

    1. $ docker swarm join-token worker
    2. To add a worker to this swarm, run the following command:
    3.  
    4.     docker swarm join
    5.     –token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx
    6.     172.17.0.2:2377
    7.  
    8. $ docker swarm join-token manager
    9. To add a manager to this swarm, run the following command:
    10.  
    11.     docker swarm join
    12.     –token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2
    13.     172.17.0.2:2377

    使用–rotate参数来为指定的角色生成一个新的join token:

    1. $ docker swarm join-token –rotate worker
    2. Succesfully rotated worker join token.
    3.  
    4. To add a worker to this swarm, run the following command:
    5.  
    6.     docker swarm join
    7.     –token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-b30ljddcqhef9b9v4rs7mel7t
    8.     172.17.0.2:2377

    使用–rotate更新token之后,只能用新的token来加入集群。

    -q或–quiet参数只打印token:

    1. $ docker swarm join-token -q worker
    2.  
    3. SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-b30ljddcqhef9b9v4rs7mel7t