Docker 学习笔记(七)-- Docker DockerFile

Docker DockerFile

Docker Dockerfile | 菜鸟教程 (runoob.com)

1、什么是 Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

2、Dockerfile 介绍

构建步骤:

1、编写 DockerFile 文件

2、docker build 构建镜像

3、docker run 运行镜像

4、docker push 发布镜像(DockerHub,阿里云镜像仓库)

查看一下官方是怎么做的

在 dockerHub 上搜索 centos,选个 tag点进去 ,就可以看到 DockerFile 文件了:

sig-cloud-instance-images/Dockerfile at b2d195220e1c5b181427c3172829c23ab9cd27eb · CentOS/sig-cloud-instance-images · GitHub

Docker 学习笔记(七)-- Docker DockerFile_第1张图片

很多官方镜像都是基础包,很多功能没有,我们通常自己搭建自己的镜像!如:CentOS + JDK + Tomcat + MySQL + Redis

3、Dockerfile 构建过程

基础知识:

1、每条保留关键字(指令)都必须为大写字母

2、指令按照从上到下的顺序执行

3、# 表示注释

4、每条指令都会创建一个新的镜像层,并提交这个镜像层

Docker 学习笔记(七)-- Docker DockerFile_第2张图片

DockerFile 是面向开发者的,以后要发布项目,做镜像,就需要编写 DockerFile 文件,这个文件十分简单!

Docker 逐渐成为企业交付的标准,尽量学会吧!!卷啊,摆烂和躺平真香!!!

步骤: 开发,部署,运维!!

DockerFile:构建文件,定义了一切的步骤,源代码!

DockerImages:通过 DockerFile 构建生成的镜像,最终发布和运行的产品!

Docker容器 :容器就是镜像运行起来提供服务的!

说明:

从应用软件的角度来看,DockerFile,Docker镜像与Docker容器分别代表软件的三个不同阶段。

  • DockerFile 是软件的原材料 (源代码)

  • Docker 镜像 则是软件的交付品 (.apk 应用文件)

  • Docker 容器 则是软件的运行状态 (客户下载安装运行)

DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!
Docker 学习笔记(七)-- Docker DockerFile_第3张图片

4、Dockerfile 指令说明

指令 命令摘要
FROM 构建镜像基于哪个镜像
MAINTAINER 镜像维护者信息,如姓名或邮箱地址
RUN 构建镜像时运行的指令,每一次RUN都会构建一层
CMD 运行容器时执行的 shell 环境。如果有多个则以最后一个为准,也可以为 ENTRYPOINT 提供参数
ENTRYPOINT 运行容器时执行的 shell 命令。容器进入时执行的命令。可以追加命令。
COPY 拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能。以复制的形式
ADD 拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压。
ENV 设置容器环境变量。变量属性值,容器内部也会起作用
ARG 构建时指定的一些参数。变量属性值,但不在容器内部起作用
VOLUME 指定容器挂载点到宿主机自动生成的目录或其他容器。如果没有定义则使用默认
EXPOSE 声明容器的服务端口(仅仅是声明)。暴露端口
USER 为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户
WORKDIR 镜像的工作目录。为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录
HEALTHCHECH 健康检测指令
ONBUILD 当构建一个被继承的 DockerFile 时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD 被触发。触发指令
FROM 			# 基础镜像,一切从这里开始构建,当前新镜像是基于哪个镜像的 
MAINTAINER 		# 镜像作者的姓名+邮箱地址
RUN 			# 容器构建时需要运行的命令
EXPOSE 			# 当前容器对外保留出的端口。暴露端口配置!
WORKDIR			# 指定在创建容器后,终端默认登录的进来工作目录。
ENV 			# 用来在构建镜像过程中设置环境变量!构建时设置环境变量!Mysql密码,JVM参数等!
ADD 			# 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包。如添加 Tomcat 压缩包。
COPY 			# 类似ADD,拷贝文件和目录到镜像中!将我们的文件拷贝到镜像中!
VOLUME 			# 容器数据卷,用于数据保存和持久化工作。挂载的目录!
CMD 			# 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最后一个生效,可被替代!
ENTRYPOINT 		# 指定一个容器启动时要运行的命令!和CMD一样!可以追加命令!
ONBUILD 		# 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发。触发指令!

Docker 学习笔记(七)-- Docker DockerFile_第4张图片

Docker 学习笔记(七)-- Docker DockerFile_第5张图片

4.1、FROM

FROM:定制的镜像都是基于 FROM 的镜像。

# 基于基础镜像
FROM scratch
# 基于centos
FROM centos

4.2、LABEL (MAINTAINER)

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法如下:

# 格式:
LABEL = = = ...

# 比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="mianbao"

4.3、 RUN

RUN:用于执行后面跟着的命令行命令。

# shell 格式
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

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

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum -y install wget \
  && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
  && tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像

4.4、CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在 docker run 时运行
  • RUN 在 docker build 时运行

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

# 格式:
CMD  										# 这种格式实际上在运行的过程中会自动转换成第二种格式运行
CMD ["<可执行文件或命令>","","",...] 	# 推荐使用格式,执行过程比较明确。默认可执行文件是 .sh。
CMD ["","",...] 					 # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

