龙空技术网

Dockerfile详解

龙潭山涛 103

前言:

目前咱们对“dockerfile 例子”都比较关怀,同学们都需要剖析一些“dockerfile 例子”的相关知识。那么小编同时在网络上汇集了一些有关“dockerfile 例子””的相关文章,希望看官们能喜欢,看官们一起来学习一下吧!

一、关于Docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

一个完整的Docker有以下几个部分组成:

DockerClient客户端

Docker Daemon守护进程

Docker Image镜像

DockerContainer容器

1、Docker为什么比虚拟机快

Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu、内存利用率上Docker将会在效率上有明显优势。

Docker利用的是宿主机的内核,而不需要Guest OS,因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统,避免了引导、加载操作系统内核这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的,而Docker由于直接利用宿主机的操作系统则省略了这个过程,因此新建一个Docker容器只需要几秒钟。

2、镜像命令

docker images #查看所有本地主机上的镜像 可以使用docker image ls代替。

docker images -aq #显示所有镜像id

docker search 镜像名称 #搜索镜像

docker pull 镜像名称 #下载镜像

docker rmi -f 镜像id #删除单个镜像

docker rmi -f 镜像id 镜像id 镜像id #删除多个镜像

3、容器命令

docker run 镜像id #新建容器并启动

docker ps #列出所有运行的容器

docker rm 容器id #删除指定容器

docker start 容器id #启动容器

docker restart 容器id #重启容器

docker stop 容器id #停止当前正在运行的容器

docker kill 容器id #强制停止当前容器

二、关于Dockerfile

在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

一个Dockerfile的示例如下所示:

#基于centos镜像

FROM centos

#维护人的信息

MAINTAINER The CentOS Project <303323496@qq.com>

#安装httpd软件包

RUN yum -y update

RUN yum -y install httpd

#开启80端口

EXPOSE 80

#复制网站首页文件至镜像中web站点下

ADD index.html /var/www/html/index.html

#复制该脚本至镜像中,并修改其权限

ADD run.sh /run.sh

RUN chmod 775 /run.sh

#当启动容器时执行的脚本文件

CMD ["/run.sh"]

由上可知,Dockerfile结构大致分为四个部分:

(1)基础镜像信息

(2)维护者信息

(3)镜像操作指令

(4)容器启动时执行指令。

Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。下面会对上面使用到的一些常用指令做一些介绍。

三、Dockerfile常用指令

首先,来一张通俗易懂的全景图:

2.1 FROM

定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

格式:

  FROM <image>

  FROM <image>:<tag>

  FROM <image>@<digest>

示例:

  FROM mysql:5.6

注:

  tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像

2.2 MAINTAINER

维护者信息,例如:

格式:

MAINTAINER <name>

示例:

MAINTAINER Jasper Xu

MAINTAINER sorex@163.com

MAINTAINER Jasper Xu <sorex@163.com>

2.3 RUN

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:shell执行格式:

RUN <command>

exec执行格式:

RUN ["executable", "param1", "param2"]示例:

RUN ["executable", "param1", "param2"]

RUN apk update

RUN ["/etc/execfile", "arg1", "arg1"]注:

  RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

2.4 CMD

启动容器时执行的Shell命令,例如:

格式:

CMD ["executable","param1","param2"] (执行可执行文件,优先)

CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)

CMD command param1 param2 (执行shell内部命令)示例:

CMD echo "This is a test." | wc -

CMD ["/usr/bin/wc","--help"]

注:

  CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

2.5 EXPOSE

声明容器运行的服务端口,例如:

格式:

EXPOSE <port> [<port>...]示例:

EXPOSE 80 443

EXPOSE 8080

EXPOSE 11211/tcp 11211/udp

注:

  EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

2.6 ENV

设置环境内环境变量,例如:

格式:

ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量

ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行示例:

ENV myName John Doe

ENV myDog Rex The Dog

ENV myCat=fluffy

2.7 ADD

拷贝文件或目录到镜像中,例如:

格式:

ADD <src>... <dest>

ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

示例:

ADD hom* /mydir/ # 添加所有以"hom"开头的文件

ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"

ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/

ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/

2.8 COPY

拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压,例如:

COPY ./start.sh /start.sh

2.9 ENTRYPOINT

启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序,例如:

格式:

ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)

ENTRYPOINT command param1 param2 (shell内部命令)

示例:

FROM ubuntu

ENTRYPOINT ["top", "-b"]

CMD ["-c"]

注:

   ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。

2.10 VOLUME

指定容器挂载点到宿主机自动生成的目录或其他容器,例如:

格式:

VOLUME ["/path/to/dir"]

示例:

VOLUME ["/data"]

VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"

注:

  一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

1 卷可以容器间共享和重用2 容器并不一定要和其它容器共享卷3 修改卷后会立即生效4 对卷的修改不会对镜像产生影响5 卷会一直存在,直到没有任何容器在使用它

2.11 USER

为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户,例如:

格式:

  USER user

  USER user:group

  USER uid

  USER uid:gid

  USER user:gid

  USER uid:group

示例:

  USER www

注:

  使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

2.12 WORKDIR

  为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录,例如:

格式:

WORKDIR /path/to/workdir

示例:

WORKDIR /a (这时工作目录为/a)

WORKDIR b (这时工作目录为/a/b)

WORKDIR c (这时工作目录为/a/b/c)

注:

  通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

2.13 HEALTHCHECK

告诉Docker如何测试容器以检查它是否仍在工作,即健康检查,例如:

HEALTHCHECK --interval=5m --timeout=3s --retries=3 \

CMD curl -f http:/localhost/ || exit 1

  其中,一些选项的说明:

--interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒 -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒 --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒 --retries=N (default: 3):认为检测失败几次为宕机,默认3次

  一些返回值的说明:

0:容器成功是健康的,随时可以使用 1:不健康的容器无法正常工作 2:保留不使用此退出代码2.14 ARG

在构建镜像时,指定一些参数,例如:

FROM centos:6

ARG user # ARG user=root

USER $user

这时,我们在docker build时可以带上自定义参数user了,如下所示:

docker build --build-arg user=edisonzhou Dockerfile .

四、综合Dockerfile案例

下面是一个Java Web应用的镜像Dockerfile,综合使用到了上述介绍中最常用的几个命令:

# Maven build container

FROM maven:3.8.5-openjdk-11 AS maven_build

COPY pom.xml /tmp/

COPY src /tmp/src/

WORKDIR /tmp/

RUN mvn package

#pull base image

FROM openjdk

#maintainer

MAINTAINER dstar55@yahoo.com

#expose port 8080

EXPOSE 8080

#default command

CMD java -jar /data/hello-world-0.1.0.jar

#copy hello world to docker image from builder image

COPY --from=maven_build /tmp/target/hello-world-0.1.0.jar /data/hello-world-0.1.0.jar

有了Dockerfile,就可以创建镜像了:

docker build -t="hello-world-java" .

最后,可以通过以下命令创建容器:

docker run -p 8080:8080 -it --rm hello-world-java

五、Dockers-compose编排

下面是一个Docker-compose编排的例子:

version: "3.0"

services:

hello-world:

build:

context: ./

dockerfile: Dockerfile

ports:

- 8080:8080

六、小结

本文介绍了Dockerfile的背景和组成,以及最常用的一些Dockerfile命令,最后介绍了一个综合使用了Dockefile指令的一个案例来说明Dockerfile的应用。

标签: #dockerfile 例子 #docker dockerfile详解