使用 Dockerfile 定制镜像

Posted by 暮夏有五 on 2020-07-09
Estimated Reading Time 4 Minutes
Words 987 In Total
Viewed Times

这里以简单定制 Nginx 镜像为例

创建 Dockerfile 文件


创建 Dockerfile 文件

1
2
3
4
5
$ mkdir /usr/local/docker
$ cd /usr/local/docker
$ mkdir nginx
$ cd nginx
$ vi Dockerfile

Dockerfile 文件的内容如下

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

这个 Dockerfile 很简单,一共就两行。涉及到了两条指令,FROMRUN

FROM 指令

  • 通常情况下,定制镜像都需要指定一个镜像为基础,在其上进行定制,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令
  • 除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像,使用这种特殊镜像,意味着不以任何操作系统为基础,会让镜像体积变得更加小巧,使用 Go 语言 开发的应用很多会使用这种方式来制作镜像
    1
    2
    FROM scratch
    ...

RUN 指令

  • RUN 指令是用来执行命令的,是 Dockerfile 定制镜像中最常用的指令之一

  • 如果遇到多条 RUN 指令一起执行的情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    FROM debian:jessie

    RUN apt-get update
    RUN apt-get install -y gcc libc6-dev make
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
    RUN mkdir -p /usr/src/redis
    RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
    RUN make -C /usr/src/redis
    RUN make -C /usr/src/redis install

    注:在 Dockerfile 中执行每一个指令都会建立一层文件,但是 Union FS 是有最大层数限制的。

    上面的 Dockerfile 正确写法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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

    这样的话,实现了将 7 层文件简化为 1 层文件。另外,每一层构建完之后要删掉无关文件,否则会造成镜像臃肿。

构建镜像


在 Dockerfile 文件所在目录下使用 build 命令

1
$ docker build -t nginx:v1 .

构建完成后,执行以下命令

1
$ docker images

会发现多了一个镜像名为 nginx,标签名为 v1 的镜像

其他 Dockerfile 指令


COPY 指令

一般用于从主机复制文件到容器

1
COPY <源路径> <目标路径>

比如:

1
COPY package.json /usr/src/app/

<源路径> 可以是多个,甚至可以是通配符。比如:

1
2
COPY hom* /mydir/
COPY hom?.txt /mydir/

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

还值得注意的一点是:使用 COPY 指令,文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。

ADD 指令

ADD 指令和 COPY 本质上基本一样,但在 COPY 的基础上添加了一些功能:

比如原路径可以为URL,下载后的文件权限默认设置为 700,也就是当前用户有可读可写可执行权限,而用户组和其他用户没有任何权限。如果下载的文件是一个压缩包,会自动解压缩

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

更多指令详解参考官方文档

更多干货请移步:https://antoniopeng.com


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !