使用dockerfile定制镜像及dockerfile指令解析

查看使用 Dockerfile 定制镜像

1.从零开始来创建一个新的镜像、

什么是 Dockerfile 文件?

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

主要作用:

1、找一个镜像:   centos

2、创建一个容器: docker run  centos

3、进入容器:     docker exec -it 容器 命令

4、操作:         各种应用配置

                ....

5、构造新镜像:    docker commit

Dockerfile 使用准则

1、大: 首字母必须大写D

   2、空: 尽量将Dockerfile放在空目录中。

   3、单: 每个容器尽量只有一个功能。

   4、少: 执行的命令越少越好。

Dockerfile 基础四指令:

   基础镜像信息          从哪来?

   维护者信息           我是谁?

   镜像操作指令          怎么干?

   容器启动时执行指令     嗨!!!

Dockerfile使用命令:

构建镜像命令格式:

  docker build -t [镜像名]:[版本号] [Dockerfile所在目录]

构建样例:

  docker build -t nginx:v0.2 /opt/dockerfile/nginx/

参数详解:

  -t     指定构建后的镜像信息,

  /opt/dockerfile/nginx/     则代表Dockerfile存放位置,如果是当前目录,则用 .(点)表示

1.1编写Dockerfile文件、

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile
$ cat Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

说明:

每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的

第一条FROM,指定使用哪个镜像源,基础镜像

FROM scratch (表示空白的镜像,是一个虚拟的概念,实际不存在)

RUN 指令是用来执行命令行命令的(两种格式)

shell 格式:RUN <命令>
exec 格式:RUN ["可执行文件", "参数1", "参数2"]
如:# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

最好不要写多个指令,每一个指令代表一层,则会创建了很多层镜像,如果需要写多个指令可以用连接符 && 连接起来,在同一层上面创建即可。

1.2 构建镜像

Dockerfile 文件所在目录执行:

$ docker build -t nginx:2.0 .
发现其执行了两步,查看镜像列表已经存在创建的镜像了
-t:指定要创建的镜像名
.:Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

运行镜像:

[root@rbtnode1 mynginx]# docker run -d -p 82:80 nginx:2.0

 

 

查看 nginx,运行的页面如构建的shell脚本更改一致

 

 

 

1.3上下文路径

最后一个 . 是上下文路径,怎么理解呢?

是docker在构建镜像,不一定使用RUN指令完成的,有时候想要使用本机的文件(如复制COPY),docker build命令得知这个路径后,会将路径下的所有东西打包。docker是C/S模式,我们使用C,引擎是S。而build是是引擎完成的,则docker不能使用我们本机C的文件,所以需要制定目录下的文件打包给S使用。如果不说吗,则为Dockerfile所在的位置。

如果在Dockerfile中写:

COPY ./package.json /app/
这并不表示要复制docker build命令所在的目录下的package.json,也不是复制Dockerfile所在目录下的package.json,而是复制上下文目录下的package.json。

**COPY 这类指令中的源文件的路径都是相对路径。**

docker build -t nginx:2.0 . 中的这个 .,实际上是在指定上下文的目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。(输出的第一行就是其过程)

 

 

为了避免犯错:

  1. 应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。

  1. 如果该目录下没有所需文件,那么应该把所需文件复制一份过来,去copy正常的Linux的路径如 ../../等是不会工作的。

  1. 不希望传有些东西给docker引擎,用.dockerignore文件(似.gitignore)剔除

为什么会误认为是指定Dockerfile路径呢?

  1. 因默认情况且不指定Dockerfile的话,会将上下文目录下的名为Dockerfile的文件名为Dockerfile

  2. 不必须命名为Dockerfile,可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile

  3. 当然,一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中

2.其它 docker build 的用法

2.1 直接用 Git repo 进行构建

  1. docker build支持url构建

    $ docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
    指定默认的 master 分支,构建目录为 /11.1/,然后 Docker 就会自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建。

     

2.2用给定的 tar 压缩包构建

$ docker build http://server/context.tar.gz
Docker 引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。

2.3从标准输入中读取 Dockerfile 进行构建

docker build - < Dockerfile
cat Dockerfile | docker build -

如果标准输入传入的是文本文件,则将其视为 Dockerfile,并开始构建。直接读取Dockerfile中的内容,没有上下文

2.4从标准输入中读取上下文压缩包进行构建

$ docker build - < context.tar.gz

直接将其展开,将里面视为上下文,并开始构建

 

3.Dockerfile 指令详解

3.1 COPY和ADD

COPY复制指令,将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。ADD是更高级的复制文件,两种格式两种(命令行,函数调动型):

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

如:COPY package.json /usr/src/app/

加入组的方式:COPY --chown=1 files* /mydir/

[--chown=<user>:<group>]**:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则

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

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定。

