Docker镜像是由文件系统叠加而成,底层是一个文件引导系统,即bootfs。Docker用户几乎永远不会和引导文件系统有什么交互,Docker看起来像一个典型的Linux虚拟机栈,其第二层是root文件系统rootfs,位于引导层之上,rootfs可以是一种或多种操作系统,rootfs文件系统永远是只读文件系统,利用联合加载技术,又会在root文件系统上加载更多的只读文件系统,将各层文件系统叠加到一起,包含所有底层文件和目录,在表面上只能看到一个文件系统。Docker将这样的文件系统称为镜像,一个镜像可以放在另一个镜像之上,位于下面为父镜像,最底层为基础镜像,在启动容器时,Docker会在容器中镜像的最顶层加载一个读写文件系统,利用写时复制,对于Docker的操作在该层进行。Docker具有的这样的特点加上镜像分层框架,使我们能够快速构建镜像,以及我们所需要的容器。
构建:
构建有两种方式:
1.使用docker commit命令(不推荐)
docker commit [ID] -m"a new image" -a"Big Bai" dockerRepositories/test : dockerRepositories为仓库名,test为镜像名,-m 为该镜像添加描述,-a为该镜像添加作者,使用docker images 查看镜像。
docker inspect dockerRepositories/test : 查看镜像详细信息。
2.使用Dockerfile构建镜像
通Dockerfile构建镜像更具有可重复性,透明性,幂等性,Dockerfile是由一系列指令和参数组成,每条指令必须大写字母,且后面要跟随一个参数。Dockerfile中的指令会按照顺序从上而下执行,且第一条指令必须是FROM,指定一个已经存在镜像作为基础镜像。
创建第一个Dockerfile文件时,需要创建一个目录,作为构建环境,Docker称此环境为上下文或者构建上下文。Docker通过在本地调用Docker build 构建镜像时其实是在调用远程的Docker引擎,所以在构建时为了获得构建镜像所需的所有文件就需要创建一个构建上下文。
#Dockerfile example 第一个Dockerfile文件 (该行是一个注释)
FROM centos:6
MAINTAINER BigBai "9320*****@qq.com"
RUN yum update
EXPOSE 80
MAINTAINER指令会知名该镜像作者是谁,邮箱多少。之后运行了一条RUN指令,RUN yum update会去更新yum,每条RUN指令都会创建一个新的镜像层,默认情况下RUN指令会在shell里使用命令包装器/bin/sh -c来执行,如果在不支持shell平台或不希望在shell中运行,也可以使用exec格式的RUN指令:RUN["yum","update"],然后设置了EXPOSE指令,暴露80端口,其不会有什么效果,主要作用是镜像创建者提示容器创建者开发其80端口。
Dockerfile执行的基本流程大概如下:
• Docker从基础镜像构建一个容器
• 执行一条执行指令,对容器做出修改
• 执行类似docker commit 的操作,提交一个新的镜像层
• Docker再基于刚提交的镜像运行一个新容器
• 执行Dockerfile 中下一条指令,直到指令全部执行完
在构建目录下运行 docker bulid -t="dockertest/test" . : -t 为新镜像设置了仓库和名称,最后的 . 告诉docker在本地目录找Dockerfile文件, 也可以运行远程Dockerfile文件。例:docker bulid -t="dockertest/test" git@github.com:dockertest/test 。在docker构建目录若存在.dockerignore 命名的文件,那么该文件内容会被按行分割,每一行都是一条文件过滤匹配模式。
Dockerfile的每一步构建过程都会将结果提交为镜像,他会将之前镜像层看做为缓存,当Dockerfile的构建过程中出现错误时,将错误的指令更改后会直接从当前开始。使用--no-cache略掉缓存。
docker history [id] : 可以看见构建的镜像的每一层,以及创建这些层的Dockerfile指令。
使用docker run命令启动容器通过-p 控制开放端口,-p 80:80 容器80端口映射宿主主机80端口,-p 8080:80,容器80端口映射宿主主机8080端口,-p 127.0.0.1:80:80 127.0.0.1主机容器80端口映射宿主主机80端口,-p 127.0.0.1::80 随机映射宿主主机端口。
docker port [ID] 80:查看容器80端口映射宿主主机的端口。
Dockerfile指令:
1.CMD
用于一个容器启动时要运行的命令。docker run命令可以覆盖CMD命令,Dockerfile中只能指定一条CMD指令,如果指定了多条CMD指令,也只有最后一条指令会被使用,如果想在启动容器时运行多个进程或多条命令,可以考虑使用Supervisor服务管理工具。
2.ENTRYPOINT
类似于CMD,不过docker run 中的参数会再从传递到ENTRYPOINT指令中指定命令。
ENTRYPOINT["/usr/sbin/nginx"]
docker run -i -t dockertest/test -g "daemon off"
-g 的 "daemon off" 会传递给ENTRYPOINT中,最终命令为 /usr/sbin/nginx -g "daemon off"
3.WORKDIR
WORKDIR 指令用来在从镜像创建新容器时,在容器内部创建一个工作目录,CMD,ENTRYPOINT会在这个目录执行,docker run 命令 -w 可以运行时覆盖工作目录
4.ENV
ENV用来在镜像构建过程中设置环境变量,这个新的环境变量在之后的任何RUN指令使用,也可使用docker run 中-e标志传递环境变量。
5.USER
用来指定该镜像会以什么样的用户去运行,默认为root
6.VOLUME
用来向基于镜像创建的容器添加卷,一个卷是可以存在一个或者多个容器内的特定目录,可以绕过联合文件系统,提供如下共享数据对数据进行持久化。
• 卷可以在容器间共享重用。
• 一个容器可以不是必须和其他容器共享卷
• 对于卷修改是立即生效的
• 对卷的修改不会对更新的镜像产生影响
• 卷会一直存咋直到没有容器使用它
VOLUME["/opt/project"] : 其会为基于此镜像创建的任何容器创建一个名为/opt/project的挂载点。也可以以数组的方式指定多个卷。
7.ADD
ADD指令的功能是将主机构建环境(上下文)目录中的文件和目录、以及一个URL标记的文件 拷贝到镜像中。
• 目标路径是以 / 结尾, 则docker认为源位置指向的是目录。
• 目标路径是以 / 结尾, 则docker认为源位置指向的是文件。
• 如果源文件是个归档文件(压缩文件),则docker会自动帮解压。
ADD会使构建缓存无效
8.COPY
类似于ADD,不过其只关心在构建上下文中复制本地文件而不会去解压
9.LABEL
为Docker 镜像添加元数据,元数据以键值对的形式展现。
LABEL version="1.0"
LABEL location="china" type="Data"
使用docker inspect 可以查看
10.STOPSIGNAL
用来设置停止容器时发送什么系统调用信号给容器。这个信号必须是合法的数,或SIGNAME格式中信号名称
11.ARG
用来定义在docker build命令运行时传递给构建运行时的变量,使用--build-arg 参数,且指定的参数需在Dockerfile文件定义过的参数。可以在Dockerfile中对于其设置默认值
12.ONBUILD
ONBUILD ADD . /app/src
为镜像添加触发器,当一个镜像被用作其他镜像的基础镜像是,就会执行。触发器会在构建过程插入新指令,我们可以认为这些指令是紧跟在FROM之后指定的,其可以是任何构建指令。可以用docker inspect 命令查看,且只能继承一次,其孙子不会触发
推送Docker镜像到Docker Hub 中:
需在Docker Hub中注册,后使用docker login命令
docker push dockertest/test
自动构建:
进github中含Dockerfile的仓库连接到Docker hub中,在向代码仓库推送代码,将会触发一次镜像构建活动并创建一个新的镜像。
运行自己的Docker Registry : docker run -p 5000:5000 registry:2
如此便创建了自己的Registry,使用时,在需在镜像名前加上主机名和端口前缀。
docker push 主机地址:5000/dockertest/test