docker compose 起步

昨天写完了 Dockerfile,使用 Docker run 将容器启动起来了。今天使用 docker compose 的方式将它启动起来。先前转载过一篇教程,也可以看一看:《Docker Compose工具快速入门

安装

Compose 目前支持 Linux、macOS、Windows 10 三大平台。 Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,或在 Docker 容器中运行。

用 pip 安装比较简单:

 pip install -U docker-compose

即可开始使用。

卸载的话使用如下命令:

pip uninstall docker-compose

编写yaml模板文件

接上一篇的dockerfile

模板文件涉及的命令还蛮多的,不过大部分指令跟 docker run 相关参数的含义都是类似的。

来看我编写的 docker-compose.yml。

version: '3'    
services:
  nginx:	  # 镜像名称
    build: .  # 指定 `Dockerfile` 所在文件夹的路径,进行镜像编译。
    ports:    # 暴露端口信息。
     - "18080:80"
    volumes:  # 数据卷所挂载路径设置。
     - /var/local/nginx:/var/local/nginx/conf/vhost
     - /var/local/log/nginx:/var/local/log/nginx
  redis:      # 做个样子顺便写的
    image: "redis:alpine"   # 镜像

这里解释一下常用的这些命令:

  • build

    自动构建这个镜像,然后使用这个镜像

  • ports

    暴露端口信息。

    使用 (HOST:CONTAINER)格式,或者仅仅指定容器的端口(宿主将机端口)都可以。

      ports:
       - "3000"
       - "8000:8000"
       - "49100:22"
       - "127.0.0.1:8001:8001"
    
  • volumes

    数据卷所挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。

    该指令中路径支持相对路径。例如

      volumes:
       - /var/lib/mysql
       - cache/:/tmp/cache
       - ~/configs:/etc/configs/:ro
    
  • image

    指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉去这个镜像。

    例如:

      image: ubuntu
      image: orchardup/postgresql
      image: a4bc65fd
    
  • command

    覆盖容器启动后默认执行的命令。

      command: echo "hello world"
    

指令列表如下:

更详细的指令解说可以查看这个文档https://yeasy.gitbooks.io/docker_practice/content/compose/yaml_file.html

运行 docker compose

写好 docker-compose.yml 后就是运行了。Compose 命令的基本的使用格式是

docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

命令选项

  • -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。
  • -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
  • --x-networking 使用 Docker 的可拔插网络后端特性(需要 Docker 1.9 及以后版本)。
  • --x-network-driver DRIVER 指定网络后端的驱动,默认为 bridge(需要 Docker 1.9 及以后版本)。
  • --verbose 输出更多调试信息。
  • -v, --version 打印版本并退出。

也解释一下常用命令:

up

格式为 docker-compose up [options] [SERVICE...]

该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。

链接的服务都将会被自动启动,除非已经处于运行状态。

可以说,大部分时候都可以直接通过该命令来启动一个项目。

默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。

当通过 Ctrl-C 停止命令时,所有容器将会停止。

如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。

默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 docker-compose up --no-recreate。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 docker-compose up --no-deps -d <SERVICE_NAME> 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。

选项:

  • -d 在后台运行服务容器。
  • --no-color 不使用颜色来区分不同的服务的控制台输出。
  • --no-deps 不启动服务所链接的容器。
  • --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用。
  • --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。
  • --no-build 不自动构建缺失的服务镜像。
  • -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。

build

格式为 docker-compose build [options] [SERVICE...]

构建(重新构建)项目中的服务容器。

服务容器一旦构建后,将会带上一个标记名,例如对于 web 项目中的一个 db 容器,可能是 web_db。

可以随时在项目目录下运行 docker-compose build 来重新构建服务。

选项包括:

  • --force-rm 删除构建过程中的临时容器。
  • --no-cache 构建镜像过程中不使用 cache(这将加长构建过程)。
  • --pull 始终尝试通过 pull 来获取更新版本的镜像。

logs

格式为 docker-compose logs [options] [SERVICE...]

查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。可以通过 --no-color 来关闭颜色。

ps

格式为 docker-compose ps [options] [SERVICE...]

列出项目中目前的所有容器。

选项:

  • -q 只打印容器的 ID 信息。

更详细的指令解说可以查看这个文档https://yeasy.gitbooks.io/docker_practice/content/compose/commands.html


dockerfile 实践

看过了这么多的教程,我仍然写不好一个 Dockerfile 文件233333333。主要原因还是没有自己动手实践,把自己的项目一行一行敲出来做成一个镜像。

在这篇文档中,我将在我 GitHub 上的项目 —— KeluLinuxKit 作为基础,对照其中的命令移植到 Dockerfile 里来。

准备


先看一下我原生的脚本:

