DockerFile 编译语法详解(5)


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

  • Docker
    categories: Docker
    copyright: true
    ---

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

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 "\ndaemon 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


转载于:https://www.cnblogs.com/LyShark/p/10872330.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值