使用 Dockerfile 定制镜像

彭楷淳发布于 2020-07-09
预计阅读时间 4 分钟
总计 987
浏览

这里以简单定制 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


如果你喜欢这个博客或发现它对你有用,欢迎你点击右下角 “OPEN CHAT” 进行评论。也欢迎你分享这个博客,让更多的人参与进来。如果在博客中使用的图片侵犯了您的版权,请联系博主删除它们。谢谢你!