install_openresty(){
    cd $DOWNLOAD
    aptitude -y install libreadline-dev libpcre3-dev libssl-dev libpq-dev
    wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz
    tar -xzvf ngx_openresty-1.9.7.1.tar.gz
    cd ngx_openresty-1.9.7.1/
    ./configure --prefix=/usr/share/openresty --with-pcre-jit --with-http_postgres_module --with-http_iconv_module --with-http_stub_status_module
    make && make install

    mkdir /var/local/nginx
    mkdir /var/local/log/nginx
    cp -R $NGINX_HOME /var/local
    cd /var/local/nginx
    mkdir conf/vhost

    cp $RESOURCE/nginx/* /var/local/nginx/
}

这部分命令行主要做的是 openresty 的下载、编译然后拷贝现有的配置,其中涉及的命令行的知识就不做解读了。

以下这个部分会非常长,嫌麻烦的可以直接跳到最后看结果。

dockerfile 介绍


接触过容器的朋友应该都知道,Dockerfile是由一系列命令和参数构成的脚本,使用 Dockerfile 可以创建容器的镜像。

一个Dockerfile里面包含了构建一个容器镜像的完整命令。Docker通过docker build执行Dockerfile中的一系列命令自动构建image

首先,我使用一个简单的例子介绍一下 dockerfile。 一个标准最小化的 dockerfile 格式应该是这样子的:

FROM nginx
MAINTAINER kelvinblood <xxx@xxx.org>
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
ENTRYPOINT ["nginx", "-g", "daemon off;"]

它包含四个部分:

  • 基础镜像(父镜像)信息
  • 维护者信息
  • 镜像操作命令
  • 容器启动命令

完成之后,我们只需要简单的的使用 docker build . 命令,就可以将它制作出来了。

以下介绍 Dockerfile 的常用命令:

  • build
  • FROM
  • MAINTAINER
  • USER
  • ENV
  • ARG
  • RUN
  • ADD
  • COPY
  • LABLE
  • ONBUILD
  • STOPSIGNAL
  • HEALTHCHECK
  • SHELL
  • CMD
  • EXPOSE
  • ENTRYPOINT
  • VOLUME
  • WORKDIR

build


通过上面的介绍,我们对 dockerfile 已经有了一个大概的认识,现在先来看如何制作镜像。

docker build CONTENT

docker build命令从Dockerfilecontext中构建image。context可以使是PATHURLPATH是本地文件目录。 URL则是 Git 仓库的位置。

context以递归方式处理。所以PATH会包括目录下的所有子目录,URL会包括仓库和仓库的子模块。下面是一个使用当前目录作为context的构建镜像的命令:

$ docker build .
Sending build context to Docker daemon  6.51 MB
...

构建由Docker 守护程序运行,而不是由 Docker 命令行运行。在这里放上一个 Docker 的架构图帮助理解。关于Docker守护进程和命令行的内容在本文就不展开了。

构建过程所做的第一件事是将整个context递归地发送给守护进程。一个比较好的做法是将Dockerfile和所需文件复制到一个空的目录,再到这个目录进行构建。(尤其注意不要把根目录这种传过去)

以下是一些与 build 相关的小知识点:

  • 可以通过.dockerignore 来排除 content 中的文件和目录。这样能提高构建的性能。
  • 一般默认Dockerfile位于context的根目录下。也可以使用-f标志可指定Dockerfile的位置。

      $ docker build -f /path/to/a/Dockerfile .
    	
    
  • 用 -t 保存为新的镜像,也可以保存成多个镜像:

      $ docker build -t shykes/myapp .
      $ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
    
  • Docker守护程序会按顺序运行Dockerfile中的指令。
  • Docker 是根据 dockerfile 中的每一个指令进行镜像构建。在 dockerfile 中运行RUN cd /tmp对下一个指令不会有任何影响。Docker 每个指令都会产生中间镜像,以此来加速docker build的过程。

Dockerfile 格式


以下四个部分的命令分类,是我按照平时各个命令常见的位置来划分的,并没有实际意义。

第一部分 基础镜像(父镜像)信息


解析器指令

用来做一些解析的设置,目前只支持 escape。

有一些注意事项,例如必须置于 From 之前,不能重复,不能换行,未知指令视为注释。

  • escape

    用于在Dockerfile中转义字符的字符。如果未指定,则缺省转义字符为\

      # escape=\ (backslash)
    

      # escape=` (backtick)
    

FROM

FROM <image> 
FROM <image>:<tag>
FROM <image>@<digest>
  • 除了注释,from 必须作为第一个命令。
  • 可以出现多次。
  • tagdigest可以不填。如果省略其中任何一个,构建器将默认使用latest

.dockerignore

docker CLI 将 content 发送到 docker 守护程序之前,它会项目根目录中查找名为.dockerignore的文件。如果文件存在,CLI 将排除匹配的文件和目录后再将 content 发送给守护程序。

使用方法与 .gitignore 类似,这里就不展开说明了。

第二部分 维护者信息


MAINTAINER

MAINTAINER <name>

指镜像维护的作者信息。

USER

USER <user>[:<group>] 
USER <UID>[:<GID>]

USER指令设置运行image时使用的用户名或UID,用于运行 RUNCMDENTRYPOINT指令。

注意,如果所在的用户组没有 root 权限,那么镜像将会以 root 用户组运行。

第三部分 镜像操作命令


ENV

ENV <key> <value>
ENV <key>=<value> ...

ENV 主要用于设置变量,使用 $variable_name${variable_name} 进行访问。一般用后者,可以进行下面这种神奇的操作:

${foo}_bar

同时还支持几个bash修饰符

  • ${variable:-word}表示默认值是word,没有值则为空字符串。
  • ${variable:+word}表示默认值是空字符串,否则是word

除此之外 ENV 还可以用来处理转义。

注意:设置全局生效的 ENV 变量可能会导致意想不到的结果,比如设置 ENV DEBIAN_FRONTEND noninteractive 会导致其他用户在 apt-get 的时候因为跳过提示而不明所以。 只在一个命令中生效可以这么设置:RUN <key>=<value> <command>.

ARG

ARG <name>[=<default value>]

ARG中定义的变量,可以通过docker build --build-arg <varname> = <value>,在构建时将其传递给构建器。如果指定了一个未在Dockerfile中定义的,则会报错。

One or more build-args were not consumed, failing build.

ARG可以设置默认值。

警告:不建议使用 ARG 来传递诸如github密钥,用户凭证等密码。这样使用docker history命令对Docker的所有用户都可见。

ARGENV很像,都可以给变量赋值,不同的是 ENV可以将它们持久保存在最终image中。

Docker有一组预定义的ARG变量,您可以在Dockerfile中使用相应的ARG指令。

  • HTTP_PROXY
  • http_proxy
  • HTTPS_PROXY
  • https_proxy
  • FTP_PROXY
  • ftp_proxy
  • NO_PROXY
  • no_proxy

使用 ARG 变量会导致一些缓存未命中的问题,会降低编译的速度。详细内容可以参考官方文档https://docs.docker.com/engine/reference/builder/#impact-on-build-caching

RUN

RUN有2种形式:

  • RUN <command>shell形式)
  • RUN ["executable","param1","param2"]exec 形式)

RUN指令将在当前 image 之上的新层中执行命令,生成新的一层。这样可以从 image 历史中的任何点创建容器,就像代码控制一样简单。

  • shell

    shell形式在 Linux上为/bin/sh -c,Windows上为cmd /S/C。 常见的方式是在末尾添加反斜杠来换行处理:

      RUN /bin/bash -c 'source $HOME/.bashrc; \
      echo $HOME'
    
  • exec

    exec形式可以避免 shell 的字符串变化,并且可以指定特定的 shell 来运行RUN命令。例如:

      RUN ["/bin/bash", "-c", "echo $HOME"]
    

    当然使用 exec形式 也有弊端,执行命令的时候必须指定 shell,不能像平时使用 shell 一样使用exec形式。比如这个形式是错的: RUN [ "echo", "$HOME" ]。正确的写法应该是上面的形式。

    exec形式中使用json进行参数传递,所以不能使用单引号包裹字符串,必须使用双引号。

    所以这也涉及到了字符转义的问题,尤其是Windows下的字符转义问题,比如这个写法是错的: RUN ["c:\windows\system32\tasklist.exe"] 。正确的写法是: RUN ["c:\\windows\\system32\\tasklist.exe"]

为了加快编译速度, Docker 会对RUN apt-get dist-upgrade -y 这样的命令做缓存,加快下一次的镜像构建。如果我们希望不对它进行缓存,应该使用--no-cache 标志, 例如 docker build --no-cache.

ADD

  • ADD <src>... <dest>
  • ADD ["<src>",... "<dest>"] (对于包含空格的路径,此形式是必需的)

ADD指令从<src>复制新文件、目录或远程文件URL,并将它们添加到容器的文件系统,路径<dest>

<src>可以包含通配符,<dest>是绝对路径或相对于WORKDIR的路径。

如果 src 是文件或者目录那么:

  • 所有新文件和目录的UID和GID都是0
  • 如果文件名中包含有特殊字符,那么需要根据 Go 的转义规则转义这些字符串。例如我们添加这个文件 arr[0].txt

      ADD arr[[]0].txt /mydir/    # copy a file named "arr[0].txt" to /mydir/
    
  • 如果<src>是可以识别的压缩格式(identity,gzip,bzip2或xz),则 Docker 会将其解包为目录。Url 的资源不会解被压缩。如解压后有冲突,那么会将冲突的文件名改为”2.”并继续解压。注意:文件是否被识别为识别的压缩格式,基于文件的内容,而不是文件的名称。

如果 src 是 url 地址:

  • dsct 的文件权限将设置为 600.
  • 如果 HTTP 头部带有Last-Modified的时间戳,则 dest 的 mtime 就使用这个时间戳。Dockerfile 的其他的操作,比如ADD,则不会修改这个值。
  • 如果<src>是URL并且<dest>以尾部斜杠结尾,则 Docker 会从URL中推断文件名,并将文件下载到<dest>/<filename>。例如,ADD http://example.com/foobar /会创建文件/ foobar。网址必须有一个路径,以便在这种情况下可以发现一个适当的文件名(http://example.com 除外)。

关于 dest:

  • <src> 路径必须在构建的上下文中; 不能 ADD ../something /something,因为docker构建的第一步是发送上下文目录(和子目录)到docker守护进程。
  • 如果<dest>以尾部斜杠/结尾,它会被认为是一个目录,<src>的内容将被写在<dest>/base(<src>)
  • 如果使用通配符指定了多个<src>资源,则<dest>必须是目录,并且必须以斜杠/结尾。
  • 如果<dest>不以尾部斜杠结尾,它将被视为常规文件,<src>的内容将写在<dest>
  • 如果<dest>不存在,则会与其路径中的所有缺少的目录一起创建。

使用 ADD 还需要注意下面这些情况:

  • 如果 dockerfile 使用管道传输过来进行构建镜像,因为不存在构建的其它文件,那么 dockerfile 里就只能使用 ADD url 的操作了。
  • ADD 不提供权限操作,无法解决访问权限的问题。如果 Docker 没有读取 src 的权限,那么需要使用 wget curl 或者其他工具解决。

COPY

两种形式:

  • COPY <src>... <dest>
  • COPY ["<src>",... "<dest>"] (src有空格时使用)

基本和ADD类似,除了COPY<src>不能为URL。

LABLE

LABEL 指令向image添加元数据。LABEL是键值对。有空格的话要使用引号或者反斜杠。下面是一些例子:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

image可以有多个label。因为每个LABEL都会产生一个新层,会导致镜像效率低下,所以建议一行将所有 Lable 都添加完全。

LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

使用docker inspect 查看image的labels:

"Labels": {
    "com.example.vendor": "ACME Incorporated"
    "com.example.label-with-value": "foo",
    "version": "1.0",
    "description": "This text illustrates that label-values can span multiple lines.",
    "multi.label1": "value1",
    "multi.label2": "value2",
    "other": "value3"
},

ONBUILD

ONBUILD [INSTRUCTION]

ONBUILD指令在当前镜像被用作其它镜像构建的基础时,添加要在以后执行的trigger指令,当前镜像内不执行。

这一块目前很少见到有使用,等以后需要了再学习。https://docs.docker.com/engine/reference/builder/#onbuild

STOPSIGNAL

STOPSIGNAL signal

STOPSIGNAL 接收系统的退出指令并退出容器。

HEALTHCHECK

两种形式:

  • HEALTHCHECK [OPTIONS] CMD command (通过在容器中运行命令来检查容器运行状况)
  • HEALTHCHECK NONE (禁用检查)

HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。

SHELL

SHELL ["executable", "parameters"]

SHELL 指令用于覆盖默认的shell。

Linux上的默认shell是["/bin/sh","-c"],在Windows上是["cmd","/S","/C"]

SHELL指令在Windows上特别有用,其中有两个常用的和完全不同的本机shell:cmdpowershell,以及sh的备用Shell。

SHELL指令可以多次出现。每个SHELL指令覆盖所有先前的SHELL指令,并影响所有后续指令。 例如:

以下示例是Windows上的常见模式,可以使用SHELL指令进行简化。也可以在Linux上使用,如zshcshtcsh等等。

SHELL功能是在Docker 1.12中添加的。

第四部分 容器启动命令


CMD

CMD指令有三种形式:

  • CMD ["executable","param1","param2"] (exec form, 首选形式)
  • CMD ["param1","param2"] (为 ENTRYPOINT 提供参数)
  • CMD command param1 param2 (shell form)

Dockerfile中只能有一个CMD指令。如果有多个则只有最后一个生效。

CMD的主要目的是为运行容器时的默认启动命令。

  • 注意:如果使用CMDENTRYPOINT指令提供默认参数,CMDENTRYPOINT指令都应该以 JSON 数组格式指定。
  • 注意:exec 形式作为JSON数组解析,使用双引号(”)而不是单引号(’)。
  • 如果用户指定docker run参数,那么它们将覆盖CMD中指定的默认值。

注意:不要将RUNCMD混淆。RUN实际上运行一个命令并提交结果;CMD在构建时不执行任何操作,目的是指定镜像运行时的默认命令。

EXPOSE

EXPOSE <port> [<port>...]

EXPOSE 主要用来标记 Docker 运行时侦听的网络端口。默认监听TCP,也可以设置为UDP。

EXPOSE并不是真正的启动一个对外的端口,它的作用主要是在镜像创建者和运行者之间类似开发文档一样的东西。要真正开启这个端口,需要在 Docker run 的时候使用 -p 命令开启特定端口或者 -P 命令监听所有端口。

ENTRYPOINT

两种形式:

  • ENTRYPOINT [“executable”, “param1”, “param2”] (exec 形式, 首选)
  • ENTRYPOINT command param1 param2 (shell 形式)

ENTRYPOINT时容器启动时运行的一个脚本,只有最后一个ENTRYPOINT指令会有效果。

如果我们为 entrypoint 写一个可执行脚本 entrypoint.sh,可以使用execgosu命令确保最终可执行文件接收到Unix信号:

#!/bin/bash
set -e

if [ "$1" = 'postgres' ]; then
    chown -R postgres "$PGDATA"

    if [ -z "$(ls -A "$PGDATA")" ]; then
        gosu postgres initdb
    fi

    exec gosu postgres "$@"
fi

exec "$@"

理解 entrypoint 与 cmd 的关系:

  • Dockerfile应该至少指定一个CMDENTRYPOINT命令。
  • 当使用容器作为可执行文件时,应该定义ENTRYPOINT
  • CMD应该用作定义ENTRYPOINT命令的默认参数。
  • 当容器运行命令带有替代参数时,CMD会将被覆盖。

下面这个表格可以辅助我们理解 entrypoint 与 cmd 的协作:

无 ENTRYPOINT ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”, “p1_entry”]
无 CMD /bin/sh -c exec_entry p1_entry exec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd
CMD [“p1_cmd”, “p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry p1_cmd p2_cmd
CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

VOLUME

VOLUME ["/data"]

VOLUME 标记为从本机主机或其他容器保留外部挂载的卷。

VOLUME 可以是JSON数组,或具有多个参数的纯字符串:

  • VOLUME ["/var/log/"]
  • VOLUME /var/log
  • VOLUME /var/log /var/db

一些注意事项:

  • 如果使用JSON数组,注意要使用双引号(”)而不是单引号(’)
  • Windows下的挂载点,必须符合两个条件之一:
    • 一个不存在的或者空的文件夹
    • 一个C盘之外的硬盘
  • 如果在声明后更改了卷中的数据,那么这些更改将无效。所以我们一般把 VOLUME 放到比较靠后的位置。

WORKDIR

WORKDIR /path/to/workdir

WORKDIR指令为Dockerfile中的RUNCMDENTRYPOINTCOPYADD等指令设置工作目录。如果WORKDIR不存在会则自动被创建。

它可以在一个Dockerfile中多次使用。如果提供的是相对路径,它将相对于先前WORKDIR指令的路径。 例如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

在这个Dockerfile中的最终pwd命令的输出是/a/b/c

WORKDIR指令可以解析先前使用ENV显式设置设置的环境变量,例如:

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

pwd命令在该Dockerfile中输出的最后结果是/path/$DIRNAME

结果

根据 Dockerfile 的文档,将之前主机上运行的脚本改写为 Dockerfile 的结果如下:

FROM debian:jessie
MAINTAINER kelvinblood <admin@kelu.org>

# Docker Build Arguments
ENV RESTY_VERSION="1.9.7.1" \
    RESTY_CONFIG_OPTIONS=" \
        --prefix=/usr/share/openresty \
        --with-pcre-jit \
        --with-http_postgres_module  \
        --with-http_iconv_module  \
        --with-http_stub_status_module" \
    RESTY_DATA_DIR="/var/local/nginx/conf/vhost/" \
    RESTY_LOG_DIR="/var/local/log/nginx/"

COPY assets/sources.list /etc/apt/sources.list

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y zip vim locales curl wget net-tools\
        libperl4-corelibs-perl libreadline-dev libpcre3-dev libssl-dev libpq-dev gcc libc6-dev make\
 && update-locale LANG=C.UTF-8 LC_MESSAGES=POSIX \
 && locale-gen en_US.UTF-8 \
 && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales \
 && cd /tmp \
    && wget https://openresty.org/download/ngx_openresty-${RESTY_VERSION}.tar.gz \
    && tar -xzvf ngx_openresty-${RESTY_VERSION}.tar.gz \
    && cd ngx_openresty-${RESTY_VERSION}/ \
    && ./configure ${RESTY_CONFIG_OPTIONS} \
    && make \
    && make install \
    && mkdir -p /var/local/log/nginx \
    && mkdir -p /var/local/nginx/fastcgi_cache/one_hour \
    && cp -R /usr/share/openresty/nginx /var/local \
    && mkdir -p /var/local/nginx/conf/vhost \
    && apt-get clean\
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /tmp/ngx_openresty-${RESTY_VERSION} \
    && rm /tmp/ngx_openresty-${RESTY_VERSION}.tar.gz

COPY assets/nginx/conf/nginx.conf /var/local/nginx/conf/nginx.conf
COPY assets/nginx/conf/vhost/www.conf /var/local/nginx/conf/vhost/www.conf

EXPOSE 80/tcp

VOLUME ["${RESTY_DATA_DIR}", "${RESTY_LOG_DIR}"]
# ENTRYPOINT /usr/share/openresty/nginx/sbin/nginx -c /var/local/nginx/conf/nginx.conf -g 'daemon off;'
CMD ["/usr/share/openresty/nginx/sbin/nginx","-c","/var/local/nginx/conf/nginx.conf","-g","daemon off;"]

将正常的脚本转换成 Dockerfile 基本的思路就是

  • 设定好这个 Dockerfile 和相关依赖包的版本号
  • 安装系统依赖
  • 清除多余软件包和文件
  • 拷贝必要的脚本或配置
  • 做好端口和挂载点声明
  • 写好并添加启动命令或脚本entrypoint.sh

这个脚本中我做了几个方便验证的东西:

  • 挂载 volume 的验证:

    在不挂载 RESTY_DATA_DIR 的情况下,,启用后我改成了另外一个配置,显示其他页面。

    运行命令: docker run --name 'daemon4' -d -p 18080:80 test 时,会显示默认的 nginx 页面。

    挂载 RESTY_DATA_DIR 文件夹后,就换成其它界面:

      docker run --name 'daemon' -d -p 18080:80 \
          --volume /var/local/nginx/:/var/local/nginx/conf/vhost \
          --volume /var/local/log/nginx/:/var/local/log/nginx/ test4
    

    挂载的nginx.conf的文件如下:

      server {
              listen 80;
              access_log /var/local/log/nginx/nginx.www.access.log;
              error_log /var/local/log/nginx/nginx.www.error.log;
    	
              location / {
                  default_type text/html;
                  content_by_lua '
                      ngx.say("<p>hello, kelu volume</p>")
                  ';
              }
          }
    
  • 最后两行 ENTRYPOINT 和 CMD 的作用是一样的。我多写了一个看看效果。

参考资料


Rancher 再学习(一)

前段时间转载了这篇《Rancher安装手册》文章, 也尝试着安装了一下,有了一些浅显的认识。今天从0开始又一次部署,算是对 Rancher 的再学习。 这一篇主要是将各种事先需要准备的一些东西。

使用的环境为 CentOS 7.4 ( cat /etc/redhat-release

事先准备几个命令,后边你可能会经常用到(但愿不需要用到)

docker kill $(docker ps -a -q) # 杀死所有正在运行的容器
docker rm $(docker ps -a -q)	# 删除所有已经停止的容器
docker rmi $(docker images -q)	# 删除所有镜像

重置 docker/rancher:

rm -rf /var/lib/docker
rm -rf /var/lib/rancher

Docker再安装

按照 Rancher 的官方推荐,使用 17.06 版本的 Docker。所以要先把本机的docker 卸载,再重新安装。

# 查看安装版本号、卸载
yum list installed | grep docker
yum -y remove docker-ce.x86_64

# 查看可用的版本
yum makecache fast
yum list docker-ce.x86_64 --showduplicates | sort -r

yum -y install docker-ce-17.06.0.ce

加速

安装成功后需要对 Docker 源进行加速。我试用 Docker 官方的加速办法:在 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值。

touch /etc/docker/daemon.json
vi /etc/docker/daemon.json
{  
	"registry-mirrors": ["https://registry.docker-cn.com"]
}

重启 Docker 后生效。

开机自启动

systemctl enable docker
# Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

Rancher 安装

参照我先前的文章《Rancher安装手册》进行安装。

注意要使用 Chrome 访问 Rancher。在 IE 下会出现无法添加主机的情况(嗯,我踩过的坑。)

防火墙firewall

容器之间通信需要借助防火墙。使用 Rancher 添加不同主机的时候,就需要打通各个主机的通信,主要是 Rancher 服务器的默认 8080 端口和 IPsec 的 500、4500端口(UDP协议)。这里列几个,其他的我会再开一篇文章记录一下。

关于 firewall,只要记住服务和端口两个概念即可。

iptables -F; # 清除 iptables,防止两个防火墙冲突。
iptables -L;
firewall-cmd --zone=public --list-ports  # 查看所有打开的端口
firewall-cmd --list-services			# 查看开启的服务。
firewall-cmd --zone=public --add-port=80/tcp --permanent    (--permanent永久生效,没有此参数重启后失效)							#  添加端口
firewall-cmd --permanent --add-service="ipsec"  # 添加服务
firewall-cmd --reload
systemctl start firewalld.server		# 重启 firewall

打了这么些命令,可以参考一下

检查远端端口是否可用

使用 nc 命令进行检测:

nc -v host port

出现 Connection refused 或者 Connected 都说明端口可用。如果出现 No route to host. 则说明端口未开放。例如:

参考资料


Rancher 中文文档 —— Rancher 安装

原文:http://rancher.com/docs/rancher/v1.6/en/installing-rancher/installing-server/

查看本系列翻译的目录

安装 Rancher 服务器


Rancher 由一系列的 Dcoekr 容器组成。 运行 Rancher 就像添加两个容器一样简单: 一个服务管理容器和一个作为客户端的节点容器。

注意:Rancher 服务器容器帮助选项docker run rancher/server --help

要求

  • 支持 Dcoekr 的 Linux 发行版。我们在 RancherOS Ubuntu 和 RHEL/CentOS 7 行会进行更多的测试(画外音:所以会更稳定一些)。。
    • 在 RHEL/CentOS 里,Docker 不支持默认的存储驱动器,比如devicemapper 使用的 loopback。所以请参考 Dcoker 的相关文档如何进行修改。
    • 对于RHEL / CentOS的,如果要启用SELinux的,需要安装附加的SELinux模块
  • 1GB RAM
  • MySQL服务器应该设置 MAX_CONNECTIONS > 150
    • 配置要求:
      • Option 1: Run with Antelope with default of COMPACT
      • Option 2: Run MySQL 5.7 with Barracuda where the default ROW_FORMAT is Dynamic
    • 推荐设置:
      • max_packet_size > = 32M
      • innodb_log_file_size > = 256M(如果你有一个现有的数据库,请确保适当的计划如何更改此设置。)
      • innodb_file_per_table=1
      • innodb_buffer_pool_size > = 1GB(对于内存较大的主机,建议4-8G池)

注:目前,Docker Mac 暂不支持 Rancher。

Rancher server 标签

Rancher server 有两个不同的标签。对于每一个主要版本的标签,我们将提供特定版本的文档。

  • rancher/server:latest标签将是我们最新开发版本。这些版本会已经通过我们的CI自动化框架验证。这些版本不意味着在它们可以在生产环境中部署。
  • rancher/server:stable标签将是我们最新的稳定版本。这个标签是我们推荐用于生产的版本。

请不要使用有任何带有rc{n}后缀的版本。这些rc是 Rancher 的测试版本

启动 Rancher 服务器 - 单容器(非HA)

在已安装了 docker 的 Linux 机器上,启动 Rancher 的单个实例很简单。

$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server

Rancher 界面

Rancher 的界面和 API 可以通过 8080 端口访问。docker 镜像下载完成后,需要1到两分钟时间才可以使用。

进入网站: http://<SERVER_IP>:8080. <SERVER_IP>是 Rancher server 的公网地址.

当 Rancher 界面启动后, 我们可以添加主机或者从应用仓库里添加容器。 默认情况下 Rancher 使用 cattle 作为容器编排的环境。在主机添加吼,我们就可以开始添加服务或者在应用商店中通过模板添加服务了。

启动 Rancher 服务器 - 单容器 - 外部数据库

我们可以指定使用外部数据库来启动 Rancher。 命令行还是相同的,不过我们会添加额外的参数来设定如何使用外部数据库。

注意:数据库,名称和数据库的用户需要事先创建好,模式Schema不需要创建。Rancher 将自动创建所有与 Rancher 的模式Schema。

下面是创建一个数据库和用户的SQL命令的例子。

> CREATE DATABASE IF NOT EXISTS cattle COLLATE = 'utf8_general_ci' CHARACTER SET = 'utf8';
> GRANT ALL ON cattle.* TO 'cattle'@'%' IDENTIFIED BY 'cattle';
> GRANT ALL ON cattle.* TO 'cattle'@'localhost' IDENTIFIED BY 'cattle';

要启动 Rancher 连接到外部数据库,我们要将额外的信息作为命令的一部分传给容器:

$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server \
    --db-host myhost.example.com --db-port 3306 --db-user username --db-pass password --db-name cattle

大多数的选项有默认值,不是必需的。只有 MySQL 服务器的位置是必需的。

--db-host               IP or hostname of MySQL server
--db-port               port of MySQL server (default: 3306)
--db-user               username for MySQL login (default: cattle)
--db-pass               password for MySQL login (default: cattle)
--db-name               MySQL database name to use (default: cattle)

注: Rancher server 的早期版本中,我们使用环境变量连接到外部数据库,这些环境变量也会继续生效,不过我们建议使用参数来运行 Rancher

启动 Rancher 服务器 - 单容器 - 绑定 Mysql 数据卷

如果你想将容器的数据库与主机商的存储设备绑定起来,那么应当这么启动 Rancher server:

$ sudo docker run -d -v <host_vol>:/var/lib/mysql --restart=unless-stopped -p 8080:8080 rancher/server

使用此命令,数据库将会把数据卷绑定到主机上。如果你已经有了 Rancher 数据库,也想绑定 MySQL 数据卷,参考我们的升级文件

启动 Rancher 服务器 - 全主动/主动HA

Rancher server 上跑 HA 和上文的跑外部数据库一样简单。通过一个额外的端口和参数,与外部的负载均衡器进行通信。

要求:

  • HA节点:
    • 支持 Dcoekr 的 Linux 发行版。我们在 RancherOS Ubuntu 和 RHEL/CentOS 7 行会进行更多的测试(画外音:所以会更稳定一些)。
      • 在 RHEL/CentOS 里,Docker 不支持默认的存储驱动器,比如devicemapper 使用的 loopback。所以请参考 Dcoker 的相关文档如何进行修改。
      • 对于RHEL / CentOS的,如果要启用SELinux的,需要安装附加的SELinux模块
    • 1GB RAM
    • 节点之间开通需要的端口:93458080
  • MySQL服务器应该设置 MAX_CONNECTIONS > 150
    • 配置要求:
      • Option 1: Run with Antelope with default of COMPACT
      • Option 2: Run MySQL 5.7 with Barracuda where the default ROW_FORMAT is Dynamic
  • 外部负载均衡器
    • 8080

注:目前,Docker Mac 暂不支持 Rancher。

对大规模部署的建议

  • 每个 Rancher server 节点应该有一个4 GB或8 GB 堆的大小,这需要具有至少8 GB或16 GB的RAM
  • MySQL数据库应该有快速磁盘
  • 对于真正的HA,建议MySQL数据库进行适当策略的备份。例如构建一个 Galera Cluster,提高MySQL服务的可用性和性能。
  1. 在每个要加入HA的节点,运行以下命令:

    # Launch on each node in your HA cluster
    $ docker run -d --restart=unless-stopped -p 8080:8080 -p 9345:9345 rancher/server \
         --db-host myhost.example.com --db-port 3306 --db-user username --db-pass password --db-name cattle \
         --advertise-address <IP_of_the_Node>
    

    对于每个节点,<IP_of_the_Node>都是唯一的,因为这将是正被加入到HA设置的每个特定节点的IP。 如果你需要更改-p 8080:8080,使HTTP端口暴露在主机上的不同端口上,将需要添加--advertise-http-port <host_port>的命令。

    注意:您可以通过运行得到帮助的命令docker run rancher/server --help

  2. 配置外部负载均衡器,平衡端口80443之间的流量,将流量指向运行 Rancher Server 的节点池。负载平衡器必须支持的WebSockets和headers转发。请参阅SSL设置页查看配置示例。

Option Example Description
IP address --advertise-address 192.168.100.100 Uses the give IP address
Interface --advertise-address eth0 Retrieves the IP of the given interface
awslocal --advertise-address awslocal Retrieves the IP from http://169.254.169.254/latest/meta-data/local-ipv4
ipify --advertise-address ipify Retrieves the IP from https://api.ipify.org

Rancher HA注意事项

如果你的 Rancher 主服务器节点更改IP,你的节点将不再是 Rancher HA 群集的一部分。您必须使用--advertise-address + 不正确的IP停止老的 Rancher server 容器 ,并使用 --advertise-address + 正确的IP 开始一个新的Rancher server 容器。

在 AWS 上运行 Rancher server 的 ELB

因为译者不用这一块,所以现在先不翻译了 2333333333333

在 AWS 的应用负载平衡器(ALB)

我们不再建议在AWS应用负载平衡器(ALB)在使用弹性/经典负载均衡器(ELB)。如果您仍然选择使用ALB,您需要将流量引导到节点上的HTTP端口,默认是8080端口。

启用ACTIVE DIRECTORY 或 OPENLDAP FOR TLS

要启用 Active Directory 或 OpenLDAP P for TLS, Rancher server 容器需要在启动时候加载由 LDAP 提供的证书。

我们需要通过绑定拥有证书的数据卷来启动 Rancher 容器。证书必须命名为ca.crt:

$ sudo docker run -d --restart=unless-stopped -p 8080:8080 \
  -v /some/dir/cert.crt:/var/lib/rancher/etc/ssl/ca.crt rancher/server

我们可以通过跟踪 Rancher server 地日志来检查 ca.crt是不是正确地传递给了 Rancher server:

$ docker logs <SERVER_CONTAINER_ID>

日志的开头,就会出现正确添加证书的信息。

Adding ca.crt to Certs.
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
Certificate was added to keystore

启用 Rancher http 代理

为了启用 http 代理, docker daemon 需要修改代理的配置。在启动 Rancher server 之前进行配置:

sudo vi /etc/default/docker

在文件中,编辑#export http_proxy="http://127.0.0.1:3128" 指向您的代理。保存更改,然后重新启动 Docker。

重启 Docker 的方式在不同操作系统之间会有所差别。

注: 如果您使用 systemd 运行 Docker,请根据 Docker 的说明 配置HTTP代理。

配置好了 Docker,为了在Rancher 应用里也能加载,需要进行一些配置,并把代理的配置参数添加到 Rancher 的环境变量。

$ sudo docker run -d \
    -e http_proxy=<proxyURL> \
    -e https_proxy=<proxyURL> \
    -e no_proxy="localhost,127.0.0.1" \
    -e NO_PROXY="localhost,127.0.0.1" \
    --restart=unless-stopped -p 8080:8080 rancher/server

如果不使用 Rancher 应用,按照正常情况启动 Rancher server 即可。

主机添加到 Rancher 之后,后续就不需要再添加其他配置了。

与 MySQL 通过 SSL 通信

注:目前,Rancher 1.6.3+ 以上支持这个特性

重要提示

如果你使用了 LDAP/AD authentication 作为认证后端,由其它客户端生成CA证书(而不是MySQL生成的),那么接下里的操作不适合你,不会达到预期效果。

要求

  • 认证文件 或 MySQL 服务器的 CA 证书(PEM编码)

说明

  1. 将服务器的证书或CA证书复制到 Rancher server 的主机。当启动rancher/server容器时需要挂载认证文件到/lib/rancher/etc/ssl/ca.crt
  2. 替换服务器变量中的默认值,构建一个自定义的JDBC URL: jdbc:mysql://<DB_HOST>:<DB_PORT>/<DB_NAME>?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&prepStmtCacheSize=517&cachePrepStmts=true&prepStmtCacheSqlLimit=4096&socketTimeout=60000&connectTimeout=60000&sslServerCert=/var/lib/rancher/etc/ssl/ca.crt&useSSL=true
  3. 根据这个 JDBC URL 设置容器中的环境变量,包括 CATTLE_DB_CATTLE_MYSQL_URLCATTLE_DB_LIQUIBASE_MYSQL_URL

  4. 在容器中设置 export CATTLE_DB_CATTLE_GO_PARAMS="tls=true"。如果服务器的证书的主题字段不匹配服务器的主机名,需要使用CATTLE_DB_CATTLE_GO_PARAMS="tls=skip-verify"代替。

例子


$ export JDBC_URL="jdbc:mysql://<DB_HOST>:<DB_PORT>/<DB_NAME>?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&prepStmtCacheSize=517&cachePrepStmts=true&prepStmtCacheSqlLimit=4096&socketTimeout=60000&connectTimeout=60000&sslServerCert=/var/lib/rancher/etc/ssl/ca.crt&useSSL=true"

$ cat <<EOF > docker-compose.yml
version: '2'
  services:
    rancher-server:
      image: rancher/server:stable
      restart: unless-stopped
      command: --db-host <DB_HOST> --db-port <DB_PORT> --db-name <DB_NAME> --db-user <DB_USER> --db-pass <DB_PASS>
      environment:
        CATTLE_DB_LIQUIBASE_MYSQL_URL: $JDBC_URL
        CATTLE_DB_CATTLE_MYSQL_URL: $JDBC_URL
        CATTLE_DB_CATTLE_GO_PARAMS: "tls=true"
      volumes:
        - /path/to/mysql/ca.crt:/var/lib/rancher/etc/ssl/ca.crt
      ports:
        - "8080:8080"
EOF

$ docker-compose up -d

重要提示: 需要同时修改 JDBC URL 和 命令行中 --db-xxx 的变量!


Rancher 中文文档 —— 快速入门指南

原文:http://rancher.com/docs/rancher/v1.6/en/quick-start-guide/

查看本系列翻译的目录

快速入门指南


在本指南中,我们将在一台 Linux 主机上安装 Rancher。

准备一台 Linux 主机

准备一台Linux主机:

  • 使用64位的Ubuntu 16.04,必须有3.10+的内核
  • 至少1G内存
  • 安装了 Docker。

你可以使用笔记本、虚拟机或者物理服务器。

如何安装Docker可以参考官方文档

注意: 目前 Rancher 不支持 Mac和 Windows 下的 Docker

译者注: 目前 Rancher v1.6 最好安装 Rancher 官方推荐的 Docker 17.06.0-ce.

Rancher server 标签

Rancher server 有两个不同的标签。对于每一个主要版本的标签,我们将提供特定版本的文档。

  • rancher/server:latest标签将是我们最新开发版本。这些版本会已经通过我们的CI自动化框架验证。这些版本不意味着在它们可以在生产环境中部署。
  • rancher/server:stable标签将是我们最新的稳定版本。这个标签是我们推荐用于生产的版本。

请不要使用有任何带有rc{n}后缀的版本。这些rc是 Rancher 的测试版本。

启动 Rancher server

你需要一行命令来启动 Rancher server。启动后,我们将跟踪查看容器的日志。

$ sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable 

# 跟踪日志  
$ sudo docker logs -f <CONTAINER_ID>

需要几分钟的时间等待 Rancher serer 启动。当日志显示.... Startup Succeeded, Listening on port...后,Rancher的 UI 就会启动并运行。

日志显示基本上是实时的。请不要以为这是在初始化时的日志的最后一行,后边可能还会有更多的日志。

注: 任何有 Rancher 所在主机IP的人员都可以访问 Rancher 的主界面和API。我们建议你进行 访问控制 的配置

添加主机

为简单起见,我们将 Rancher Server 所在的机器添加为主机。在实际环境中,我们推荐使用独立的(一个或多个)主机来运行 Rancher server。

要添加主机,访问的用户界面,然后单击Infrastructure,它会立即跳到Hosts页面。点击 Add Host

非原文图片

Rancher 会提示你选择一个主机注册 URL。这个网址是 Rancher server 运行的地址,必须要保证其它被添加的主机都能访问到。把 Rancher 服务器的端口通过防火墙的 NAT 或者负载均衡器暴露出来,或者暴露到 Internet上在有些情况下是很有用的。如果你的主机有一个私有或者本地 IP 地址,例如: 192.168.*.*;Rancher 将打印一个提示信息,告诉您是否确认这个 IP 地址可以被正常访问到。

现在我们添加 Rancher 服务器主机自身,因此我们可以忽略这个提示信息。点击保存。之后的页面中,默认情况下选中的是custom选项。在这可以得到运行 rancher/agent 容器的命令。这里还有其它的公有云的选项。

网页列出了需要服务器预先打开的端口和说明。由于我们正在添加 Rancher 服务器的主机,我们需要添加这个主机所使用的共有 IP。Rancher agent 命令中如果没有这个参数,这个主机的 IP 很可能会是个错误的配置。

在需要添加的主机上运行界面提示的命令。

当您单击关闭之后就会到达Stacks - > Infrastructure页面。等待一两分钟后,主机就自动出现了。

基础架构服务

第一次登录 Rancher, 你会自动处于 默认 环境中。在默认环境中我们使用了 cattle 的环境模板来添加一些基础架构服务。 这些基础架构服务需要预先被添加进来,才能获得 Rancher 框架的支持。这些基础架构服务可以在 ` Stacks -> Infrastructure` 里找到。

这些应用在添加主机之前都会会保持 unhealthy 的状态。在增加主机后,我们需要等待一点时间,直到这些应用变为 active 的状态。

在主机页面中,默认情况下,作为基础设施服务的容器不会显示出来。你也可以勾选显示系统容器,将系统容器显示出来。

通过界面创建容器

编者注:你可能会混淆一些概念,下文翻译的“应用”英文原文都是stack,而不是application。这个翻译是按照 Rancher 里的中文翻译对应的,并非编者所创。

点击 stacks 进入 stack 页面。如果您看到欢迎屏幕,您可以点击定义一个应用。如果已经存在了一些应用,您可以点击添加服务于任何现有的应用,或创建一个新应用中添加服务。

应用/statck 仅仅是一个方便的方式来组服务结合在一起。如果你需要创建一个新的应用,点击添加应用,填好名称和描述,单击创建,然后点击添加服务。

假设我们定义了一个服务叫first-service。你可以使用默认设置单机创建。 Rancher 就会将容器添加到主机中。无论你的主机IP地址是多少,这个first-service容器的IP都会在 10.42.*.* 的范围内,因为在前文中 Rancher 使用了 ipsec 的基础设施服务,这个服务采用了 overlay 的网络架构解决容器间的跨主机通信问题。

在容器界面中,点击 first-container 的下拉菜单,你就可以进行一些容器的管理操作,例如停止容器、擦好看日志,或者进入命令行等。

通过 Docker 原生命令创建容器

Rancher也会显示那些通过 Docker 原生命令行创建的容器。

通过主机的终端,我们运行以下命令创建容器:

$ docker run -d -it --name=second-container ubuntu:14.04.2

在 Rancher 的主机页面上,你会看到一个名叫 second-container 的容器冒出来了。

Rancher 感知到 Docker daemon 发生的事件,并用恰当的方式将他们显示出来, 可以查看 native docker CLI. 获得更多的信息。

如果你查看 second-container 的 IP,你会发现它并不是10.42.*.* 范围里的,而是与 Docker deamon 类似的 IP。这是使用原生命令行创建容器的结果。

如果我们希望使用原生命令行创建容器,又将它纳入 Rancher 的 Overlay 网络,使得管理更为便利,应该怎么办呢? 很简单,我们为它在命令行中添加一个标签,例如io.rancher.container.network=true,使得 Rancher 将这个容器识别为可以管理的。

$ docker run -d -it --label io.rancher.container.network=true ubuntu:14.04.2

创建一个多容器应用

我们已经展示了如何创建单独的容器,并解释它们如何将我们的跨主机网络的连接。然而,大多数现实中的应用,是创建多种服务,每个服务由多个容器组成。例如一个LetsChat应用,可以包括以下服务:

  1. 负载均衡器LB。负载均衡网络流量重定向到“LetsChat”应用程序。
  2. 一个_网络_服务 web service 由两个“LetsChat”容器组成。
  3. 一个 db service 由一个“Mongo的”容器组成。

lb 与 web service 相连,web service 与 db service 相连(例如Mongo)。

在本节中,我们将详细介绍如何创建和部署LetsChat在牧场主的应用。

导航到stacks页面,如果您看到欢迎屏幕,您可以点击 Define a Service。如果已经有相关的应用存在了,您可以点击** Add Stack来创建一个新的应用。填好名称和描述,单击创建。然后在新的应用中点击 **Add Service

首先,我们使用mongo镜像,创建一个名为database的数据库服务。点击创建。你会立即回到应用页面(Stacks),其中将包含新创建的db service。

接下来,点击Add Service再添加另外的服务。我们将添加一个LetsChat服务,并链接到db service——创建一个名为web的服务的并使用sdelements/lets-chat镜像。 在页面中,我们将将滑块移动到——有服务的规模为2个容器。 在 Service Links,添加db service,并提供名称mongo

类似于Docker,Rancher 将从mongo中链接所需的环境变量到letschat镜像。点击创建

最后,我们创建一个负载平衡器。点击旁边的下拉菜单图标Add Service按钮。选择 Add Load Balancer。我们明明为letschatapplb。输入的源端口(即80),选择目标服务(即web),并选择一个目标端口(即8080, 假定 web service 监听 8080 端口), 点击创建

我们LetsChat应用程序现在完成了!在Stacks页面,你就可以找到负载平衡器为网络上暴露的端口。点击这个链接,你就到了 LetsChat 的应用上了。

使用 Rancher CLI 创建多容器应用程序

在本节中,我们将向您展示如何使用 Rancher CLI 创建和部署相同的LetsChat

在 Rancher 中,使用 Rancher CLI 把应用拉起来,就像 Docker Compose 工具那么简单。你同样需要docker-compose.yml文件来部署在 Rancher 上的应用。此外您可以指定一个额外的rancher-compose.yml扩展和覆盖docker-compose.yml的文件。

在上一节中,我们创建了一个带有负载均衡器的 LetsChat 应用。如果你已经在 Rancher 创建了它,你可以直接从应用中的下拉菜单导出配置。在docker-compose.ymlrancher-compose.yml文件是这样的:

DOCKER-COMPOSE.YML 示例

version: '2'
services:
  letschatapplb:
    #If you only have 1 host and also created the host in the UI,
    # you may have to change the port exposed on the host.
    ports:
    - 80:80/tcp
    labels:
      io.rancher.container.create_agent: 'true'
      io.rancher.container.agent.role: environmentAdmin
    image: rancher/lb-service-haproxy:v0.4.2
  web:
    labels:
      io.rancher.container.pull_image: always
    tty: true
    image: sdelements/lets-chat
    links:
    - database:mongo
    stdin_open: true
  database:
    labels:
      io.rancher.container.pull_image: always
    tty: true
    image: mongo
    stdin_open: true

RANCHER-COMPOSE.YML 示例

version: '2'
services:
  letschatapplb:
    scale: 1
    lb_config:
      certs: []
      port_rules:
      - hostname: ''
        path: ''
        priority: 1
        protocol: http
        service: web
        source_port: 80
        target_port: 8080
    health_check:
      port: 42
      interval: 2000
      unhealthy_threshold: 3
      healthy_threshold: 2
      response_timeout: 2000
  web:
    scale: 2
  database:
    scale: 1

Rancher CLI 的二进制包可以在 Rancher 主页面的右下角找到。适用于 Windows Mac 和 Linux.

为了在Rancher CLI 中使用 Rancher 的一系列服务,我们还需要设置一些环境变量。我们需要在 Rancher 页面中创建一个帐户API密钥。点击API - > Key。点击添加帐户API密钥。填写名称,然后点击创建。保存Access KeySecret Key。 之后就可以通过 Rancher URL,Access Key和Secret Key,使用 rancher config 来配置 Rancher CLI了。

# Configure Rancher CLI
$ rancher config
# Set the Rancher URL
URL []: http://<SERVER_IP>:8080/
# Set the access key, i.e. username
Access Key []: <accessKey_of_account_api_key>
# Set the secret key, i.e. password
Secret Key []:  <secretKey_of_account_api_key>

现在,将 docker-compose.ymlrancher-compose.yml 保存后运行如下命令:

$ rancher up -d -s NewLetsChatApp

你就可以看到一个名为NewLetsChatApp的应用就启动起来了。


Rancher 中文文档 —— Rancher 概述

原文:http://rancher.com/docs/rancher/v1.6/en/

查看本系列翻译的目录

概述


Rancher 是一个开源软件平台,用于运行和管理 Docker 与 Kubernetes。在 Rancher 中,我们不再需要从头开始整合不同的开源技术搭建容器平台。Rancher 整合提供了容器生产环境中所需要的软件技术栈。

基础架构

Rancher 可以在任何公有云或私有云的 Linux 主机上使用底层的计算资源。 Linux 主机可以是虚拟机,也可以是物理机。Rancher 对主机资源的消耗也很小。从 Rancher 的角度看,Rancher 无法区分当前管理的机器是物理机还是虚拟机。

Rancher 实现了便携的专为 Dcoker 设计的基础架构,包括 网络、存储、负载均衡、DNS 和安全性。 Rancher 可以在任何Linux主机任何云上进行部署,因为 Rancher 的基础设施服务也是由 Docker 进行部署。

容器的编排和调度

许多用户使用容器编排和调度框架来管理容器化的应用。 Rancher 包含了当下所有流行的容器编排和调度框架,包括 Docker Swarm, Kubernetes 和 Mesos. 同一个用户可以创建多个 Swarm 或 Kubernetes 集群,然后再用 Swarm 或 Kubernetes 的原生工具管理他们的应用。

除了支持这些流行的框架 Swarm, Kubernetes 和 Mesos, Rancher 也支持了一套自家公司开发的编排和调度工具 —— Cattle。

应用商店

在 Rancher 中可以很方便地在应用商店中部署多个容器集群的应用。 如果应用有版本升级,应用升级的过程都是自动化的,简单无痛。

Rancher 用户除了可以使用公有的应用商店,也可以创建自己的私有应用商店。

企业级控制

Rancher 对用户身份验证的支持非常灵活,可以自由设置登陆用户的访问权限。除此之外,Rancher 还内置了Active Directory, LDAP, 和 GitHub 认证插件。 Rancher 基于角色的访问控制权限可以同时在开发环境和生产环境中使用。

下图是 Rancher 的主要组件和功能特性。