DockerFile 编译语法详解

网友投稿 239 2022-10-20

DockerFile 编译语法详解

Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像,本小结首先介绍Dockerfile典型的基本结构和它支持的众多指令,并具体讲解通过这些指令来编写定制镜像的Dockerfile,以及如何生成镜像.最后介绍使用Dockerfile的一些最佳实践经验.

DockerFile基本结构

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行,一般而言,Dockerfile分为四部分.基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令.例如下面的一个小例子.

# This Dockerfile uses the ubuntu imageFROM ubuntu:lastest# Maintainer: docker_user (@docker_user)MAINTAINER docker_user docker_user@email.com# Commands to update the imageRUN echo "deb raring main universe" >> /etc/apt/sources.listRUN apt-get update && apt-get install -y nginxRUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf# Commands when creating a new containerCMD /usr/sbin/nginx

其中,一开始必须指明所基于的镜像名称,接下来一般是说明维护者信息.后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令.每运行一条RUN指令,镜像就添加新的一层,并提交.最后是CMD指令,用来指定运行容器时的操作命令.

实例1: 在​​debian:latest​​基础镜像基础上安装Nginx环境,从而创建一个新的nginx镜像.

FROM debian:latestMAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"ENV NGINX_VERSION 1.10.1-1~jessieRUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \&& echo "deb jessie nginx" >> /etc/apt/sources.list \&& apt-get update \&& apt-get install --no-install-recommends --no-install-suggests -y \ca-certificates \nginx=${NGINX_VERSION} \nginx-module-xslt \nginx-module-geoip \nginx-module-image-filter \nginx-module-perl \nginx-module-njs \gettext-base \&& rm -rf /var/lib/apt/lists/*# forward request and error logs to docker log collectorRUN ln -sf /dev/stdout /var/log/nginx/access.log \&& ln -sf /dev/stderr /var/log/nginx/error.logEXPOSE 80 443CMD ["nginx", "-g", "daemon off;"]

实例2: 基于​​buildpack-deps:latest​​基础镜像,安装Golang相关环境,制作一个GO语言的运行环境镜像.

FROM buildpack-deps:lastest# gcc for cgoRUN apt-get update && apt-get install -y --no-install-recommends \g++ \gcc \libc6-dev \make \&& rm -rf /var/lib/apt/lists/*ENV GOLANG_VERSION 1.6.3ENV GOLANG_DOWNLOAD_URL GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aebRUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \&& echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \&& tar -C /usr/local -xzf golang.tar.gz \&& rm golang.tar.gzENV GOPATH /goENV PATH $GOPATH/bin:/usr/local/go/bin:$PATHRUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"WORKDIR $GOPATHCOPY go-wrapper /usr/local/bin/

DockerFile命令详解

指令的一般格式为​​INSTRUCTION arguments​​指令包括FROM、MAINTAINER、RUN等,参见下表.

接下来,我将详细介绍几个常用命令的参数的详细说明信息.

FROM:(指定基础镜像的名称)

构建指令,必须指定且需要在Dockerfile其他指令的前面.后续的指令都依赖于该指令指定的image,FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库.

example: FROM centos:latest FROM ubuntu:14.04

MAINTAINER:(指定镜像创建者信息)

构建指令,用于将image的制作者相关的信息写入到image中,当我们对该image执行docker inspect命令时,输出中有相应的字段记录该信息.

example: MAINTAINER LyShark "mkdirs.com"

RUN:(运行命令,安装软件用)

RUN指令是用来执行命令行命令的,由于命令行的强大能力,RUN指令在定制镜像时是最常用的指令之一.

设置指令,用于container启动时指定的操作.该操作可以是执行自定义脚本,也可以是执行系统命令.该指令只能在文件中存在一次,如果有多个,则只执行最后一条.

FROM centos:latest RUN yum install -y gcc libc6-dev make RUN wget -O redis.tar.gz " RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install

Dockerfile 中每一个指令都会建立一层,RUN也不例外.每一个RUN的行为,就和刚才我们手工建立镜像的过程一样,新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像.

而上面的这种写法,创建了 6 层镜像.这是完全没有意义的,不仅仅增加了构建部署的时间,也很容易出错,这是很多初学 Docker 的人常犯的一个错误,Union FS 是有最大层数限制的,比如 AUFS曾经是最大不得超过 42 层,现在是不得超过127 层.

上面的 Dockerfile 正确的写法应该是这样:

