Docker - 镜像构建教程2(使用Dockerfile构建镜像)

Docker 提供了两种构建镜像的方法:docker commit 命令与 Dockerfile 构建文件。日常使用中推荐通过后者(Dockerfile)来构建镜像,下面通过样例进行演示。

一、使用 Dockerfile 构建镜像样例

1,创建一个 Dockerfile 文件

(1)Dockerfile 其实是一个文本文件,记录了镜像构建的所有步骤。我们可以通过 vi 命令创建它。

1

vi Dockerfile


(2)Dockerfile 里的内容如下:

  • 第一行:执行 FROM,将 Apache Server 作为 base 镜像。
  • 第二行:执行 COPY,将 index.html 这个文件复制到镜像里的 /usr/local/apache2/htdocs/ 目录下。

1

2

FROM httpd

COPY index.html /usr/local/apache2/htdocs/


(3)根据前面定义的构建步骤,需要将一个外部文件复制到镜像中。所有我们在同级目录下创建一个 index.html 文件,内容如下:

1

欢迎访问 hangge.com

2,构建镜像

(1)运行 docker build 命令开始构建镜像:参数说明:

  • -t 表示将新镜像命名为 hangge_server
  • 末尾的 . 指明 build context 为当前目录
  • Docker 默认会从 build context 中查找 Dockerfile 文件,我们也可以通过 -f 参数指定 Dockerfile 的位置。

1

docker build -t hangge_server .


(2)上面执行后会显示出详细的构建过程。

Docker - 镜像构建教程2(使用Dockerfile构建镜像)_第1张图片

3,使用镜像

(1)下面我们使用 docker run 命令运行我们构建的自定义镜像:

1

docker run -it -d -p 80:80  hangge_server


(2)运行后我们使用浏览器访问,可以看到这个 index.html 确实已经包含在这个镜像中。

Docker - 镜像构建教程2(使用Dockerfile构建镜像)_第2张图片

二、设置镜像的 tag

当我们执行 docker build 命令制作镜像时,使用 -t 参数为镜像取个名字。实际上一个特定镜像的名字由两部分组成:repository 和 tag。其中 tag 常用于描述镜像的版本信息。

1,不手动设置 tag

(1)上面样例中我们没有特别指定 tag:

1

docker build -t hangge_server .


(2)那么就会默认使用 latest,即上面效果相当于:

1

docker build -t hangge_server:latest .

原文:Docker - 镜像构建教程2(使用Dockerfile构建镜像)

2,创建时指定 tag

(1)tag 常用于描述镜像的版本信息:

1

docker build -t hangge_server:2.4 .


(2)当然 tag 也可以是任意字符串:

1

docker build -t hangge_server:trusty .

3,给已有的镜像打 tag

(1)我们可以通过 docker tag 命令方便地给现有的镜像打 tag,比如下面将 latest 打上 3.1.0 的 tag。

1

docker tag hangge_server hangge_server:3.1.0

Docker - 镜像构建教程2(使用Dockerfile构建镜像)_第3张图片


(2)又比如下面将 latest 移到 4.1.0

1

docker tag hangge_server:4.1.0 hangge_server:latest

三、Dockerfile 常用指令

1,FROM

用于指定基础镜像。如果不以任何镜像为基础,那么写法为:FROM scratch。

2,MAINAINER

设置镜像的作者,可以是任意字符串。

3,COPY 

将文件从 build context 复制到镜像。COPY 支持如下两种形式:

  • COPY src dest
  • COPY ["src", "dest"]

注意:src 只能指定 build context 中的文件或目录。

4,ADD

与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar、zip、tgz、xz 等),文件会被自动解压到 dest。

5,ENV

设置环境变量,环境变量可被后面的指令使用。下面是一个设置和使用的样例:

1

2

ENV MY_VERSION 1.3

RUN apt-get install -y mypackage=$MY_VERSION

6,EXPOSE

指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。

1

EXPOSE 8081 8082

7,VOLUME

    用于指定持久化目录,实现挂载功能,授权访问从容器内到主机上的目录。用于 containers 之间共享数据,将本地文件夹或者其他容器中的文件夹挂在到这个容器中等。具体用法可以参考我之前写的一篇文章:

  • Docker - 容器存储详解2(volume container、data-packed volume container)

8,WORKDIR

为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。

1

WORKDIR /root

9,RUN

(1)RUN 指令将在当前镜像基础上执行指定命令(即在最顶部执行命令),并提交为新的镜像,也就是多少个 RUN 就构建了多少层镜像。

(2)RUN 指令通常用于安装应用和软件包。下面是使用 RUN 安装多个包的例子:

1

2

3

4

5

6

RUN apt-get update && apt-get install -y \ 

 bzr \

 cvs \

 git \

 mercurial \

 subversion

10,CMD

(1)CMD 是构建容器后调用,也就是在容器启动时才进行调用。

注意:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。

(2)CMD 指令允许用户指定容器的默认执行的命令,CMD 命令会在容器启动且 docker run 没有指定其他命令时运行。

  • 比如下面镜像构建以后,使用 docker run -it [image] 运行容器将会输出:Hello world

1

CMD echo "Hello world"


(3)如果 docker run 后面带上其它参数,那么 CMD 会被忽略掉。

  • 比如我们使用 docker run -it [image] /bin/bash 运行容器命令 bash 将被执行,而 Hello world 则不会输出。

11,ENTRYPOINT

(1)ENTRYPOINT 和 CMD 很像:

  • 只能写一条,如果写了多条,那么只有最后一条生效
  • 它们的运行时机相同,都是容器启动时才运行

(2)ENTRYPOINT 与 CMD 不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 dokcer run 时指定了其它命令。

(3)如果我们在 Dockerfile 中同时写了 ENTRYPOINT 和 CMD,并且 CMD 指令不是一个完整的可执行命令,那么 CMD 指定的内容将会作为 ENTRYPOINT 的参数。

1

2

3

FROM ubuntu

ENTRYPOINT ["top""-b"]

CMD ["-c"]


(4)如果我们在 Dockerfile 种同时写了 ENTRYPOINT 和 CMD,并且 CMD 是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效。

    比如下面 ls -al 将会执行,top -b 则不会执行

1

2

3

FROM ubuntu

ENTRYPOINT ["top""-b"]

CMD ls -al

你可能感兴趣的:(docker,容器,运维)