使用COPY指令,各类元数据都会保留,git时很方便。

ADD源路径:

  1. 是一个url,docker引擎会去下载这个路径,自动设置权限为600,也可以加RUN调整权限。下载到的若是个压缩包,若解压则加一层RUN指令,也可以wget或curl下载,处理。

  2. <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径>

    1. 使用注意:

      1. 尽量多用COPY,只是复制没必要那么复杂,需要自动解压再用ADD

      2. ADD会让镜像构建失效,从而镜像缓慢。

      3. --chown=<user>:<group>
        ADD --chown=55:mygroup files* /mydir/  
        修改用户及所属组

3.2 CMD和ENTRYPOINT

  1. 概念

    CMD:指定默认的容器主进程的启动命令,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。多个CMD时仅最后一个生效。

    ENTRYPOINT:类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序,存在多个 ENTRYPOINT 指令,仅最后一个生效。需要通过 docker run 的参数 --entrypoint 来指定。

  2. 格式

CMD 指令的格式和 RUN 相似,CMD与ENTRYPOINT类似。也是两种格式(推荐exec):

  • shell 格式:CMD <命令>

  • exec 格式:CMD ["可执行文件", "参数1", "参数2"...]

  • 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

  1. 使用规则

    1. CMD
      1. 使用exec格式,其会被解析成接送数组,一定需要“”双引号。

      2. 使用shell格式,实际命令会被包装是 sh -c 执行。这样就需要环境变量,环境变量会被shell进行解析。容器中执行的命令需要在前台执行,类似于systemd后台命令无法执行,被迫容器退出,因为容器执行会解读为sh执行,这样sh就是这个命令的主进程。那么后台的命令结束则sh结束了就退出了,启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程结自然容器也退出了。除非CMD要求前台执行。

    2. ENTRYPOINT
      1. 指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令。<ENTRYPOINT> "<CMD>"

      2. 可以让镜像变成像命令一样使用

      3. 启动容器就是启动主进程,但有些时候,启动主进程前,需要一些准备工作。

         

3.3环境指令详情

1. 环境设置指令

  ENV

  格式:

      ENV <key> <value>

      ENV <key>=<value> ...

  解释:

      设置环境变量,可以在RUN之前使用,然后RUN命令时调用,容器启动时这些环境变量都会被指定

 

  WORKDIR

   格式:

    WORKDIR /path/to/workdir                 (shell 模式)

  解释:

      切换目录,为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。 相当于cd

    可以多次切换(相当于cd命令),

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

   举例:

    WORKDIR /a

    WORKDIR b

    WORKDIR c

    RUN pwd

    则最终路径为 /a/b/c。

 

ENV实践

修改Dockerfile文件内容:

  # 在上一个Dockerfile文件内容基础上,在RUN下面增加一个ENV

ENV NIHAO=helloworld

 

WORKDIR实践

  修改Dockerfile文件内容:

    # 在上一个Dockerfile文件内容基础上,在RUN下面增加一个WORKDIR

WORKDIR /nihao/itcast/

RUN ["touch","itcast.txt"]

 

Dockerfile构建过程

Dockerfile**构建过程:**

  1. 从基础镜像1运行一个容器A

    遇到一条Dockerfile指令,都对容器A做一次修改操作

    执行完毕一条命令,提交生成一个新镜像2

    再基于新的镜像2运行一个容器B

    遇到一条Dockerfile指令,都对容器B做一次修改操作

    执行完毕一条命令,提交生成一个新镜像3

    ...

  1. 构建过程镜像介绍**

    构建过程中,创建了很多镜像,这些中间镜像,我们可以直接使用来启动容器,通过查看容器效果,从侧面能看到我们每次构建的效果。

    提供了镜像调试的能力

    我们可以通过docker history <镜像名> 来查看整个构建过程所产生的镜像

    执行的步骤越多越好呢?还是越少越好?

  1. 构建缓存**

    我们第一次构建很慢,之后的构建都会很快,因为他们用到了构建的缓存。

不适用构建缓存方法常见两种:

全部不同缓存:

docker build --no-cache -t [镜像名]:镜像版本

只要构建的缓存时间不变,那么就用缓存,如果时间一旦改变,就不用缓存了

样例:

# 构建一个基于ubuntu-base的docker定制镜像

# 基础镜像

FROM ubuntu-base

\ # 镜像作者

MAINTAINER 邮箱

\ # 创建构建刷新时间

ENV REFRESH_DATE 2019-12-06

# 执行命令

...

 

构建历史:

1. 查看构建过程查看

docker history

清理构建缓存:

docker system prune

docker system prune --volumes

posted on 2019-11-30 13:34  不浮泛  阅读(1149)  评论(0编辑  收藏  举报

导航