docker镜像相关原理,镜像构建,Dockerfile常用命令
Posted Leo Han
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker镜像相关原理,镜像构建,Dockerfile常用命令相关的知识,希望对你有一定的参考价值。
我们知道,传统的开发部署流程是,开发将程序开发完成之后,编写相关的部署文档,然后将程序部署包和部署文档交给运维,运维根据部署文档在生产环境部署程序,但是经常会出现的问题是,程序在开发的环境能够正常运行但是在生产的环境却运行不了,给运维带来了极大的难度。这个问题主要的原因是在于二者的运行环境导致。
而docker的出现带来了便利,docker中的交付不在是一个部署程序,而是部署程序和其对应的环境,交付的是一个镜像。
docker镜像实际上一层一层的文件系统组成,称为unionFS(联合文件系统)。
一般我们常见的linux系统中有如下两个文件系统很重要:bootfs 和 rootfs。
bootfs主要包含bootloader和kernel,bootloader加载kernel,Linux系统启动的时候会加载bootfs文件系统,docker镜像的最底层就是bootfs
。这一层与我们典型的Linux系统是一样的,包含boot加载器和内核,当boot加载完之后,整个内核都在内存中了,此时内存的使用权由bootfs转交给内核,系统也会在此时卸载bootfs。
rootfs,在bootfs之上,包含典型的linux系统中的/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同发型版本的linux,如unbantu,centos
一个精简的系统,rootfs可以很小,只需要最基本的命令、工具和程序库即可,底层可以直接用宿主机的kernel,只需要提供rootfs,因此,不同的linux发行版本,boofs基本一致的,rootfs会有差别,不同发行版本可以公用bootfs
docker底层使用的是宿主机的bootfs,因此加载速度会特别快,秒级
docker在bootfs上使用自己的rootfs,称为base image,即所谓的基础镜像
,然后在上面可以叠加其他镜像。
我们一般安装centos系统都需要几个G大小,但是docker下载的centos镜像却只需要几百兆,这就是这个原因,docker的centos镜像只需要rootfs,不需要bootfs。
docker中采用分层镜像,能够最大程度的共享资源。如果有多个镜像都从相同的基础镜像构建而来,那么在宿主机上只需要保留一份基础镜像,同时内存中也只需要加载一份基础镜像,就可以为所有的容器服务,而且镜像的每一层都可以被共享。
docker中镜像都是可读的,当docker容器启动的时候,一个新的可写层被加载到镜像的顶部,这层通常称为容器层
,容器层之下的都称为镜像层
一般我们构建docker镜像大部分使用Dockerfile构建,构建流程大致如下:
docker执行Dockerfile的大致流程:
- docker从基础镜像上运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似docker commit的操作命令提交一个镜像
- docker在基于上述提交的镜像运行一个新的容器
- 执行Dockerfile中的下一条指令重复上述过程知道所有的命令都执行完成
Dockerfile构建过程中常用命令如下:
- FROM 指定基础镜像,如:
FROM ubuntu:18.04
- MAINTAINER 镜像维护者信息
FROM alpine:3.8
MAINTAINER LeoHan
- RUN 构建时运行的命令
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
- ENV 在镜像构建过程中设置环境变量
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
ENV JDK_VERSION 1.8
ENV JDK_LOCAL /root/1.8
ENV JDK_HOME /usr/local/jdk8
- ADD、COPY 拷贝宿主机上的文件到镜像中,但是ADD会自动处理URL和解压tar包
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
ENV JDK_VERSION 1.8
ENV JDK_LOCAL /root/1.8
ENV JDK_HOME /usr/local/jdk8
COPY $JDK_LOCAL/* $JDK_HOME/
- EXPOSE 当前容器对外暴露的端口,这里只是对docker服务提供这个端口信息,并不会改变任何网络信息,如果需要通过该端口访问,需要在启动容器的时候通过
-P
参数将端口发布出来
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
ENV JDK_VERSION 1.8
ENV JDK_LOCAL /root/1.8
ENV JDK_HOME /usr/local/jdk8
COPY $JDK_LOCAL/* $JDK_HOME/
EXPOSE 8080
- WORKDIR 对后续的RUN、CMD、ENTRYPOINT、ADD、COPY指令设置工作目录,可以多次使用,支持相对路径,按上次定义的WORKDIR解析
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
ENV JDK_VERSION 1.8
ENV JDK_LOCAL /root/1.8
ENV JDK_HOME /usr/local/jdk8
COPY $JDK_LOCAL/* $JDK_HOME/
EXPOSE 8080
WORKDIR /data1
WORKDIR /data2
- VOLUME 向基于该镜像的容器添加数据卷
FROM alpine:3.8
MAINTAINER LeoHan
RUN echo "start build"
RUN mkdir /usr/local/jdk8
ENV JDK_VERSION 1.8
ENV JDK_LOCAL /root/1.8
ENV JDK_HOME /usr/local/jdk8
COPY $JDK_LOCAL/* $JDK_HOME/
EXPOSE 8080
VOLME ["/data1","/data2"]
- CMD 指定一个容器要启动的时候运行的命令,类似RUN,但是RUN是在镜像构建的时候运行,而CMD则是容器在启动的时候运行,类似于docker run,多个CMD命令只会使用最后一个
CMD ["/bin/sh"]
#传递参数
CMD [“/usr/local/jdk/bin/java","-version"]
- ENTRYPOINT 与CMD非常类似,
但是CMD命令会被docker run命令行中的命令覆盖
,而ENTRYPOINT则不会。另外docker run命令行中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指令中指定的命令
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
如果将上述命令调整如下:
ENTRYPOINT ["/usr/sbin/nginx"]
然后在docker run中传递参数:
docker run -i -t xxxx -g "daemon off;"
如果同时定义了CMD和ENTRYPOINT,则CMD会被当成ENTRYPOINT参数
:
ENTRYPOINT ["/usr/local/jdk/bin/java"]
CMD ["-version"]
- ONBUILD 当一个镜像被用作其他镜像的基础镜像的时候会触发执行
- LABEL 为镜像添加元数据,键值对形式, key=value
LABEL version="1.0.1" name="test"
而后通过docker inspect 能够查看到元数据信息
- ARG 定义可以在docker build命令时传递给构建运行时的变量,通过 --build-arg标志即可,用户只能在构建时指定在Dockerfile中定义过的参数
ARG version
#设置默认值
ARG name=test
然后可以如下传递:
docker build --build-arg version=1.0.1
Dockerfile常用命令总结:
命令名称 | 作用 | 说明 |
---|---|---|
FROM | 指定基础镜像 | 如:FROM alpine:3.8 |
MAINTAINER | 开发维护者相关信息 | MAINTAINER LeoHan |
RUN | 构建时运行的命令 | RUN echo “hello world” |
ENV | 在镜像构建过程中设置环境变量 | ENV version 1.0.1 |
EXPOSE | 当前容器对外暴露的端口,这里只是对docker服务提供这个端口信息,并不会改变任何网络信息,如果需要通过该端口访问,需要在启动容器的时候通过-P 参数将端口发布出来 | EXPOSE 8080 |
ADD、COPY | 拷贝宿主机上的文件到镜像中,但是ADD会自动处理URL和解压tar包 | |
WORKDIR | 对后续的RUN、CMD、ENTRYPOINT、ADD、COPY指令设置工作目录,可以多次使用,支持相对路径,按上次定义的WORKDIR解析,可以理解为相当于切换了工作目录,CMD 、ENTRYPOINT 都在改目录下工作 | |
VOLUME | 向基于该镜像的容器添加数据卷 | VOLUME ["/data1","/data2"] |
CMD | 指定一个容器要启动的时候运行的命令,类似RUN,但是RUN是在镜像构建的时候运行,而CMD则是容器在启动的时候运行,类似于docker run,多个CMD命令只会使用最后一个 | |
ENTRYPOINT | 与CMD非常类似,但是CMD命令会被docker run命令行中的命令覆盖 ,而ENTRYPOINT则不会。另外docker run命令行中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指令中指定的命令 | |
ONBUILD | 当一个镜像被用作其他镜像的基础镜像的时候会触发执行 | |
LABEL | 为镜像添加元数据,键值对形式, key=value | |
ARG | 定义可以在docker build命令时传递给构建运行时的变量,通过 --build-arg标志即可,用户只能在构建时指定在Dockerfile中定义过的参数 |
以上是关于docker镜像相关原理,镜像构建,Dockerfile常用命令的主要内容,如果未能解决你的问题,请参考以下文章