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. 高楼扔鸡蛋问题(鹰蛋问题) POJ-3783

    这是一道经典的DP模板题. https://vjudge.net/problem/POJ-3783#author=Herlo 一开始也是不知道咋写,尝试找了很多博客,感觉有点领悟之后写下自己的理解. ...

  2. Azure 实践(1)- Azure Devops Server 安装

    1.Azure Devops介绍 Azure DevOps Server 2020 (之前的名称为TFS),作为微软Azure DevOps 的企业私有(on-premises)服务器,是一个为开发团 ...

  3. Use Module and Function instead of Class in Python

    The following scripts run in ipython demonstrate the differences between instance method and static ...

  4. SpringMVC学习04(数据处理及跳转)

    4.数据处理及跳转 4.1结果跳转方式 4.1.1 ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 . 页面 : {视图解析器前缀} ...

  5. [编译] 9、在Linux下搭建 nordic 最新基于 zephyr 的开发烧写环境

    目录 前言 1.概述 2.安装工具 3.获取 nRF Connect SDK 源码 4.安装 Python modules 5.安装 toolchain 6.下载 nRF Command Line T ...

  6. K8s 部署 Gitlab

    K8s 版本:1.20.6 这里使用的镜像不是官方的,而是 Gitlab 容器化中使用非常多的一个第三方镜像:sameersbn/gitlab,基本上和官方保持同步更新.地址:http://www.d ...

  7. miniFTP项目实战三

    项目简介: 在Linux环境下用C语言开发的Vsftpd的简化版本,拥有部分Vsftpd功能和相同的FTP协议,系统的主要架构采用多进程模型,每当有一个新的客户连接到达,主进程就会派生出一个ftp服务 ...

  8. 题解 Cover

    传送门 考场上坚持认为树上背包可以有70pts,于是爆零了 首先我以为是树上背包的部分分其实是树形DP 然后极其魔鬼的正解: 首先我们令 \(dp[i][j]\) 为以i为根的子树覆盖次数至多为j时的 ...

  9. Failed to set locale, defaulting to C.UTF-8

    CentOS 8中执行命令,出现报错:Failed to set locale, defaulting to C.UTF-8 报错原因: 1.没有安装相应的语言包. 2.没有设置正确的语言环境. 解决 ...

  10. 9、二进制安装K8s之增加node

    二进制安装K8s之增加node 1.复制文件,要部署几台就直接复制即可 #二进制文件 scp /data/k8s/bin/{kubelet,kube-proxy} root@192.168.100.1 ...