Dockerfile结构

Dockerfile的结构分成了若干部分,每个部分之间的先后顺序有明确的要求:

部分 命令
基础镜像信息 FROM
维护者信息 MAINTAINER
镜像操作指令 RUNCOPYADDEXPOSEWORKDIRONBUILDUSERVOLUME
启动时命令 CMD, ENTRYPOINT

Dockerfile示例

携程Apollo开源项目的Dockerfile为例:

# Dockerfile for apollo-adminservice
# 1. Copy apollo-adminservice-${VERSION}-github.zip to current directory
# 2. Build with: docker build -t apollo-adminservice .
# 3. Run with: docker run -p 8090:8090 -d -v /tmp/logs:/opt/logs --name apollo-adminservice apollo-adminservice FROM openjdk:8-jre-alpine
MAINTAINER ameizi <sxyx2008@163.com> ENV VERSION 1.5.0-SNAPSHOT
ENV SERVER_PORT 8090
# DataSource Info
ENV DS_URL ""
ENV DS_USERNAME ""
ENV DS_PASSWORD "" RUN echo "http://mirrors.aliyun.com/alpine/v3.8/main" > /etc/apk/repositories \
&& echo "http://mirrors.aliyun.com/alpine/v3.8/community" >> /etc/apk/repositories \
&& apk update upgrade \
&& apk add --no-cache procps unzip curl bash tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone ADD apollo-adminservice-${VERSION}-github.zip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip RUN unzip /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip -d /apollo-adminservice \
&& rm -rf /apollo-adminservice/apollo-adminservice-${VERSION}-github.zip \
&& sed -i '$d' /apollo-adminservice/scripts/startup.sh \
&& chmod +x /apollo-adminservice/scripts/startup.sh \
&& echo "tail -f /dev/null" >> /apollo-adminservice/scripts/startup.sh EXPOSE $SERVER_PORT CMD ["/apollo-adminservice/scripts/startup.sh"]

注释

Dockerfile中使用#进行行注释。

ADD 复制文件

格式:

ADD <src> <dest>

src复制文件到容器中的dest

注意:

  1. src可以是文件、目录、URL或压缩包,但是必须在构建上下文也就是Dockerfile所在的目录中
  2. dest/结尾,则认为src是一个目录;dest不以/结尾,则认为src是一个文件。
  3. 如果src是可识别的压缩包格式(gzip, bzip2, xz),则Docker会自动解压到容器的指定destdest中重名的文件不会被覆盖。
  4. 如果指定的dest不存在,则会自动创建dest(含路径中的任何目录),新创建的文件和目录的模式为755,UIG和GID都是0。

ARG 设置构建参数

ARG设置构建时的环境变量,这些指定的参数在容器运行时不再有用。

示例

ARG build # 声明一个构建参数,但没有赋缺省值

ARG webapp_user=wasuser # 声明一个构建参数并指定缺省值

docker build命令构建镜像时,通过--build-arg指定构建参数的值,例如:

docker build --build-arg build=12345 -t darren/test_image .

此时构建Dockerfile中使用到的build的实际值是12345,而webapp_user的实际值是其缺省值。

CMD 容器启动命令

CMD指定容器启动时执行的一条命令。

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

每个Dockerfile只有一个CMD命令,如果指定了多条CMD命令,则只有最后一条会被执行。

启动容器时如果通过命令行指定了运行的命令,将会覆盖Dockerfile中指定的CMD命令。

Docker推荐使用数组语法设置要执行的命令:

CMD ["/bin/bash", "-l"]

COPY 复制文件

COPY类似于ADD

格式:

COPY <src> <dest>

注意:

  1. COPY不支持URL和压缩包。
  2. 如果src是一个目录,则将其中的所有文件拷贝到dest,而不含src本身;
  3. dest必须是一个绝对路径
  4. 该指令创建的文件或目录的UID和GID都是0
  5. 复制时保留被拷贝目录/文件的元数据

ENTRYPOINT 入口点

CMD指令类似,同样指定容器启动时执行的命令。

docker run命令中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指定的命令。

格式:

ENTRYPOINT ["executable", "param1", "param2"]

ENTRYPOINT command arg1 arg2

示例:

在Dockerfile中:

ENTRYPOIINT ["/usr/sbin/nginx"]

docker run命令中:

docker run -t -i darren/test_image -g "daemon off;"

其中的参数-g "daemon off;"会传递给ENTRYPOINT指定的命令,接在ENTRYPOINT之后,因此,最终实际在启动容器时执行的相当于ENTRYPOINT指令:

ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

其含义是前台进程的形式运行Nginx守护进程。

ENTRYPOINTCMD同时使用时,所有命令行中指定的参数会传递给ENTRYPOINT指令,覆盖CMD指定的参数;当命令行没有额外指定参数时,则ENTRYPOINTCMD指定的参数作为默认的输入。

示例:

ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]

