Dockerfile详解

Dockerfile

Dockerfile简介

1.是什么

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

2.构建三步骤

  • 编写dockerfile 文件
  • docker build
  • docker run

3.文件什么样?

Centos为例子

FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

4.dockerfile构建过程解析

  • 1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • 2:指令按照从上到下,顺序执行
  • 3:#表示注释
  • 4:每条指令都会创建一个新的镜像层,并对镜像进行提交

5.docker执行dockerfile的大致流程

  • docker 从基础镜像运行一个容器
  • 执行一条指令并对容器作出修改
  • 执行类似docker commit 的操作提交一个新的镜像层
  • docker 再基 于刚提交的镜像运行一个新容器
  • 执行dockerfile 中的下一条指令直到所有指令都执行完成

6.小总结

  1. 从应用软件的角度来看,Dockerfile、 Docker 镜像与Docker 容器分别代表
  2. 软件的三个不同阶段,
  3. Dockerfile是软件的原材料
  4. Docker 镜像是软件的交付品
  5. Docker 容器则可以认为是软件的运行态。
  6. Dockerfile面向开发,Docker 镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。

Dockerfile,需要定义一个 Dockerfile, Dockerfile 定义了进程需要的一切东西。Dockerfile 涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;

  1. Docker 镜像,在用 Dockerfile定义一个文件之后,docker build 时会产生一个Docker 镜像,当运行 Docker 镜像时,会真正开始提供服务;
  2. Docker 容器,容器是直接提供服务的。

如何用 Dockerfile 构建镜像

  • 前面讲到镜像的构建时,讲述的是用 commit 的方式构建镜像,而 Dockerfile 是 另一种构建镜像的方式
  • Dockerfile 构建镜像是以基础镜像为基础的,Dockerfile 是一个文本文件,内容是 用户编写的一些 docker 指令,每一条指令构建一层,因此每一条指令的内容,就是 描述该层应当如何构建。
  • Dockerfile 的基本指令有十三个,分别是:FROM、MAINTAINER、RUN、CMD、 EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、 ONBUILD 从前面的内容可以看出,要构建一个容器,需要做很多的工作,设置很多的配 置,如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个 脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、 体积的问题就都会解决。
  • 这个脚本就是 Dockerfile。 因此学会用 Dockerfile 来构建镜像,是非常有必要的。学习 Dockerfile 之前,我们先 来学习一些 Dockerfile 常用的指令。

1 Dockerfile 常用指令

Dockerfile详解_第1张图片

1.1、FROM :指定基础镜像

所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之 前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指定的。而FROM 就是指定基础镜 像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必 须是第一条指令。 如:指定 ubuntu 的 14 版本作为基础镜像

FROM ubuntu:14

1.2、RUN:执行命令

RUN 指令在新镜像内部执行的命令,如:执行某些动作、安装系统软件、配置系统 信息之类, 格式如下两种:

1)shell 格式:RUN< command > ,就像直接在命令行中输入的命令一样。 
如在 nginx 里的默认主页中写”hello“:
RUN echo 'hello ' >/etc/nginx/html/index.html 
2)exec 格式:RUN ["可执行文件", "参数 1", "参数 2"] 
如在新镜像中用 yum 方式安装 nginx:
RUN ["yum","install","nginx"]

注:多行命令不要写多个 RUN,原因是 Dockerfile 中每一个指令都会建立一层.多少 个 RUN 就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的 时间,还容易出错,RUN 书写时的换行符是\

1.3、COPY:复制文件

COPY 命令用于将宿主机器上的的文件复制到镜像内,如果目的位置不存在,Docker 会自动创建。但宿主机器用要复制的目录必须是和 Dockerfile 文件统计目录下。 格式:

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

如把宿主机中的 package.json 文件复制到容器中/usr/src/app/目录下:

COPY package.json /usr/src/app/ 

1.4、CMD:容器启动命令