FROM centos:latestRUN buildDeps='gcc libc6-dev make' \ && apt-get install -y $buildDeps \ && wget -O redis.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

CMD:(设置容器启动时执行的操作)

设置指令,用于容器启动时指定的操作,该操作可以是执行自定义脚本,也可以是执行系统命令,该指令只能在文件中存在一次,如果有多个,则只执行最后一条.

example: CMD echo "Hello, World!"

ENTRYPOINT:(设置容器启动时执行的操作)

设置指令,指定容器启动时执行的命令,可以多次设置,但是只有最后一个有效.

example: ENTRYPOINT ls -l

该指令的使用分为两种情况,一种是独自使用,另一种和CMD指令配合使用.当独自使用时,如果你还使用了CMD命令且CMD是一个完整的可执行的命令,那么CMD指令和ENTRYPOINT会互相覆盖只有最后一个CMD或者ENTRYPOINT有效.如下命令:CMD指令将不会被执行,只有ENTRYPOINT指令被执行

example: CMD echo "Hello, World!" ENTRYPOINT ls -l

另一种用法和CMD指令配合使用来指定ENTRYPOINT的默认参数,这时CMD指令不是一个完整的可执行命令,仅仅是参数部分:ENTRYPOINT指令只能使用JSON方式指定执行命令,而不能指定参数.

example: FROM centos:latest CMD ["-l"] ENTRYPOINT ["/usr/bin/ls"]

USER:(设置container容器的用户)

设置指令,设置启动容器的用户,默认是root用户.或者说以那个身份的用户运行容器,如下所示运行memcached,并以daemon用户运行.

example: USER daemon = ENTRYPOINT ["memcached", "-u", "daemon"]

EXPOSE:(指定容器需要映射到宿主机器的端口)

设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口.当你需要访问容器的时候,可以不是用容器的IP地址而是使用宿主机器的IP地址和映射后的端口.要完成整个操作需要两个步骤,首先在Dockerfile使用EXPOSE设置需要映射的容器端口,然后在运行容器的时候指定-p选项加上EXPOSE设置的端口,这样EXPOSE设置的端口号会被随机映射成宿主机器中的一个端口号.也可以指定需要映射到宿主机器的那个端口,这时要确保宿主机器上的端口号没有被使用.EXPOSE指令可以一次设置多个端口号,相应的运行容器的时候,可以配套的多次使用-p选项.

example: 映射一个端口 EXPOSE 22 相应的运行容器使用的命令 docker run -p port1 image 映射多个端口 EXPOSE port1 port2 port3 相应的运行容器使用的命令 docker run -p port1 -p port2 -p port3 image 还可以指定需要映射到宿主机器上的某个端口号 docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image

ENV:(用于设置环境变量)

构建指令,在image中设置一个环境变量.设置了后,后续的RUN命令都可以使用,container启动后,可以通过docker inspect查看这个环境变量,也可以通过在​​docker run --env key=value​​时设置或修改环境变量.假如你安装了JAVA程序,需要设置JAVA_HOME,那么可以在Dockerfile中这样写:

example: ENV JAVA_HOME /path/to/java/dirent

ADD:(从src复制文件到容器的dest路径)

example: ADD 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url 是容器中的绝对路径

COPY:(从src复制文件到容器的dest路径)

example: COPY

VOLUME:(指定挂载点)

设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用.我们知道容器使用的是AUFS这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失.当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令.

examp: FROM base VOLUME ["/tmp/data"]

WORKDIR:(切换目录)

设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效.

example: WORKDIR /p1 WORKDIR p2 RUN vim a.txt

ONBUILD:(在子镜像中执行)

ONBUILD指定的命令在构建镜像时并不执行,而是在它的子镜像中执行.

example: ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src

好了关于编译命令还有很多,这里就不一一列举了,更多指令操作语法请自行百度,下面我们来看使用DockerFile编译构建一些好玩的东西吧,相信看完下面的小例子,你就能丰衣足食了.

构建Apache镜像

Apache是一个高稳定性的、商业级别的开源Web服务器.目前Apache已经是世界使用排名第一的Web服务器软件,由于其良好的跨平台和安全性,Apache被广泛应用在多种平台和操作系统上.作为Apache软件基金会支持的项目,它的开发者社区完善而高效.自1995年发布至今,一直以高标准进行维护与开发.Apache名称源自美国的西南部一个印第安人部落:阿帕奇族,它支持类UNIX和Windows系统.

