zoukankan      html  css  js  c++  java
  • docker,Dockerfile,dockercompose梳理(1) Marathon

    docker学习

    docker

    概述
    docker作为一个开源项目,诞生于2013年,基于Google的go语言实现,遵从Apache 2.0协议。
    Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。
    在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
    下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。

    docker好处

    快速交付应用程序
          -1.我们希望你的开发环境能够更好的提高你的工作效率。Docker容器能够帮助开发人员、系统管理员、QA和版本控制工程师在一个生产环节中一起协同工作。我们制定了一套容器标准,而这套容器标准能够使系统管理员更改容器的时候,程序员不需要关心容器的变化,而更专注自己的应用程序代码。从而隔离开了开发和管理,简化了开发和部署的成本。
          -2.我们使应用的构建方式更加简单,可以快速的迭代你的应用,并且可以可视化的来查看应用的细微更改。这能够帮助组织里边的成员来更好的理解一个应用从构建到运行的过程。
          -3.Docker 是一个轻量级的容器,所以它的速度是非常快的,而容器的启动时间只需要一秒钟,从而大大的减少了开发、测试和部署的时间。轻松部署和扩展
          -3.Docker 容器可以运行在大多数的环境中,你可以在桌面环境、物理主机、虚拟主机再到数据中,私有或者公有云中部署。
          -4.因为 Docker 可以从多平台下运行。你可以很容器的迁移你的应用程序。如果需要,你可以非常简单的将应用程序从测试环境迁移到云,或者从云迁移到测试环境。
          -5.Docker 是一个轻量级的容器,因此它可以在很短的时间内启动和关闭。当你需要的时候,你可以启动多个容器引擎,并且在不需要使用他们的时候,可以将他们全部关闭。
    

    从docker命令出发,梳理出命令结构

    1.images-镜像相关

    在 Docker 的术语里,一个只读层被称为镜像,一个镜像是永久不会变的。
    由于 Docker 使用一个统一文件系统,Docker 进程认为整个文件系统是以读写方式挂载的。 但是所有的变更都发生顶层的可写层,而下层的原始的只读镜像文件并未变化。由于镜像不 可写,所以镜像是无状态的。
    每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像。我们有时说,下层那个 镜像是上层镜像的父镜像。
    一个没有任何父镜像的镜像,谓之基础镜像。
    镜像ID,所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的 碰撞机率,所以服务器总是返回长ID。

    docker 在root环境下执行下列命令

    镜像常用命令集合

    docker pull imagesName:tags  从docker hub拉取镜像或从私有hub拉取
    docker push imagesName 与pull对应,推送到相关仓库
    docker search imagesName 搜索某镜像
    docker images 列出所有镜像
    docker rmi imagesName|imageID 删除镜像,前提已经停掉删除相关容器
    docker run 从镜像中启动容器
    docker save 存储镜像
    docker load 本地载入镜像
    

    docker run

    # -i or -t:标准输入输出,类似终端显示进入容器
    1.
    $ docker run -t -i ubuntu:12.04 /bin/bash
    root@fe7fc4bd8fc9:/
    # 交互模式启动,-t 表示伪终端,-i 交互式 /bin/bash 运行bash应用
    
    2.
    $ docker run images:tags [echo "hello world"] # 可启动后执行相关命令
    # 运行镜像为容器应用
    
    3. 
    $ docker run --name containerName images:tags
    # 取别名
    
    4. 
    $ docker run -d images:tags
    # 后台守护进程运行
    
    5.
    $ docker run -P|-p xx:xx images:tags
    # 实现容器与本地主机或其他host通信
    # -P 映射容器端口到本地的随机端口
    # -p 可指定端口及ip映射
    # e.g.
    # -p 11211:11211 这个即是默认情况下,绑定主机所有网卡(0.0.0.0)的11211端口到容器的11211端口上
    # -p 127.0.0.1:11211:11211 只绑定localhost这个接口的11211端口
    # -p 127.0.0.1::5000 容器5000端口映射到本地随机端口
    # -p 127.0.0.1:80:8080 容器8080端口映射到本地80端口
    
    6.
    $ docker run -v <host-path:container-path> images:tags
    # 目录映射
    

    docker tag镜像打标签

    tag的作用主要有两点:一是为镜像起一个容易理解的名字,二是可以通过docker tag来重新指定镜像的仓库,这样在push时自动提交到仓库
    将同一IMAGE_ID的所有tag,合并为一个新的
    # docker tag 195eb90b5349 seanlook/ubuntu:rm_test
    
    新建一个tag,保留旧的那条记录
    # docker tag Registry/Repos:Tag New_Registry/New_Repos:New_Tag
    

    2.container-容器相关

    docker ps

    1.docker ps
    # 列出所有正在运行的容器
    
    2.docker ps -a 
    # 列出所有容器
    
    3.docker ps -l
    # 列出最近运行的容器
    

    容器生命周期管理-开启、停止、重启-start、stop、restart

    容器可以通过run新建一个来运行,也可以重新start已经停止的container,但start不能够再指定容器启动时运行的指令,因为docker只能有一个前台进程。
    容器stop(或Ctrl+D)时,会在保存当前容器的状态之后退出,下次start时保有上次关闭时更改。而且每次进入attach进去的界面是一样的,与第一次run启动或commit提交的时刻相同。

    CONTAINER_ID=$(docker start <containner_id>)
    docker stop $CONTAINER_ID
    docker restart $CONTAINER_ID
    

    docker commit

    提交容器作为新的镜像
    当我们在制作自己的镜像的时候,会在container中安装一些工具、修改配置,如果不做commit保存起来,那么container停止以后再启动,这些更改就消失了。
    
    docker commit <container> [repo:tag]
    # 后面的repo:tag可选
    
    e.g.
    # docker commit -m "some tools installed" fcbd0a5348ca seanlook/ubuntu:14.10_tutorial
    
    

    docker commit/push补充

    1.通过运行的容器提交镜像
    # docker commit -m="描述信息" -a="作者信息" 容器ID 用户名/镜像名:tag信息
    e.g.
    # docker commit -m="my fisrt image" -a="test" xxxxxxxxx test/ubuntu:v1
    
    2.push到docker hub上
    # docker push 用户名/镜像名:v1
    # 等待,速度较慢
    

    docker inspect

    inspect的对象可以是image、运行中的container和停止的container。
    查看容器的内部IP
    
    

    p.s.
    你可能在使用过程中会build或commit许多镜像,无用的镜像需要删除。但删除这些镜像是有一些条件的:

    • 同一个IMAGE ID可能会有多个TAG(可能还在不同的仓库),首先你要根据这些 image names 来删除标签,当删除最后一个tag的时候就会自动删除镜像;
    • 承上,如果要删除的多个IMAGE NAME在同一个REPOSITORY,可以通过docker rmi <image_id>来同时删除剩下的TAG;若在不同Repo则还是需要手动逐个删除TAG;
    • 还存在由这个镜像启动的container时(即便已经停止),也无法删除镜像;

    删除容器
    docker rm <container_id/contaner_name>

    删除所有停止的容器
    docker rm $(docker ps -a -q)

    docker logs

    docker logs containerID|containerName
    # 查看应用日志
    
    docker logs -f containerID|containerName
    # 类似于tail -f 命令
    

    docker port
    使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址

    docker --link
    容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式。
    该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。
    docker run -d -P --name web --link db:db training/webapp python app.py
    此时,db 容器和 web 容器建立互联关系。
    --link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。
    使用 docker ps 来查看容器的连接

    3.docker 其他常用命令

    docker exec

    # docker exec 进入容器内部
    e.g. docker exec -it containerID /bin/bash
    

    docker cp

    # 实现文件拷贝,类似于scp/cp
    # 语法格式
    # docker cp source dest
    e.g. docker cp containerID:/file-path dest
    # 从某容器内部拷贝文件至目标位置
    

    Dockerfile

    1、基本结构

    Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。

    一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

    例如

    # This dockerfile uses the ubuntu image
    # VERSION 2 - EDITION 1
    # Author: docker_user
    # Command format: Instruction [arguments / command] ..
    
    # Base image to use, this must be set as the first line
    FROM ubuntu
    
    # Maintainer: docker_user <docker_user at email.com> (@docker_user)
    MAINTAINER docker_user docker_user@email.com
    
    # Commands to update the image
    RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
    RUN apt-get update && apt-get install -y nginx
    RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
    
    # Commands when creating a new container
    CMD /usr/sbin/nginx
    

    其中,一开始必须指明所基于的镜像名称,接下来推荐说明维护者信息。

    后面则是镜像操作指令,例如 RUN 指令,RUN 指令将对镜像执行跟随的命令。每运行一条 RUN 指令,镜像添加新的一层,并提交。

    最后是 CMD 指令,来指定运行容器时的操作命令。

    下面是一个更复杂的例子

    # Nginx
    #
    # VERSION               0.0.1
    
    FROM      ubuntu
    MAINTAINER Victor Vieux <victor@docker.com>
    
    RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
    
    # Firefox over VNC
    #
    # VERSION               0.3
    
    FROM ubuntu
    
    # Install vnc, xvfb in order to create a 'fake' display and firefox
    RUN apt-get update && apt-get install -y x11vnc xvfb firefox
    RUN mkdir /.vnc
    # Setup a password
    RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
    # Autostart firefox (might not be the best way, but it does the trick)
    RUN bash -c 'echo "firefox" >> /.bashrc'
    
    EXPOSE 5900
    CMD    ["x11vnc", "-forever", "-usepw", "-create"]
    
    # Multiple images example
    #
    # VERSION               0.1
    
    FROM ubuntu
    RUN echo foo > bar
    # Will output something like ===> 907ad6c2736f
    
    FROM ubuntu
    RUN echo moo > oink
    # Will output something like ===> 695d7793cbe4
    
    # You᾿ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
    # /oink.
    

    2、指令

    指令的一般格式为 INSTRUCTION arguments,指令包括 FROM、MAINTAINER、RUN 等。

    2.1 FROM
    格式为 FROM 或FROM :

    第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次)。

    2.2 MAINTAINER
    格式为 MAINTAINER ,指定维护者信息。

    2.3 RUN
    格式为 RUN 或 RUN ["executable", "param1", "param2"]。

    前者将在 shell 终端中运行命令,即 /bin/sh -c;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"]。

    每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。

    2.4 CMD
    支持三种格式

    CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
    CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
    CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
    指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。

    如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

    2.5 EXPOSE
    格式为 EXPOSE [...]。

    告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。

    2.6 ENV
    格式为 ENV 。 指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。

    例如

    ENV PG_MAJOR 9.3
    ENV PG_VERSION 9.3.4
    RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
    ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

    2.7 ADD
    格式为 ADD

    该命令将复制指定的 到容器中的 。 其中 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(自动解压为目录)。

    2.8 COPY
    格式为 COPY

    复制本地主机的 (为 Dockerfile 所在目录的相对路径)到容器中的

    当使用本地目录为源目录时,推荐使用 COPY。

    ENTRYPOINT
    两种格式:

    ENTRYPOINT ["executable", "param1", "param2"]
    ENTRYPOINT command param1 param2(shell中执行)。
    配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。

    每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。

    2.9 VOLUME
    格式为 VOLUME ["/data"]。

    创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

    2.10 USER
    格式为 USER daemon。

    指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。

    当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要临时获取管理员权限可以使用 gosu,而不推荐 sudo。

    2.11 WORKDIR
    格式为 WORKDIR /path/to/workdir。

    为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。

    可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd
    则最终路径为 /a/b/c。

    2.12 ONBUILD
    格式为 ONBUILD [INSTRUCTION]。

    配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。

    例如,Dockerfile 使用如下的内容创建了镜像 image-A。

    [...]
    ONBUILD ADD . /app/src
    ONBUILD RUN /usr/local/bin/python-build --dir /app/src
    [...]
    如果基于 image-A 创建新的镜像时,新的Dockerfile中使用 FROM image-A指定基础镜像时,会自动执行ONBUILD 指令内容,等价于在后面添加了两条指令。

    FROM image-A
    
    #Automatically run the following
    ADD . /app/src
    RUN /usr/local/bin/python-build --dir /app/src
    

    使用 ONBUILD 指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild。

    3、创建镜像

    编写完成 Dockerfile 之后,可以通过 docker build 命令来创建镜像。

    基本的格式为 docker build [选项] 路径,该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下所有内容发送给 Docker 服务端,由服务端来创建镜像。因此一般建议放置 Dockerfile 的目录为空目录。也可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker 忽略路径下的目录和文件。

    要指定镜像的标签信息,可以通过 -t 选项,例如

    $ sudo docker build -t myrepo/myapp:tag /tmp/test1/
    

    docker-compose

    Docker Compose 项目
    Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。

    介绍 Compose 项目情况以及安装和使用。

    1、简介

    Compose 项目目前在 Github 上进行维护。

    Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。

    Dockerfile 可以让用户管理一个单独的应用容器;而 Compose 则允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。

    该项目由 Python 编写,实际上调用了 Docker 提供的 API 来实现。

    2、安装

    安装 Compose 之前,要先安装 Docker,在此不再赘述。

    2.1 PIP 安装
    这种方式最为推荐。

    执行命令。

    $ sudo pip install -U docker-compose
    安装成功后,可以查看 docker-compose 命令的用法。

    $ 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 补全命令。

    $ curl -L https://raw.githubusercontent.com/docker/compose/1.2.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
    2.2 二进制包
    发布的二进制包可以在 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

    3、使用

    3.1 术语
    首先介绍几个术语。

    服务(service):一个应用容器,实际上可以运行多个相同镜像的实例。
    项目(project):由一组关联的应用容器组成的一个完整业务单元。
    可见,一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

    3.2 场景
    下面,我们创建一个经典的 Web 项目:一个 Haproxy,挂载三个 Web 容器。

    创建一个 compose-haproxy-web 目录,作为项目工作目录,并在其中分别创建两个子目录:haproxy 和web。

    3.3 Web 子目录
    这里用 Python 程序来提供一个简单的 HTTP 服务,打印出访问者的 IP 和 实际的本地 IP。

    3.3.1 index.py
    编写一个 index.py 作为服务器文件,代码为

    #!/usr/bin/python
    #authors: yeasy.github.com
    #date: 2013-07-05
    
    import sys
    import BaseHTTPServer
    from SimpleHTTPServer import SimpleHTTPRequestHandler
    import socket
    import fcntl
    import struct
    import pickle
    from datetime import datetime
    from collections import OrderedDict
    
    class HandlerClass(SimpleHTTPRequestHandler):
        def get_ip_address(self,ifname):
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            return socket.inet_ntoa(fcntl.ioctl(
                s.fileno(),
                0x8915,  # SIOCGIFADDR
                struct.pack('256s', ifname[:15])
            )[20:24])
        def log_message(self, format, *args):
            if len(args) < 3 or "200" not in args[1]:
                return
            try:
                request = pickle.load(open("pickle_data.txt","r"))
            except:
                request=OrderedDict()
            time_now = datetime.now()
            ts = time_now.strftime('%Y-%m-%d %H:%M:%S')
            server = self.get_ip_address('eth0')
            host=self.address_string()
            addr_pair = (host,server)
            if addr_pair not in request:
                request[addr_pair]=[1,ts]
            else:
                num = request[addr_pair][0]+1
                del request[addr_pair]
                request[addr_pair]=[num,ts]
            file=open("index.html", "w")
            file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\" face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit Results</h1></center>");
            for pair in request:
                if pair[0] == host:
                    guest = "LOCAL: "+pair[0]
                else:
                    guest = pair[0]
                if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d %H:%M:%S')).seconds < 3:
                    file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"red\">"+str(request[pair][0])+ "</font> requests " + "from &lt<font color=\"blue\">"+guest+"</font>&gt to WebServer &lt<font color=\"blue\">"+pair[1]+"</font>&gt</p>")
                else:
                    file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from &lt<font color=\"navy\">"+guest+"</font>&gt to WebServer &lt<font color=\"navy\">"+pair[1]+"</font>&gt</p>")
            file.write("</body> </html>");
            file.close()
            pickle.dump(request,open("pickle_data.txt","w"))
    
    if __name__ == '__main__':
        try:
            ServerClass  = BaseHTTPServer.HTTPServer
            Protocol     = "HTTP/1.0"
            addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1]
            port = len(sys.argv) < 3 and 80 or int(sys.argv[2])
            HandlerClass.protocol_version = Protocol
            httpd = ServerClass((addr, port), HandlerClass)
            sa = httpd.socket.getsockname()
            print "Serving HTTP on", sa[0], "port", sa[1], "..."
            httpd.serve_forever()
        except:
            exit()
    
    

    3.3.2 index.html
    生成一个临时的 index.html 文件,其内容会被 index.py 更新。

    $ touch index.html
    3.3.3 Dockerfile
    生成一个 Dockerfile,内容为

    FROM python:2.7
    WORKDIR /code
    ADD . /code
    EXPOSE 80
    CMD python index.py
    

    3.4 haproxy 目录
    在其中生成一个 haproxy.cfg 文件,内容为

    global
      log 127.0.0.1 local0
      log 127.0.0.1 local1 notice
    
    defaults
      log global
      mode http
      option httplog
      option dontlognull
      timeout connect 5000ms
      timeout client 50000ms
      timeout server 50000ms
    
    listen stats :70
        stats enable
        stats uri /
    
    frontend balancer
        bind 0.0.0.0:80
        mode http
        default_backend web_backends
    
    backend web_backends
        mode http
        option forwardfor
        balance roundrobin
        server weba weba:80 check
        server webb webb:80 check
        server webc webc:80 check
        option httpchk GET /
        http-check expect status 200
    

    3.5 docker-compose.yml
    编写 docker-compose.yml 文件,这个是 Compose 使用的主模板文件。内容十分简单,指定 3 个 web 容器,以及 1 个 haproxy 容器。

    weba:
        build: ./web
        expose:
            - 80
    
    webb:
        build: ./web
        expose:
            - 80
    
    webc:
        build: ./web
        expose:
            - 80
    
    haproxy:
        image: haproxy:latest
        volumes:
            - haproxy:/haproxy-override
            - haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
        links:
            - weba
            - webb
            - webc
        ports:
            - "80:80"
            - "70:70"
        expose:
            - "80"
            - "70"
    
    

    3.6 运行 compose 项目
    现在 compose-haproxy-web 目录长成下面的样子。

    compose-haproxy-web
    ├── docker-compose.yml
    ├── haproxy
    │   └── haproxy.cfg
    └── web
        ├── Dockerfile
        ├── index.html
        └── index.py
    

    在该目录下执行docker-compose up命令,会整合输出所有容器的输出。

    $sudo docker-compose up
    Recreating composehaproxyweb_webb_1...
    Recreating composehaproxyweb_webc_1...
    Recreating composehaproxyweb_weba_1...
    Recreating composehaproxyweb_haproxy_1...
    Attaching to composehaproxyweb_webb_1, composehaproxyweb_webc_1, composehaproxyweb_weba_1, composehaproxyweb_haproxy_1
    

    此时访问本地的 80 端口,会经过 haproxy 自动转发到后端的某个 web 容器上,刷新页面,可以观察到访问的容器地址的变化。

    访问本地 70 端口,可以查看到 haproxy 的统计信息。

    当然,还可以使用 consul、etcd 等实现服务发现,这样就可以避免手动指定后端的 web 容器了,更为灵活。

    4、Compose 命令说明

    大部分命令都可以运行在一个或多个服务上。如果没有特别的说明,命令则应用在项目所有的服务上。

    执行 docker-compose [COMMAND] --help 查看具体某个命令的使用说明。

    基本的使用格式是

    docker-compose [options] [COMMAND] [ARGS...]
    4.1 选项

    --verbose 输出更多调试信息。
    --version 打印版本并退出。
    -f, --file FILE 使用特定的 compose 模板文件,默认为 docker-compose.yml。
    -p, --project-name NAME 指定项目名称,默认使用目录名称。
    

    4.2 命令
    build
    构建或重新构建服务。

    服务一旦构建后,将会带上一个标记名,例如 web_db。

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

    help
    获得一个命令的帮助。

    kill
    通过发送 SIGKILL 信号来强制停止服务容器。支持通过参数来指定发送的信号,例如

    $ 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。如果需要的话,这样将会启动已经停止的容器。

    4.3 环境变量
    环境变量可以用来配置 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 。

    5、YAML 模板文件

    默认的模板文件是 docker-compose.yml,其中定义的每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)来自动构建。

    其它大部分指令都跟 docker run 中的类似。

    如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中再次设置。

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

    例如:

    image: ubuntu
    image: orchardup/postgresql
    image: a4bc65fd
    build
    指定 Dockerfile 所在文件夹的路径。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。

    build: /path/to/build/dir
    command
    覆盖容器启动后默认执行的命令。

    command: bundle exec thin -p 3000
    links
    链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。

    links:
     - db
     - db:database
     - redis
    

    使用的别名将会自动在服务容器中的 /etc/hosts 里创建。例如:

    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
    暴露端口,但不映射到宿主机,只被连接的服务访问。

    仅可以指定内部端口为参数

    expose:
     - "3000"
     - "8000"
    

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

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

    volumes_from
    从另一个服务或容器挂载它的所有卷。

    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 指令冲突,则以后者为准。

    env_file: .env
    
    env_file:
      - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
    

    环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

    # common.env: Set Rails/Rack environment
    RACK_ENV=development
    extends
    基于已有的服务进行扩展。例如我们已经有了一个 webapp 服务,模板文件为 common.yml。

    # common.yml
    webapp:
      build: ./webapp
      environment:
        - DEBUG=false
        - SEND_EMAILS=false
    编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展。
    
    # 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"
    

    pid
    跟主机系统共享进程命名空间。打开该选项的容器可以相互通过进程 ID 来访问和操作。

    pid: "host"
    dns
    配置 DNS 服务器。可以是一个值,也可以是一个列表。

    dns: 8.8.8.8
    dns:
      - 8.8.8.8
      - 9.9.9.9
    

    cap_add, cap_drop
    添加或放弃容器的 Linux 能力(Capabiliity)。

    cap_add:
      - ALL
    
    cap_drop:
      - NET_ADMIN
      - SYS_ADMIN
    

    dns_search
    配置 DNS 搜索域。可以是一个值,也可以是一个列表。

    dns_search: example.com
    dns_search:
      - domain1.example.com
      - domain2.example.com
    

    working_dir, entrypoint, user, hostname, domainname, mem_limit, privileged, restart, stdin_open, tty, cpu_shares
    这些都是和 docker run 支持的选项类似。

    cpu_shares: 73
    
    working_dir: /code
    entrypoint: /code/entrypoint.sh
    user: postgresql
    
    hostname: foo
    domainname: foo.com
    
    mem_limit: 1000000000
    privileged: true
    
    restart: always
    
    stdin_open: true
    tty: true
    

    参考

    1.http://www.dockerinfo.net/document
    
    

    声明:本文内容主要基于网上内容整理,如有侵权请联系本人标明出处

  • 相关阅读:
    止步于磁盘空间不足
    添加随机扰动 爬山算法
    递归 启发式
    删除文件
    linux 下载 图片
    CURD特性
    php 写session
    php 写session
    14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件
    14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件
  • 原文地址:https://www.cnblogs.com/davis12/p/14168698.html
Copyright © 2011-2022 走看看