Docker
一.底层技术支持cgroups/LXC/AUFS
1.cgroups
cgroups 进程分组化管理,Linux内核提供原生支持。通过分组实现对系统资源的限制与分配。
cgroups中的重要概念是“子系统”,也就是资源控制器,每种子系统就是一个资源的分配器.比如cpu子系统是控制cpu时间分配的。首先挂载子系统,然后才有control group的。比如先挂载memory子系统,然后在memory子系统中创建一个cgroup节点,在这个节点中,将需要控制的进程id写入,并且将控制的属性写入,这就完成了内存的资源限制。
2.LXC
LXC是Linux containers的简称,是一种基于容器的操作系统层级的虚拟化技术。
借助于namespace的隔离机制和cgroup限额功能,LXC提供了一套统一的API和工具来建立和管理container。
LXC旨在提供一个共享kernel的OS级虚拟化方法,在执行时不用重复加载Kernel,且container的kernel与host共享.
3.联合文件系统(UnionFS)
联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统。
联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像可以制作各种具体的应用镜像。
AuFS是ubantu上最常用的联合文件系统。
Docker镜像实际上是由具有依赖关系的多个Layer组成的。
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过42层,现在是不得超过127层。
二.基本概念
1.Docker Image
1)操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:14.04 就包含了完整的一套Ubuntu 14.04 最小系统的 root 文件系统。
2)Docker Image内不建议有运行期需要修改的配置文件
2.Docker Container
1)Docker Container是Image的实例,共享内核
2)Docker Container里可以运行不同Os的Image,比如Ubuntu的或者Centos
3)Docker Container不建议内部开启一个SSHD服务,1.3版本后新增了docker exec命令进入容器排查问题。
4)Docker Container没有IP地址,通常不会有服务端口暴露,是一个封闭的“盒子/沙箱”
3.Docker Daemon
1)Docker Daemon是创建和运行Container的Linux守护进程,也是Docker最主要的核心组件.
2)Docker Daemon 可以理解为Docker Container的Container
4.数据卷
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器可以随意删除、重新 run ,数据却不会丢失。
数据卷是一个的特殊目录,可以在容器之间共享和重用,数据卷默认会一直存在,即使容器被删除.Docker挂载数据卷的默认权限是读写,用户也可以通过:ro指定为只读。
数据卷容器 如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
5. Docker Registry
1)一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
2)通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
eg:registry.cn-qingdao.aliyuncs.com/dockerres/dockerres:webv1s1
3)虚悬镜像 由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none> 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image)。要注意区分虚悬镜像与中间层镜像。
三.Dockerfile
1.创建docker镜像
1)docker commit
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
eg:docker commit \
--author "Tao Wang <twang2218@gmail.com>" \
--message "修改了默认网页" \
webserver \
nginx:v2
2)Dockerfile
docker build [选项] <上下文路径/URL/->
eg:docker build -t nginx:v3 . <.>表示上下文路径为当前目录
2.docker build的用法
a.直接用Git进行构建
docker build https://github.com/twang2218/gitlab-ce-zh.git
b.用给定的 tar 压缩包构建
docker build http://server/context.tar.gz
c.从标准输入中读取 Dockerfile 进行构建
docker build - < Dockerfile
d.从标准输入中读取上下文压缩包进行构建
docker build - < context.tar.gz
3.dockerfile命令
dockerfile内容:
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
1)FROM 指定基础镜像。
如果不以任何镜像为基础,则以FROM scratch代替。
2)RUN
shell 格式: RUN <命令>
exec 格式: RUN ["可执行文件", "参数1", "参数2"]
每一条RUN语句都会生成一个镜像,可以用&&将多条命令合成一条RUN语句。
3)COPY
COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等.
eg:
COPY hom* /mydir/
COPY hom?.txt /mydir/
4)ADD
ADD格式与COPY一样 在COPY和ADD指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用COPY指令,仅在需要自动解压缩的场合使用ADD。
5)CMD 启动参数
CMD 指令用于指定容器默认的启动程序及参数。
shell 格式: CMD <命令>
exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
指令格式上,一般推荐使用exec格式。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主 进程退出,容器就失去了存在的意义,从而退出。正确的做法是 直接执行可执行文件,并且要求以前台形式运行,不要以服务后台的形式启动。
6)ENTRYPOINT 启动参数
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。
ENTRYPOINT的主要应用场景:
a.让镜像变成像命令一样使用
b.应用运行前的准备工作
7)ENV 设置环境变量
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>
eg:ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
8)ARG 构建参数
ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。
9)VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径>
容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记挂载卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷.
10)EXPOSE 声明端口
EXPOSE <端口1> [<端口2>...]
EXPOSE指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。
11)WORKDIR 指定工作目录
WORKDIR <工作目录路径>
12)USER 指定当前用户
USER <用户名>
13)HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
eg:HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
14)ONBUILD 为他人做嫁衣裳
ONBUILD <其它指令>
eg:ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的。
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
四、Docker网络服务
1.外部访问容器
可以通过 -P 或-p 参数来指定端口映射。
a.使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
b.-p hostPort:containerPort 指定端口
eg:$ sudo docker run -d -p 5000:5000 training/webapp python app.py
c.-p ip:hostPort:containerPort
eg:sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
d.ip::containerPort 映射到指定地址的任意端口
eg:sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
e.使用 udp 标记来指定 udp 端口
eg:sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
f.docker port 来查看当前映射的端口配置
eg:docker port nostalgic_morse 5000
2.容器互联
--link 参数的格式为 --link name:alias ,其中 name 是要链接的容器的名称, alias 是这个连接的别名。
eg:sudo docker run -d -P --name web --link db:db training/webapp python app.py
3.网桥
Docker启动时,会自动在主机上创建一个docker0虚拟网桥。当创建一个Docker容器的时候,同时会创建了一对虚拟网卡(veth pair)接口,这对接口一端在容器内,即eth0;另一端在本地并被挂载到docker0网桥。这样所有容器在一个局域网内,通过docker0与主机通信。
4.网络配置
--net=bridge 这个是默认值,连接到默认的网桥。
--net=host 告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。
--net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过lo 环回接口通信。
--net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
五.其他
tomcat Dockerfile
FROM tomcat:8.5.37-jre8
MAINTAINER "wdw"
ADD web1.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
来源:oschina
链接:https://my.oschina.net/u/2836721/blog/3018999