4.5、ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

# 格式:
ENTRYPOINT ["","","",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

**示例:**假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx

ENTRYPOINT ["nginx", "-c"] 		# 定参
CMD ["/etc/nginx/nginx.conf"] 	# 变参 

1、不传参运行

$ docker run nginx:test

# 容器内会默认运行以下命令,启动主进程。
$ nginx -c /etc/nginx/nginx.conf

2、传参运行

$ docker run nginx:test -c /etc/nginx/new.conf

# 容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
$ nginx -c /etc/nginx/new.conf

4.6、COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

# 格式:
COPY [--chown=:] <源路径1>...  <目标路径>
COPY [--chown=:] ["<源路径1>",...  "<目标路径>"]
# [--chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

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

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

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

4.7、ADD

ADD 指令和 COPY 的使用格式类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

4.8、ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

# 格式:
ENV  
ENV = =...

示例: 设置 NODE_VERSION = 7.2.0 ,在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

4.9、ARG

构建参数,与 ENV 作用一致。不过作用域不同。ARG 设置的环境变量仅对 Dockerfile 内有效,即只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。

# 格式:
ARG <参数名>[=<默认值>]

4.10、VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。作用:避免重要的数据,因容器重启而丢失,这是非常致命的;避免容器不断变大。

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

# 格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

4.11、EXPOSE

仅仅只是声明端口。作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
# 格式:
EXPOSE <端口1> [<端口2>...]

4.12、WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

# 格式:
WORKDIR <工作目录路径>

4.13、USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

# 格式:
USER <用户名>[:<用户组>]

4.14、HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

# 格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

4.15、ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

# 格式:
ONBUILD <其它指令>

5、CMD 和 ENTRYPOINT 的区别

CMD 指定一个容器启动时要运行的命令,但只有最后一个生效,可被替代!
ENTRYPOINT 指定一个容器启动时要运行的命令,可以追加命令!

CMD 命令测试

# 创建 dockerfile
[root@localhost dockerfile]$ vim dockerfile-cmd-test
[root@localhost dockerfile]$ cat dockerfile-cmd-test 
FROM centos:centos7
CMD ["ls", "-a"]
# 构建镜像
[root@localhost dockerfile]$ docker build -f dockerfile-cmd-test -t cmd-test:1.0 .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos:centos7
---> eeb6ee3f44bd
Step 2/2 : CMD ["ls", "-a"]
---> Running in 1a5ca4268543
Removing intermediate container 1a5ca4268543
---> 4f1c5614fc97
Successfully built 4f1c5614fc97
Successfully tagged cmd-test:1.0
# 运行测试, 直接运行 ls -a 这个命令
[root@localhost dockerfile]$ docker run 4f1c5614fc97
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
............
usr
var
# 想追加一个命令 -l ,理想是实现 ls -al 这个命令
[root@localhost dockerfile]$ docker run 4f1c5614fc97 -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
# -l 替换了 CMD ["ls","-a"] 命令,-l 不是命令,所以报错了

# 替换需要写完整的命令
[root@localhost dockerfile]$ docker run 4f1c5614fc97 ls -al
total 12
drwxr-xr-x.   1 root root     6 Jul  5 15:09 .
drwxr-xr-x.   1 root root     6 Jul  5 15:09 ..
-rwxr-xr-x.   1 root root     0 Jul  5 15:09 .dockerenv
-rw-r--r--.   1 root root 12114 Nov 13  2020 anaconda-post.log
lrwxrwxrwx.   1 root root     7 Nov 13  2020 bin -> usr/bin
drwxr-xr-x.   5 root root   340 Jul  5 15:09 dev
drwxr-xr-x.   1 root root    66 Jul  5 15:09 etc
drwxr-xr-x.   2 root root     6 Apr 11  2018 home
................................................
drwxr-xr-x.  13 root root   155 Nov 13  2020 usr
drwxr-xr-x.  18 root root   238 Nov 13  2020 var

ENTRYPOINT 命令测试

# 创建 dockerfile
[root@localhost dockerfile]$ vim dockerfile-entrypoint-test
[root@localhost dockerfile]$ cat dockerfile-entrypoint-test 
FROM centos:centos7
ENTRYPOINT ["ls", "-a"]
# 构建镜像
[root@localhost dockerfile]$ docker build -f dockerfile-entrypoint-test -t entrypoint-test:1.0 .
Sending build context to Docker daemon   5.12kB
Step 1/2 : FROM centos:centos7
---> eeb6ee3f44bd
Step 2/2 : ENTRYPOINT ["ls", "-a"]
---> Using cache
---> 7806e33422a8
Successfully built 7806e33422a8
Successfully tagged entrypoint-test:1.0
# 运行了 ls -a 命令
[root@localhost dockerfile]$ docker run 7806e33422a8
...... 
# 运行了 ls -al 命令。
[root@localhost dockerfile]# docker run 7806e33422a8 -l
......
# 这里就是一种追加,我们可以明显的知道 CMD 和ENTRYPOINT 的区别了

总结

DockerFile 中很多命令都十分相似,需要详细了解它们的区别,最好的学习就是对比然后测试效果!

你可能感兴趣的:(Docker,docker,dockerfile)