1.首先我们要解决Docker容器内不得网络问题.修改DockerDNS,默认没有文件自行创建即可.

[root@localhost ~]# vim /etc/default/dockerdocker_OPTS="--dns 8.8.8.8 --dns 114.114.114.114"[root@localhost ~]# systemctl restart docker

2.接着在当前目录创建一个Dockerfile文件,和一个index.html文件,文件内容如下.

[root@localhost ~]# vim DockerFileFROM centos:latestMAINTAINER email@email.comRUN yum install -y -q apr apr-util ./index.html /var/80ENTRYPOINT apachectl start && tail -f /var/log/build​​​命令创建​​centos:~]# docker build -t centos:.Sending build context to Docker daemon 18.94kBStep 1/6 : FROM centos:latest....省略....Successfully built 65d0de3819dfSuccessfully tagged centos:~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos 65d0de3819df 36 seconds ago 305MBcentos latest 1e1148e4cc2c 11 days ago 202MB[root@localhost ~]# docker run -itd -p 80:80 centos:~]# vim /etc/default/dockerdocker_OPTS="--dns 8.8.8.8 --dns 114.114.114.114"[root@localhost ~]# systemctl restart docker

2.接着在当前目录创建一个Dockerfile文件,和一个index.html文件,文件内容如下.

[root@localhost ~]# vim DockerFileFROM centos:latestMAINTAINER email@email.comRUN yum install -y epel-releaseRUN yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-develRUN rpm -i yum install -y nginxEXPOSE 80ENTRYPOINT nginx && tail -f /var/log/nginx/access.log #tail必须加,否则容器瞬间终止

3.开始通过dockerfile编译生成​​nginx:centos​​镜像文件.

[root@localhost ~]# docker build -t nginx:centos .Sending build context to Docker daemon 18.43kBStep 1/8 : FROM centos:latest....省略....Successfully built 956a361043bcSuccessfully tagged nginx:centos

4.查看生成的镜像文件,并运行这个镜像测试一下吧.

[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEnginx centos 956a361043bc About a minute ago 591MBcentos latest 1e1148e4cc2c 11 days ago 202MB[root@localhost ~]# docker run --name nginx -p 80:80 -d nginx:centos[root@localhost ~]# curl 127.0.0.1

构建Tomcat镜像

Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对Servlet和Java Server Page(JSP)的支持.同时,它提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等.由于Tomcat本身也内含了一个HTTP服务器,也可以当作一个单独的Web服务器来使用.下面介绍如何定制Tomcat镜像.

1.首先准备好原材料,Tomcat,jdk环境.

[root@localhost ~]# ls -lhtotal 100M-rw-r--r-- 1 root root 92M Dec 16 23:21 jdk.tar.gz-rw-r--r-- 1 root root 7.6M Dec 16 23:21 tomcat.tar.gz

2.编写这个构建模板文件,如下内容.

[root@localhost ~]# vim DockerfileFROM centos:latestMAINTAINER email@email.comADD ./tomcat.tar.gz /rootADD ./jdk.tar.gz /rootENV JAVA_HOME /root/jdk1.7.0_25ENV PATH $JAVA_HOME/bin:$PATHEXPOSE 8080ENTRYPOINT /root/apache-tomcat-7.0.42/bin/startup.sh && tail -F /root/apache-tomcat-7.0.42/logs/catalina.out

3.使用​​docker build​​​命令创建​​centos:tomcat​​镜像,注意命令最后的"."表示当前目录.

[root@localhost ~]# docker build -t centos:tomcat .Sending build context to Docker daemon 104.3MBStep 1/8 : FROM centos:lastest....省略....Successfully built feac1f1c6ed4Successfully tagged centos:tomcat[root@localhost ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos tomcat 65d0de3819df 36 seconds ago 405MBcentos latest 1e1148e4cc2c 11 days ago 202MB

4.下面开始使用​​run​​​指令测试镜像,可以使用​​-P​​参数映射需要开放的端口(22和80端口)

[root@localhost ~]# docker run --name tomcat -p 80:8080 -d centos:tomcat[root@localhost ~]# curl 127.0.0.1:80[root@localhost ~]# docker save 镜像ID > /home/xxx.tar

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java实现二叉树的示例代码(递归&迭代)
下一篇:Docker 构建私有镜像仓库
相关文章

 发表评论

暂时没有评论,来抢沙发吧~