文档章节

Docker 之 Dockerfile 介绍

whoru
 whoru
发布于 2017/08/11 17:26
字数 2185
阅读 304
收藏 0

1. 基本结构

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

在文件中,支持以 # 开头的注释行。

一般,Dockerfile 共包括四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令

使用流程

➜ mkdir mynginx
➜ cd mynginx
➜ touch Dockerfile
➜ vi Dockerfile

写入如下内容

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index
.html

以上是一个最简单的 Dockerfile,相对完整版的 Dockerfile 示例,请点击这里查看。

2. 常用指令

2.1. FROM

指定当前 Dockerfile 文件所创建的镜像基于哪个基础镜像

格式:

  • FROM <image>
  • FROM <image>:<tag>

注意

  • 一个 Dockerfile 中 FROM 是必备的指令,并 且必须是第一条指令。

  • Docker 还存在一个特殊的镜像,名为 scratch 。

    它是个虚拟概念,并不实际存在,表示一个空白的镜像。

    FROM scratch
    ...
    

    如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

  • 在 Docker 仓库中存在很多高质量的官方镜像

2.2. MAINTAINER

指定维护者信息。

格式:

  • MAINTAINER <name>

2.3. RUN

每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。

格式:

  • RUN <command> 在 shell 终端中运行命令,即 /bin/sh -c
  • RUN ["executable", "param1", "param2"] 使用 exec 执行

比如,我们想指定使用其它终端,就可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"]

注意:Dockerfile 中每一个指令都会建立一层, RUN 也不例外。所以在编写 Dockerfile 的过程中,我们应该尽量避免无意义的层次,采取类似如下示例的操作:

FROM ubuntu:16.04

RUN apt-get update \
	
	# 安装基础工具包
	&& apt-get install -y software-properties-common vim wget  \
    
    # 这里追加其它操作:安装软件、配置服务等
    # ...
    
	# 做一些清理工作
	&& apt-get clean \
    && apt-get autoclean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

提示:在编写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。

2.4. CMD

指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。

格式:

  • CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式

    示例:CMD ["nginx", "-g", "daemon off;"]

  • CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用

  • CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。 CMD 指令就是用于指定默认的容器主进程的启动命令的。

ubuntu 镜像默认的 CMD 是 /bin/bash

注意

  1. 如果指定了多条命令,只有最后一条会被执行。
  2. 如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

2.5. ENTRYPOINT

与 CMD 一样,都是配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。

格式:

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

当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

注意:每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。

2.6. ENV

设置环境变量,会被后续 RUN 指令使用,并在容器运行时保持。

格式:

  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...

示例:

ENV VERSION=1.0 DEBUG=on \

    NAME="Happy Feet"

2.7. COPY

复制本地主机的 <src>(为 Dockerfile 所在目录的相对路径)到容器中的 <dest>。

格式:

  • COPY <源路径>... <目标路径>
  • COPY ["<源路径1>",... "<目标路径>"]

<源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:

COPY hom* /mydir/

COPY hom?.txt /mydir/

<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工 作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建 相关文件都在使用 Git 进行管理的时候。

2.8. ADD

与 COPY 的格式和性质基本一致,但是在 COPY 基础上增加了一些功能。

其中 <src> 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(自动解压为目录)。

在 Docker 官方的最佳实践文档中要求,尽可能的使用 COPY ,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。

注意

ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

因此在 COPY 和 制均使用 COPY 指令中选择的时候,可以遵循这样的原则:所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。

2.9. VOLUME

定义匿名卷。

即创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

格式:

  • VOLUME ["<path1>", "<path2>"...]
  • VOLUME path

运行时可以通过 -v 选项覆盖这个挂载设置,如:

docker run -d -v mydata:/data xxxx

2.10. EXPOSE

告诉 Docker 服务端容器暴露的端口号,供互联系统使用。

格式:

  • EXPOSE <port> [<port>...]