CMD 命令用于容器启动时需要执行的命令,CMD 在 Dockerfile 中只能出现一次,如 果出现多个,那么只有最后一个会有效。 其作用是在启动容器的时候提供一个默认 的命令项。如果用户执行 docker run 的时候提供了命令项,就会覆盖掉这个命令, 没提供就会使用构建时的命令。
格式: `shell 格式:CMD <命令> exec 格式:CMD [“可执行文件”, “参数 1”, “参数 2”…]

如容器启动时进入 bash:
CMD /bin/bash

也可以用 exec 写法:
CMD ["/bin/bash"]

1.5、MAINTAINER:指定作者

用来指定 dockerfile 的作者名称和邮箱,主要作用是为了标识软件的所有者是谁。

语法: MAINTAINER   如:
MAINTAINER autor_jiabuli [email protected]

1.6、EXPOSE:暴露端口

EXPOSE 命名适用于设置容器对外映射的容器端口号,如 tomcat 容器内使用的端口8081,则用 EXPOSE 命令可以告诉外界该容器的 8081 端口对外,在构建镜像时 用 docker run -p 可以设置暴露的端口对宿主机器端口的映射。

语法: EXPOSE <端口 1> [<端口 2>...]
如: EXPOSE 8081

EXPOSE 8081 其实等价于 docker run -p 8081 当需要把 8081 端口映射到宿主机中 的某个端口(如 8888)以便外界访问时,则可以用 docker run -p 8888:8081

1.7、WORKDIR:配置工作目录

WORKDIR 命令是为 RUN、CMD、ENTRYPOINT 指令配置工作目录。其效果类似于 Linux 命名中的 cd 命令,用于目录的切换,但是和 cd 不一样的是:如果切换到的目 录不存在,WORKDIR 会为此创建目录。

语法: WORKDIR path

如需要在 nginx 目录下创建一个 hello.txt 的文件:
进入/usr/local/nginx 目录下
WORKDIR /usr/local/nginx
进入/usr/local/nginx 中的 html 目录下
WORKDIR html
在 html 目录下创建了一个 hello.txt 文件
RUN echo 'hello' > hello.txt

1.8、ENTRYPOINT:容器启动执行命名

ENTRYPOINT 的作用和用法和 CMD 一模一样,但是 ENTRYPOINT 有和 CMD 有 2 处 不一样:

  1. CMD 的命令会被 docker run 的命令覆盖而 ENTRYPOINT 不会
  2. CMD 和 ENTRYPOINT 都存在时,CMD 的指令变成了 ENTRYPOINT 的参数, 并且此 CMD 提供的参数会被 docker run 后面的命令覆盖

1.9、VOLUME 数据卷

VOLUME 用来创建一个可以从本地主机或其他容器挂载的挂载点。例如我们知道 tomcat 的 webapps 目录是放 web 应用程序代码的地方,此时我们要把 webapps 目 录挂载为匿名卷,这样任何写入 webapps 中的心都不会被记录到容器的存储层,让 容器存储层无状态化。

格式: VOLUME ["path"]
如创建 tomcat 的 webapps 目录的一个挂载点
VOLUME /usr/local/tomcat/webapps

这样,在运行容器时,也可以用过 docker run -v 来把匿名挂载点挂载都宿主机器上 的某个目录,
如 docker run -d -v /home/tomcat_webapps:/usr/local/tomcat/webapps

1.10、USER 用户

命令用于指定当前望下执行的用户,需要注意的是这个用户必须是已经存在,否则无 法指定。它的用法和 WORKDIR 有点像,切换用户。

格式:
USER daemon

1.11、ADD 解压

作用和使用方法和 COPY一模一样,在此不重复讲述。

格式:
ADD wordpress.tar.gz /opt/

1.12、ONBUILD 主动

ONBUILD 用于配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的 操作指令。 意思就是:这个镜像创建后,如果其它镜像以这个镜像为基础,会先执 行这个镜像的 ONBUILD 命令

格式: 
ONBUILD [INSTRUCTION]

1.13、ENV:设置环境变量

ENV 命名用于设置容器的环境变量,这些变量以”key=value”的形式存在,在容器内 被脚本或者程序调用,容器运行的时候这个变量也会保留。

格式: 
1) 设置一个: ENV 
2) 设置多个: ENV = =... 
如设置一个环境变量 JAVA_HOME,接下来的命名就可以使用这个变量: 
ENV JAVA_HOME /opt/jdk 
ENV PATH $PATH:$JAVA_HOME/bin 
    
在使用 ENV 设置环境变量时,有几点需要注意: 
1)具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥 有当前这个基础镜像所有的环境变量  
2)ENV 定义的环境变量,可以在 dockerfile 被后面的所有指令(CMD 除外) 中使用,但不能被 docker run 的命令参数引用 
如: 
ENV tomcat_home_name tomcat_7 
RUN mkdir $tomcat_home_name 

3)除了 ENV 之外,docker run -e 也可以设置环境变量传入容器内。 
如: 
ocker run -d tomcat -e "tomcat_home_name=tomcat_7"
这样我们进入容器内部用 ENV 可以看到 tomcat_home_name 这个环境变量。 

Dockerfile 的编写

我们先看一个例子

编写一个dockerfile,在 centos 上安装 nginx

#指定基础镜像
FROM centos 
#标明著作人的名称和邮箱 
MAINTAINER jiabuli [email protected] 
#测试一下网络环境 
RUN ping -c 1 www.baidu.com 
#安装 nginx 必要的一些软件 
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib 
#把 nginx 安装包复制到/usr/src/目录下 
ADD nginx-1.15.8.tar.gz /usr/src/ 
#切换到/usr/src/nginx-1.15.8 编译并且安装 nginx 
RUN cd /usr/src/nginx-1.15.8 \     
	&& mkdir /usr/local/nginx \     
    && ./configure --prefix=/usr/local/nginx 
    && make && make install \     
    && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ \     
    && nginx 
#删除安装 nginx 安装目录 
RUN rm -rf /usr/src/nginx-nginx-1.15.8 
#对外暴露 80 端口 
EXPOSE 80 
#启动 nginx 
CMD ["nginx", "-g", "daemon off;"] 

上面的注释已经讲的非常清楚,其实不难发现,上面的例子就是类似于在 centos 系 统上安装一个 nginx 的的一个过程,因此编写 Dockerfile 构建镜像就和在 Linux 上安 装软件的流程几乎是一模一样的。所以我们在编写 Dockerfile 来构建镜像时,可以先 思考在 Linux 上安装该软件的流程,再用 Dockerfile 提供的指令转化到 Dockerfile 中 即可。

用 Dockerfile 构建镜像

  • 用 Dockerfile 的核心在于编写 Dockerfile,但是编写完之后我们需要知道怎么使用 Dockerfile 来构建镜像,下面以构建 nginx 镜像为例来简要说明构建流程

上传安装包

  • 首先我们需要把要构建的软件安装包上传到服务器中,我们可以在服务器目录上创建 一个专门的文件夹,如:/var/nginx_build,然后把从 nginx 官网下载的 nginx1.15.8.tar.gz 安装包上传到这个目录里。

编写 Dockerfile

  • 如何编写 nginx 的 Dockerfile 上面已经详细介绍,现在我们只需把编写好的 Dockerfile 上传到/var/nginx_build 目录下,当然你也可以在服务器上直接编写 Dockerfile,但是要记得一定保证 Dockerfile 文件和安装包在一个目录下。

运行构建命令构建

docker build 命令用于使用 Dockerfile 创建镜像。 格式:

docker build [OPTIONS] PATH | URL |

  • OPTIONS 有很多指令,下面列举几个常用的:
  • -build-arg=[] : 设置镜像创建时的变量;
  • -f : 指定要使用的 Dockerfile 路径;
  • -force-rm : 设置镜像过程中删除中间容器;
  • -rm : 设置镜像成功后删除中间容器;
  • -tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;

因此我们构建 nginx 可以用以下命令
docker build -t nginx:v1.0 .

当 Dockerfile 和当前执行命令的目录不在同一个时,我们也可以指定 Dockerfile,如 docker build -f /var/nginx_build/Dockerfile . 执行命名之后,会看到控制台逐层输出构建内容,直到输出两个 Successfully 即为构 建成功。

中间容器;

  • -tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;

因此我们构建 nginx 可以用以下命令
docker build -t nginx:v1.0 .

当 Dockerfile 和当前执行命令的目录不在同一个时,我们也可以指定 Dockerfile,如 docker build -f /var/nginx_build/Dockerfile . 执行命名之后,会看到控制台逐层输出构建内容,直到输出两个 Successfully 即为构 建成功。

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