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. RedisTemplate连接不释放、Redis断线不重连问题、Redis连接数高飙升

    使用RedisTemplate操作Redis数据,但遇到网络断线后不会重新连接 毫无头绪 一顿捣鼓 最终解决 整理如下 帮助更多的人 1.起因 使用RedisTemplate 配置 开启了事务 ena ...

  2. Longhorn 云原生分布式块存储解决方案设计架构和概念

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? 目录 1. 设计 1.1. Longhorn Manager 和 Longhorn Engine 1.2 ...

  3. Golang语言系列-14-单元测试

    单元测试 字符串切割函数 package split_string import ( "fmt" "strings" ) // Split:切割字符串 // e ...

  4. SQL语法 - WHERE 子句

    WHERE 子句用于规定选择的标准. 语法 SELECT 列名称 FROM 表名称 WHERE 列 运算符 值 下面的运算符可在 WHERE 子句中使用: 操作符 描述 = 等于 <> 不 ...

  5. SpringCloud升级之路2020.0.x版-17.Eureka的实例配置

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 上一节我们提到过, ...

  6. 5 秒克隆声音「GitHub 热点速览 v.21.34」

    作者:HelloGitHub-小鱼干 本周特推的 2 个项目都很好用,Realtime-Voice-Clone-Chinese 能让你无需开启变声音,即可获得一个特定声音的语音.这个声音可以是你朋友的 ...

  7. 深入解析多态和方法调用在JVM中的实现

    深入解析多态和方法调用在JVM中的实现 1. 什么是多态 多态(polymorphism)是面向对象编程的三大特性之一,它建立在继承的基础之上.在<Java核心技术卷>中这样定义: 一个对 ...

  8. 分享一份【饿了么】Java面试专家岗面试题,欢迎留言交流哦!

    前段时间有小伙伴去饿了么面试Java专家岗,记录了一面技术相关的问题,大家可以看看. 基础问题 1.数据库事务的隔离级别? 2.事务的几大特性,并谈一下实现原理 3.如何用redis实现消息的发布订阅 ...

  9. 题解 Six(留坑)

    传送门 考场上搞了个三进制状压,结果正确性假了-- 有想到从约数下手,但觉得就光预处理约数复杂度就爆炸就没往这边想-- 首先是关于约数个数的证明,再一次感谢战神: 因为 \(n = \prod p_i ...

  10. noip 模拟 6

    果然考试一多就改不过来了 考试经过 上来看题,T1似乎是一个计数题,但看见1e9的数据范围就觉得不可做,拿了20部分分匆忙跑路 T2是个图论题,不过一看统计种类就发现是自己不会的东西,瞄准30分冲了一 ...