此时可以在docker run命令中显示指定参数从而修改ENTRYPOINT指令的参数,或者使用CMD传给ENTRYPOINT指令的参数,相当于/usr/sbin/nginx -h,即显示Nginx的帮助。

ENV 设置环境变量

ENV设置环境变量,设置的环境变量在容器运行时可以在容器内获取和使用,后续的RUN指令等可以使用ENV指令设置的环境变量。

示例:

  1. 一次定义多个环境变量
ENV RVM_PATH=/home/rvm RVM_ARCHFLAGS="-arch amd64"
  1. 使用环境变量
ENV JAVA_HOME /path/to/java
WORKDIR $JAVA_HOME

ENV指令指定的环境变量会保存到构建的所有容器中,例如Linux容器中通过env命令来查看容器运行时的环境变量。

docker run命令中通过-e选项传递的环境变量只对该命令启动的容器当次运行生效。

EXPOSE 声明暴露的端口

声明容器对外暴露的端口号:

EXPOSE <port1>

EXPOSE <port1> <port2> <port3>

运行时容器真实暴露的端口以命令行中的设定为准,如果在启动一个容器时希望使用其Dockerfile中声明的端口,则使用-P选项:

docker run -P your-docker-image

FROM 指定基础镜像

FROM指定构建使用的基础镜像,FROM命令必须写在其他的指令前。

格式:

FROM <image>

FROM <image>:<tag>

FROM <image>@<digest>

LABEL 添加镜像元数据

LABEL指令添加的元数据需要以键值对的形式指定。

示例:

LABEL version="1.0.0"

LABEL description="This description illustrates \
that label-values can span multi lines." LABEL key1="v1" k2="v2" k3="v3"

注意:

  1. LABEL指令的值中,\可以用来换行。
  2. 推荐将所有元数据放到一条LABEL中执行
  3. 可以通过docker inspect命令来查看镜像的标签

MAINTAINER 维护者信息

用于为Dockerfile署名。

示例:

MAINTAINER darren<darren@darren_s.com>

RUN 执行命令

RUN不同于CMD指令,RUN可以在Dockerfile中出现和执行多次。

在Shell终端中执行命令,Linux中默认是/bin/sh -c,Windows中是cmd /s /c

格式:

RUN <command>

RUN ["executable", "arg1", "arg2", ..., "argN"]

示例:

RUN ["/bin/sh", "-c", "echo Hello Wolrd!"]

USER 指定启动用户

指定启动时的用户,后续的指令都将以该用户执行命令。

示例:

USER wasuser

使用USER指令的各种方式

USER user

USER user:group

USER uid

USER uid:gid

USER user:gid

USER uid:group

如不通过USER指令指定用户,默认的用户为root

可以在docker run命令中通过-u选项覆盖该指令的值。

VOLUME 指定挂载点

向容器添加卷,一个卷是可以存在于一个或多个容器内的特定目录。

使容器内的一个目录具有持久化存储的功能,被指定的目录既可以被容器本身使用,也可以共享给其他容器。

  • 卷可以在容器之间共享和重用
  • 一个容器可以不和别的容器共享卷
  • 对卷的修改立即生效
  • 对卷的修改不会对更新镜像产生影响
  • 卷一直存在到没有容器再使用它

示例:

VOLUME /mnt/data

该指令为每个基于该镜像创建的容器创建一个名为/mnt/data的挂载点。也可以指定多个卷:

VOLUME ["/mnt/project1", "/mnt/project2"]

WORKDIR 指定工作目录

从镜像创建容器时,在容器内设置一个工作目录。

相当于Linux中的cd命令,用于切换到指定的工作目录,后续的指令都将在指定的工作目录下执行。

WORKDIR指令可以多次出现,在不同的工作目录之间进行切换:

WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
RUN [ "rackup" ]

启动容器时可以使用-w选项覆盖工作目录:

docker run -it -w /var/log ubuntu pwd

会将容器内的工作目录设置为/var/log

ONBUILD指令

为镜像添加触发器,当镜像A被作为镜像B的基础镜像,在构建镜像B时,会执行镜像A的ONBUILD指令。

注意:

  1. ONBUILD指令按照其在镜像A中声明的顺序依次执行
  2. ONBUILD指令只能被继承一次,即如果镜像C再以镜像B作为基础镜像,构建镜像C时不会触发镜像A的ONBUILD指令。
  3. 可以认为镜像A的ONBUILD指令在镜像B的FROM指令后立即执行。
  4. FROMMAINTAINERONBUILD指令是不能出现在ONBUILD指令中的。

示例

镜像A中:

ONBUILD ADD . /var/www

镜像B

FROM 镜像A

则会在构建镜像B的Step 0 : FROM阶段就执行镜像A的ONBUILD指令,即将构建上下文中的所有内容添加到/var/www目录