注意

  1. 这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处:

    • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映 射;
    • 用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
  2. 要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。

    • -p ,是 映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问;
    • EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

2.11. USER

指定运行容器时的用户名或 UID,后续的 RUN / CMD / ENTRYPOINT 也会使用指定用户。

格式:

  • USER daemon

与 WORKDIR 指令一样, USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

示例:

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

要临时获取管理员权限可以使用 gosu,而不推荐 sudo,可参照:https://github.com/tianon/gosu

使用示例:

# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis

# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true

# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]

2.12. WORKDIR

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。

格式:

  • WORKDIR /path/to/workdir

我们可以使用多个 WORKDIR 指令,但是后续命令的参数如果是相对路径,则会基于之前命令指定的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

最后的路径是 /a/b/c

2.13. ONBUILD

配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。

格式:

  • ONBUILD [INSTRUCTION]

3. 构建镜像

编写完成 Dockerfile 之后,我们就可以通过 docker build 命令来创建镜像了。

格式:docker build [选项] 路径

在 Dockerfile 所在目录,执行如下命令进行构建:

➜ sudo docker build -t php:v5.6 .
➜ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
php                 5.6                 cb4854aef367        3 months ago        351MB

其中 -t 用于指定镜像的标签信息;. 表示构建上下文的目录

© 著作权归作者所有

whoru
粉丝 17
博文 156
码字总数 76424
作品 0
济南
高级程序员
私信 提问
DICOM:Docker实现增量发布之前期准备

背景: 为了方便整体产品的发布,希望通过docker实现增量发布。大致的思路如下: is-there-a-way-to-add-only-changed-files-to-a-docker-image-as-a-new-layer-with。本博文对这种方式进行了...

zssureqh
2016/07/24
0
0
docker~通过vs2017的Dockerfile来生成镜像

Dockerfile这个东西我们之前是介绍过,它方便,快捷,易用,而在vs2017中也对docker进行了支持,而生成docker image的方式就是有用Dockerfile为基础的,在添加docker支持之后,vs会为我们在根...

mcy247
2017/12/05
0
0
Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用

本篇文章操作系统信息 Windows:Window 10 Visual Studio:2017 15.8.0 创建项目并添加Dockerfile 在VS2017及以上版本上创建一个控制台项目,这里的名称叫【ConsoleAppDockerWindows2】。 创...

alun-chen
2018/11/23
0
0
[笔记] docker入门篇1

1.docker的概念 docker是一个依赖于linux内核的软件。同时是一个典型的C/S架构的软件,分为Docker Client和Docker Server。熟悉github的同学可以和git做一下对比。 1.介绍两个至关重要的概念...

李文良
2016/08/24
6
0
dockerfile介绍与实例演示

1 Dockerfile(总结) 首先来看下什么是dockerfile:Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。Docker程序将这些Dockerfil...

我不是瘦子
2017/11/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

利用mybatis generator生成实体类、Mapper接口以及对应的XML文件

项目中通常会遇到数据的持久化,如果是采用mybatis的orm,就会涉及到生成xml的问题,刚好mybatis官网提供了这么个插件MyBatis Generator,效果简直是棒呆。 1. 首先需要在build.gradle文件中...

啊哈关关
今天
2
0
SpringSocial相关的知识点

使用SprigSocial开发第三方登录 核心类 ServiceProvider(AbstractOauth2ServiceProvider):主要负责实现server提供商(例如QQ,微信等共有的东西),默认实现类是AbstractOauth2ServiceProvider...

chendom
今天
3
0
Java并发之AQS详解

一、概述   谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!   类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源...

群星纪元
昨天
3
0
Fabric-sdk-java最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程。 如果希望快速掌握F...

汇智网教程
昨天
3
0
react 子组件监听props 变化

componentWillReceiveProps //已经被废弃 getDerivedStateFromProps// 推荐使用//如果条件不存在必须要返回null static getDerivedStateFromProps(props, current_stat...

一箭落旄头
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部