DockerFile 编译语法详解(5)


title: DockerFile 编译语法详解(5)
date: 2018-12-16 16:53:20
tags:html

  • Docker
    categories: Docker
    copyright: true
    ---

Docker是基于Go语言实现的开源容器项目,Docker让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的 Linux 机器上,也能够实现虚拟化.容器是彻底使用沙箱机制,相互之间不会有任何接口,Docker诞生于2013年年初,最初发起者是dotCloud公司.Docker自开源后受到普遍的关注和讨论,目前已有多个相关项目(包括Docker三剑客、Kubernetes等),逐渐造成了围绕Docker容器的生态体系,因为Docker在业界形成的影响力实在太大,dotCloud公司后来也直接更名为Docker Inc,并专一于Docker相关技术和产品的开发.java

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

python

DockerFile基本结构

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

# 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 "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx

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

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

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语言的运行环境镜像.redis

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等,参见下表.docker

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

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

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

构建指令,必须指定且须要在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、POP三、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
相关文章
相关标签/搜索