Dockerfile常见命令的更多相关文章

  1. Docker - Dockerfile - 常见命令简介

    概述 感觉是个 比较重要的东西 有个疑问 我是先讲 docker build 还是 先讲 Dockerfile 穿插讲 docker build 最基本的东西 原理 -t -f docker file ...

  2. 016、Dockerfile 常用命令(2019-01-07 周一)

    参考https://www.cnblogs.com/CloudMan6/p/6864000.html   Dokcerfile常见命令   FROM     指定base镜像   MAINTAINER ...

  3. 2 . Linux常见命令

    Linux常见命令格式: 命令名称 选项 参数 ls -alh 文件/目录 --all #ls 显示当前目录内容 #ls -l 显示文件详细信息 #ls -hl h已常见单位显示文件大小 k M G# ...

  4. [Linux基础]Linux基础知识入门及常见命令.

    前言:最近刚安装了Linux系统, 所以学了一些最基本的操作, 在这里把自己总结的笔记记录在这里. 1,V8:192.168.40.10V1:192.168.40.11Linux ip:192.168 ...

  5. 嵌入式Linux开发教程:Linux常见命令(上篇)

    摘要:这是对周立功编著的<嵌入式Linux开发教程>的第7期连载.本期刊载内容有关LinuxLinux常见命令中的导航命令.目录命令和文件命令.下一期将连载网络操作命令.安装卸载文件系统等 ...

  6. 关于XShell的常见使用和设置以及Linux中的常见命令.

    本文部分转自:http://sundful.iteye.com/blog/704079 和 http://www.vckai.com/p/5 有时候在XShell中操作的一些命令傻傻的分不清这个命令到 ...

  7. 重启IIS常见命令

    重启IIS常见命令 http://jingyan.baidu.com/article/4ae03de30d6cfa3efe9e6b4a.html

  8. 一个linux常见命令的列表

    这是一个linux常见命令的列表. 那些有• 标记的条目,你可以直接拷贝到终端上而不需要任何修改,因此你最好开一个终端边读边剪切&拷贝. 所有的命令已在Fedora和Ubuntu下做了测试 命 ...

  9. shell中bash的常见命令

    shell 在计算机科学中,Shell俗称壳,用来区别Kernel(核) Shell分类:1:图形界面shell:通过提供友好的可视化界面,调用相应应用程序,如windows系列操作系统,Linux系 ...

随机推荐

  1. 为什么不建议使用WordPress呢?

    程序过于注重扩展性与动态配置解析,导致执行流程中包含大量的钩子.判断.文件加载等操作,导致执行效率偏低,对服务器要求较高.对系统的开销,尤其是CPU等部分消耗较大,据观察,单个请求在腾讯云s1主机单核 ...

  2. rancher清理主机脚本

    #!/bin/bash #From:rancher #date:2019-10-18 #admin:jarno # 停止服务 systemctl disable kubelet.service sys ...

  3. Shell-04-流程控制

    if语句 1 单分支 2 双分支 示例 3 多分支 for语句 语法 for 变量名 in 取值表; do 语句 done 1 {...} 2 $@ 将位置参数当作独立的字符串来处理 3 $* 所有的 ...

  4. CVPR2021 | 重新思考BatchNorm中的Batch

    ​ 前言 公众号在前面发过三篇分别对BatchNorm解读.分析和总结的文章(文章链接在文末),阅读过这三篇文章的读者对BatchNorm和归一化方法应该已经有了较深的认识和理解.在本文将介绍一篇关于 ...

  5. 关于phpmyadmin getshell

    思考一个问题:如何在获得一个PHP MySQL 搭建网站的phpmyadmin界面后(无论用什么办法,进到phpmyadmin里),进行一个getshell的操作? ...... 0x01山重水复 当 ...

  6. Django推导 安装等

    HTTP协议补充 四大特性: 基于请求响应 基于TCP/IP协议之上的应用层协议 无状态 不能保存用户信息(cookie,session,token) 短链接 请求数据格式: 请求首行(请求方式,ht ...

  7. Visual Studio 2019 使用C语言创建动态链接库(Dll)并使用C语言和C#实现调用

    参考网址:https://blog.csdn.net/weixin_34976988/article/details/99625533 一.创建DLL1.建立动态链接库项目 2.创建头文件和源文件 删 ...

  8. Servlet学习之复习

    Servlet的注册与运行(Servlet程序通常需要存储在<web应用程序目录>\WEB-INF\classes\目录中) 1.注册Servlet:在web.xml文件中,一个<s ...

  9. java js转码解码

    摘自网友:https://blog.csdn.net/sgear/article/details/1509400?utm_medium=distribute.pc_relevant.none-task ...

  10. jdbc操作mysql(四):利用反射封装

    前言 有了前面利用注解拼接sql语句,下面来看一下利用反射获取类的属性和方法 不过好像有一个问题,数据库中的表名和字段中带有下划线该如何解决呢 实践操作 工具类:获取connection对象 publ ...