Docker越来越成为云计算和分布式系统的宠儿和基石。
我们可以从 Docker Hub 或其他registry,如 DockerPool 和 阿里云Docker镜像库, pull下已有的镜像,也可以自己写Dockerfile文件,自己创建镜像。有了镜像,就可以去RUN它。下面依次介绍了RUN一个镜像(docker run),自己创建镜像(Dockerfile语法 和 docker build)。在介绍它的最基本用法之后,开始初步深入它的原理和内核技术,不求理解,只求一个印象 :-)。深入部分会越来越细致,不断完善。之后也会增加Docker Runtime metrics的介绍和命令,这样对Performance的分析也会有帮助。
感谢大家一起帮助博主完善这篇blog。
$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]
docker run命令有两个参数,一个是镜像名,一个是要在镜像中运行的命令。
正确的命令:
$ docker run learn/tutorial echo "hello word"
–link (name or id): alias
$ docker run -d -P --name web --link db:db training/webapp python app.py
上面命令连接了web和db两个container,注意link的参数 db:db,前一个db是容器名,后一个db是alias。
如果一个名为web的container被连接到db container上, –link db:webdb,那么Docker就会在web这个container中创建环境变量 WEBDB_NAME=/web/webdb。其中<alias>_NAME
= WEBDB_NAME。
docker run --name mongo_001 -d -P mongo
映射所有接口地址
使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
此时默认会绑定本地所有接口上的所有地址。
映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址
127.0.0.1$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
映射到指定地址的任意端口
使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
还可以使用 udp 标记来指定 udp 端口
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
$ docker port nostalgic_morse 5000
127.0.0.1:49155.
VOLUME [“mountpoint”] 将本地文件夹或者其他container的文件夹挂载到container中
# Define mountable directories.
VOLUME ["/data/db"]
WORKDIR /path/to/workdir 切换目录用,可以多次切换(相当于cd命令)
# Define working directory.
WORKDIR /data
CMD [“executable”,”param1”,”param2”] container启动时执行的命令,但是一个Dockerfile中只能有一条CMD命令,多条则只执行最后一条CMD
# Define default command.
CMD ["mongod"]
EXPOSE port 把这个端口暴露在外,这样容器外可以看到这个端口并与其通信
# Expose ports.
# - 27017: process
# - 28017: http
EXPOSE 27017
EXPOSE 28017
ENV key value 设置环境变量
ENV APP_NAME app.js
示例(构建mongodb镜像的Dockerfile)
#
# MongoDB Dockerfile
#
# Pull base image
FROM ubuntu:latest
MAINTAINER LIU Qiu Shan <qsliubj@cn.ibm.com>
# Install MongoDB
# The real logic
# Add 10gen official apt source to the sources list
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && echo ‘deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen‘ > /etc/apt/sources.list.d/mongodb.list && apt-get update && apt-get install -y mongodb-org && rm -rf /var/lib/apt/lists/*
# Define mountable directories
VOLUME ["/data/db"]
# Define working directory
WORKDIR /data
# Define default mongodb command
CMD ["mongod"]
# Expose the process port of mongodb
EXPOSE 27017
# Expose the http port of mongodb
#EXPOSE 28017
docker build -t="dockerfile/mongodb" .
在当前目录下有名为Dockerfile的文件,执行上述命令,构建名为dockerfile/mongodb的镜像。
查看所有镜像 $ docker images
删除指定镜像 $ docker rmi image_name
”Docker有两方面的技术非常重要,第一是Linux容器方面的技术,第二是Docker镜像的技术。从技术本身来讲,两者的可复制性很强,不存在绝对的技术难点,然而Docker Hub由于存在大量的数据的原因,导致Docker Hub的可复制性几乎不存在,这需要一个生态的营造。“
Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则可以认为是软件的运行态。
Dockerfile中的四条命令 FROM, ADD, VOLUME, CMD, 这四条命令可以构建出一个镜像来,分别对应四个镜像层,见下图。
下图的出处是http://www.csdn.net/article/2015-08-21/2825511
Docker最大的创新点在于Docker镜像的设计,下面是张Docker镜像的层次图,分层的文件系统,一层层地搭建出一个完整的容器运行环境:
Cgroups可以限制、记录、隔离进程组所使用的物理资源(包括:CPU、memory、IO等),为容器实现虚拟化提供了基本保证,是构建Docker等一系列虚拟化管理工具的基石,最初由Google工程师(Paul Menage和Rohit Seth)于2006年提出。
Cgroups可以对进程组使用的资源总额进行限制,如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOM(Out of Memory)。通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级。 cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能非常适用于计费。cgroups可以对进程组执行挂起、恢复等操作。
Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC。从单个进程的资源控制,到实现操作系统层次的虚拟化(OS Level Virtualization)。
“根据Docker布道师Jerome Petazzoni的说法,Docker约等于LXC+AUFS(之前只支持ubuntu时)。其中LXC负责资源管理,AUFS负责镜像管理;而LXC又包括cgroup、namespace、chroot等组件,并通过cgroup进行资源管理。所以只从资源管理这条线来看的话,Docker、LXC、CGroup三者的关系是:Cgroup在最底层落实资源管理,LXC在cgroup上封装了一层,Docker又在LXC封装了一层,关系图如图1.b所示。”
(出自http://speakingbaicai.blog.51cto.com/5667326/1352962)
(a)
(b)
图1 Docker-LXC-CGroup结构图
Docker的本质实际上是宿主机上的一个进程,通过namespace实现了资源隔离,通过cgroup实现了资源限制,通过UnionFS实现了Copy on Write的文件操作。
以下来自http://www.sel.zju.edu.cn/?p=573
术语表
task(任务):cgroups的术语中,task就表示系统的一个进程。
cgroup(控制组):cgroups 中的资源控制都以cgroup为单位实现。cgroup表示按某种资源控制标准划分而成的任务组,包含一个或多个子系统。一个任务可以加入某个cgroup,也可以从某个cgroup迁移到另外一个cgroup。
subsystem(子系统):cgroups中的subsystem就是一个资源调度控制器(Resource Controller)。比如CPU子系统可以控制CPU时间分配,内存子系统可以限制cgroup内存使用量。
hierarchy(层级树):hierarchy由一系列cgroup以一个树状结构排列而成,每个hierarchy通过绑定对应的subsystem进行资源调度。hierarchy中的cgroup节点可以包含零或多个子节点,子节点继承父节点的属性。整个系统可以有多个hierarchy
规则1: 同一个hierarchy可以附加一个或多个subsystem。如下图1,cpu和memory的subsystem附加到了一个hierarchy。
图1 同一个hierarchy可以附加一个或多个subsystem
规则2: 一个subsystem可以附加到多个hierarchy,当且仅当这些hierarchy只有这唯一一个subsystem。如下图2,小圈中的数字表示subsystem附加的时间顺序,CPU subsystem附加到hierarchy A的同时不能再附加到hierarchy B,因为hierarchy B已经附加了memory subsystem。如果hierarchy B与hierarchy A状态相同,没有附加过memory subsystem,那么CPU subsystem同时附加到两个hierarchy是可以的。
图2 一个已经附加在某个hierarchy上的subsystem不能附加到其他含有别的subsystem的hierarchy上
规则3: 系统每次新建一个hierarchy时,该系统上的所有task默认构成了这个新建的hierarchy的初始化cgroup,这个cgroup也称为root cgroup。对于你创建的每个hierarchy,task只能存在于其中一个cgroup中,即一个task不能存在于同一个hierarchy的不同cgroup中,但是一个task可以存在在不同hierarchy中的多个cgroup中。如果操作时把一个task添加到同一个hierarchy中的另一个cgroup中,则会从第一个cgroup中移除。在下图3中可以看到,httpd进程已经加入到hierarchy A中的/cg1而不能加入同一个hierarchy中的/cg2,但是可以加入hierarchy B中的/cg3。实际上不允许加入同一个hierarchy中的其他cgroup野生为了防止出现矛盾,如CPU subsystem为/cg1分配了30%,而为/cg2分配了50%,此时如果httpd在这两个cgroup中,就会出现矛盾。
图3 一个task不能属于同一个hierarchy的不同cgroup
规则4: 进程(task)在fork自身时创建的子任务(child task)默认与原task在同一个cgroup中,但是child task允许被移动到不同的cgroup中。即fork完成后,父子进程间是完全独立的。如下图4中,小圈中的数字表示task 出现的时间顺序,当httpd刚fork出另一个httpd时,在同一个hierarchy中的同一个cgroup中。但是随后如果PID为4840的httpd需要移动到其他cgroup也是可以的,因为父子任务间已经独立。总结起来就是:初始化时子任务与父任务在同一个cgroup,但是这种关系随后可以改变。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/bluecloudmatrix/article/details/48156861