• DockerFile 编译语法详解


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

    DockerFile基本结构

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

    # This Dockerfile uses the ubuntu image
    
    FROM ubuntu:lastest
    # Maintainer: docker_user <docker_user at email.com> (@docker_user)
    MAINTAINER docker_user docker_user@email.com
    # Commands to update the image
    RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
    RUN apt-get update && apt-get install -y nginx
    RUN echo "
    daemon off;" >> /etc/nginx/nginx.conf
    # Commands when creating a new container
    CMD /usr/sbin/nginx
    

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

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

    FROM debian:latest
    MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"
    ENV NGINX_VERSION 1.10.1-1~jessie
    RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC64107
    9A6ABABF5BD827BD9BF62 
    && echo "deb http://nginx.org/packages/debian/ 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 collector
    RUN ln -sf /dev/stdout /var/log/nginx/access.log 
    && ln -sf /dev/stderr /var/log/nginx/error.log
    EXPOSE 80 443
    CMD ["nginx", "-g", "daemon off;"]
    

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

    FROM buildpack-deps:lastest
    # gcc for cgo
    RUN 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.3
    ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
    ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd
    7561275a87aeb
    RUN 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.gz
    ENV GOPATH /go
    ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
    RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
    WORKDIR $GOPATH
    COPY go-wrapper /usr/local/bin/
    

    ## DockerFile命令详解

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

    指 令 指 令 说 明
    FROM 创建镜像的基础镜像
    MAINTAINER 维护者信息(说明)
    RUN 运行命令,安装软件用
    CMD 启动容器时默认执行的命令
    LABEL 指生成镜像的元数据标签信息
    EXPOSE 声明镜像内服务所监听的端口
    ENV 声明环境变量
    ADD 复制指令,将拷贝到容器中的
    COPY(推荐) 复制指令,将拷贝到容器中的
    ENTRYPOINT 指定镜像的默认入口
    VOLUME 创建数据卷挂载点
    USER 指定运行容器时的用户名或UID
    WORKDIR 配置工作目录
    ARG 指定镜像内使用的参数
    ONBUILD 配置当所创建镜像作为其他镜像基础时,所执行的命令
    STOPSIGNAL 容器退出的信号值
    HEALTHCHECK 如何进行健康检查
    SHELL 指定使用SHELL时的默认shell类型

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

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

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

    example:
    	FROM centos:latest
    	FROM ubuntu:14.04
    

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

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

    example:
    	MAINTAINER  LyShark "www.mkdirs.com"
    

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

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

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

    FROM centos:latest
    	RUN yum install -y gcc libc6-dev make
    	RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.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:latest
    RUN buildDeps='gcc libc6-dev make' 
        && 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
    

    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 <src> <dest>  
    		<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url
    		<dest> 是容器中的绝对路径
    

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

    example:	
    	COPY <src> <dest>
    

    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/docker
    
    docker_OPTS="--dns 8.8.8.8 --dns 114.114.114.114"
    
    [root@localhost ~]# systemctl restart docker
    

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

    [root@localhost ~]# vim DockerFile
    
    FROM centos:latest
    MAINTAINER email@email.com
    
    RUN yum install -y -q apr apr-util httpd
    COPY ./index.html /var/www/html/
    
    EXPOSE 80
    ENTRYPOINT apachectl start && tail -f /var/log/httpd/access_log
    

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

    [root@localhost ~]# docker build -t centos:httpd .
    
    Sending build context to Docker daemon  18.94kB
    Step 1/6 : FROM centos:latest
    ....省略....
    Successfully built 65d0de3819df
    Successfully tagged centos:httpd
    

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

    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              httpd               65d0de3819df        36 seconds ago      305MB
    centos              latest              1e1148e4cc2c        11 days ago         202MB
    
    [root@localhost ~]# docker run -itd -p 80:80 centos:httpd
    

    ## 构建Nginx镜像

    Nginx是一款功能强大的开源反向代理服务器,支持HTTP、HTTPS、SMTP、POP3、IMAP等协议.它也可以作为负载均衡器、HTTP缓存或Web服务器.Nginx一开始就专注于高并发和高性能的应用场景,它使用类BSD开源协议,支持Linux、BSD、Mac、Solaris、AIX等类Unix系统,同时也有Windows上的移植版本.

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

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

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

    [root@localhost ~]# vim DockerFile
    
    FROM centos:latest
    MAINTAINER email@email.com
    
    RUN yum install -y epel-release
    RUN yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
    RUN rpm -i http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
    RUN yum install -y nginx
    
    EXPOSE 80
    ENTRYPOINT 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.43kB
    Step 1/8 : FROM centos:latest
    ....省略....
    Successfully built 956a361043bc
    Successfully tagged nginx:centos
    

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

    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
    nginx               centos              956a361043bc        About a minute ago   591MB
    centos              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 -lh
    total 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 Dockerfile
    
    FROM centos:latest
    MAINTAINER email@email.com
    
    ADD ./tomcat.tar.gz /root
    ADD ./jdk.tar.gz /root
    
    ENV JAVA_HOME /root/jdk1.7.0_25
    ENV PATH $JAVA_HOME/bin:$PATH
    
    EXPOSE 8080
    
    ENTRYPOINT /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.3MB
    Step 1/8 : FROM centos:lastest
    ....省略....
    Successfully built feac1f1c6ed4
    Successfully tagged centos:tomcat
    
    [root@localhost ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              tomcat              65d0de3819df        36 seconds ago      405MB
    centos              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
    

    参考文献:《Docker技术入门与实战》《Docker基础与实战》

  • 相关阅读:
    MySQL_基础_TCL事务控制语言
    MySQL_基础_DDL数据定义语言
    MySQL_基础_DQL数据查询语言
    MySQL_基础_DML数据操纵语言
    MySQL_基础_存储过程和函数
    MySQL_基础_变量
    linux 常用命令
    灵活QinQ示例
    RRPP 演示实例
    ERPS实例演示
  • 原文地址:https://www.cnblogs.com/LyShark/p/10872330.html
Copyright © 2020-2023  润新知