使用 Dockerfile 定制镜像


Dockerfile 简介

通过上篇教程docker commit 的学习,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。

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

如果我们通过 Dockerfile 来构建上篇教程 docker commit 完成的事情,可以这么编写指令:

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

这里面涉及到 Dockerfile 的两条最基本指令,FROMRUN

  • FROM 用于指定基础镜像,表示定制镜像基于此基础镜像构建,常见的基础镜像有 nginxphpmysqlgoubuntualpine 等,FROMDockerfile 的必备指令,并且必须是第一条指令;
  • RUN 用来执行命令行命令,由于命令行的强大能力,因此它是定制镜像时最常用的指令,RUN 有两种格式:shell 格式(RUN <shell命令>)和 exec 格式(RUN ["可执行文件", "参数1", "参数2",有点像函数调用)。

对于复杂的构建指令,可以像下面这样编写:

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
    && apt-get update \
    && 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

在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每 一层该如何构建,而且要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉,如果每条 RUN 指令都只执行一个 shell 脚本,会造成很多不必要的中间内容被装进镜像,导致镜像层级很多,体积臃肿,构建缓慢,这是初学者常犯的错误。

构建镜像

通过 Dockerfile 构建镜像需要在 Dockerfile 文件所在目录执行 docker build 命令,Dockerfile 中可以配置多个镜像,我们可以在构建时通过指定镜像名来构建指定镜像:

使用 docker build 构建镜像

注:-t 表示镜像名包含标签,如果没有标签,可以省略,最后面的 . 号表示镜像构建的上下文目录(Dockerfile 中的相对路径都以此目录作为前缀),默认是当前目录。

我们可以通过命令输出清晰看到镜像构建过程,构建完成后,可以通过 docker run 来启动这个镜像:

docker run --name web3 -d -p 82:80 nginx:v3

此外,docker build 还有其他一些非常规的用法:

  • 直接用 Git repo 进行构建:docker build https://github.com/twang2218/gitlab-ce-zh.git#:8.14
  • 用给定的 tar 压缩包构建:docker build http://server/context.tar.gz
  • 从标准输入中读取 Dockerfile 进行构建:docker build - < Dockerfile 或者 cat Dockerfile | docker build -
  • 从标准输入中读取上下文压缩包进行构建:docker build - < context.tar.gz

点赞 取消点赞 收藏 取消收藏

<< 上一篇: 利用 docker commit 理解镜像分层构建

>> 下一篇: Dockerfile 常用指令详解