第二口docker的感觉 —— Dockerfile

简介:

前言

首先我们来思考这样一个问题:如果将改变了一些配置的Container在生成一个镜像?

正文

就前言的问题,我做一下解答:
通过docker commit命令,这个命令的目的是将我们的最新修改作为镜像的一层进行构建,命令详情参考:

https://docs.docker.com/engine/reference/commandline/commit/

❌但是这种方式方式我们并不提倡,因为这种构建方式相当于一个黑盒的构建,别人也不知道你具体做了那些操作,这个时候就需要引出我们的"构建好助手"——DockerFile

dockerfile是把你所有想要需要的地方都表现在了纸面上,这样我们可以明确知道所有的修改内容。

dockerfile的具体写法我们在后面进行详细的讨论。 但是在这里我们要明确一个问题,Dockerfile其实并不是向镜像里直接写入的,因为镜像是只读的。docker在这个时候创建了一个临时的容器,然后写入内容之后,再把临时容器删除。

DockerFile使用说明

我们创建自己需要的镜像的时候,可以通过commit和dockerfile的形式进行构建,但是前面也说了,官方推荐的还是dockerfile的形式。我们其实很容易的把它理解为一个构建脚本,docker为我们提供了很多可以使用的命令,下面我会一一说明。

基本指令说明
  1. ARG指令**
    定义创建镜像过程中使用的变量,相当于我们为docker build - -build-arg赋值。镜像编译结束后,这个变量将不会被保存

    ARG version=1.0
  2. FROM指令
    指定我们要在哪个image之上再进行构建,尽量使用官方image进行base image,为了安全。并且一个Dockerfile,必须要以From指令作为开头(ARG是唯一一个可以先于From命令的)

    FROM debian:latest
  3. LABLE指令
    像是代码里的注释一样,一些概括的维护者信息。

    LABLE author=harry
  4. ENV指令
    定义变量,可以在dockerfile下方进行使用,例如我们定义了 ENV USER harry,那么下面可以这样使用 "${USER}"

    ENV FILE_LOCATION /usr/local/file
  5. USER指令
    指定运行容器时的用户是谁
  6. WORKDIR指令
    进入到我们指定的目录中,如果没有这个目录会自动进行创建,用WORKDIR,代替 RUN cd。尽量使用绝对目录,不要使用相对目录。

    WORKDIR /usr/local
    WORKDIR tomcat/config
    # 可以连续指定路径,如果像上述一样,指定的路径为/usr/local/tomcat/configs
  7. RUN指令
    每执行一次RUN就是就会产生镜像的一层,使用 "&&" 将多个命令串联起来,如果需要换行在最后需要使用" " 反斜杠。环境的运行与搭建,大多数情况下需要这个命令

    RUN yum update \
            && yum install -y nginx
    #上述操作先更新yum,然后下载nginx
  8. CMD指令
    设置启动后默认执行的命令和参数。如果docker run 进行了指定了命令,例如 docker run -it … /bin/bash。则不会运行CMD中的命令,而且CMD定义多个,后面会覆盖之前的。

    启动tomcat命令
    CMD ['catalina.sh', 'run']
  9. ENTRYPOINT指令
    设置容器启动时默认执行的命令和参数,该命令会在启动容器后作为根命令执行,通过名称可以看出来是入口。让容器以应用程序或者服务去执行。并且ENTRYPOINT一定会执行

    将一个shell脚本作为docker启动的入口。
    ENTRYPOINT ['/entry.sh']
  10. COPY指令
    把本地文件拷贝到docker里去,COPY指令优于ADD指令,如果需要添加远程文件可以使用 curl或者wget

    COPY . /temp
  11. ADD指令
    是把本地的文件复制到docker里去,不过不光如此,还会对压缩文件自动进行解压缩

    ADD . /temp
  12. VOLUME指令
    启动容器时,可以在本地或者是其他容器创建数据卷挂载点,用于存放数据库和持久化数据

    #指定挂载点为 /temp/mount
    VOLUME /temp/mount
  13. EXPOSE指令
    声明镜像内部服务监听的端口,一次可以暴露多个端口

    #暴露22端口,和8888端口
    EXPOSE 22 8888
  14. ONBUILD指令
    指定自己的子镜像都会执行哪些命令

    #把当前目录下的所有东西拷贝到/app/src目录下
    ONBUILD COPY . /app/src

DockerFile的写法的关键在于:环境 + 工程代码 + 运行
DockerFile的最佳实践,请看官网:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

ARG和ENV的区别

两个看起来都是生命变量用的,他们之间的区别在于ARG时创建镜像过程中使用的变量,在启动后的容器中不能使用。而ENV在容器中可以使用

RUN,CMD以及ENTRYPOINT的相同点以及区别

这里要着重说一下RUN 和 CMD和ENTRYPOINT,他们都可以使用exec格式和shell格式

exec格式举例:

CMD ['/bin/echo', 'hello world']

shell格式举例:

CMD echo 'hello world'

但是要注意:如果使用exec格式,打印一个环境变量

CMD['/bin/echo', 'hello world $name'],打印的会是 hello world name的。

这个时候可以考虑使用shell格式,或者说把exec格式进行改造一下,改成如下格式:

CMD['/bin/bash','-c','echo hello world $name ']

另外值得注意的是,RUN命令用于构建镜像,CMD和ENTRYPOINT用于指定容器启动时的一些默认指令和参数。

CMD与ENTRYPOINT的共同点

两者在dockerfile中各自都只能声明一次,声明多次,不会报错,但是只有最后一条命令会生效。

CMD与ENTRYPOINT的区别

二者既然都是作为容器启动时的命令,那么他们的区别在哪里呢?

通过我去查阅官网,官网的意思是说ENTRYPOINT是docker容器的主命令,而默认的一些参数会在CMD中进行指定。

请看下方代码:

ENTRYPOINT ['/bin/echo', 'hello']
CMD ['world']

如果我们运行
docker run -it < image > 会输出 hello world

而如果我们运行

docker run -it < image > harry 会输出 hello harry

这就是因为我上面说过的,如果run的时候没有指定CMD会执行,如果指定了命令就不会执行CMD了。

所以总结起来他们两者的关键区别在于:

CMD会被作为命令或者参数在ENTRYPOINT 参数后追加。

CMD可被覆盖,ENTRYPOINT不会被覆盖

CMD结合ENTRYPOINT的使用

想象一下这样一个简单的场景,我们只希望我们的docker,不作为一个应用程序启动,而是用做一个工具。假设为一个压力测试的工具,这个工具需要被指定一些参数例如说 --vm 之类的我们可以通过 ->

CMD["/usr/bin/strees",'--vm 1']这种形式进行启动。但是有没有想过,这样的话变量值就被限制死了,有什么好办法做到docker启动的时候动态传入吗?我都这么说了,当然是有的:

FROM ubuntu
RUN apt-get update && apt-install -y stress
ENTRYPOINT ["/usr/bin/stress"]
CMD[]

这样在启动的使用就可以动态的将变量传入:

docker run -it dockerImage名称 --vm 1

最后总结一下,其实如果CMD和ENTRYPOINT结合的来,那么ENTRYPOINT是用来指定命令的,而CMD中的则是用来指定参数的。

相关文章
|
25天前
|
缓存 安全 Docker
《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)
《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)
53 0
|
2月前
|
应用服务中间件 Shell nginx
Docker进阶:深入了解 Dockerfile
Dockerfile 是定义 Docker 镜像内容和构建步骤的文本文件,用于定制化镜像构建,包括基础镜像选择、软件安装和环境变量设置等。其优点在于支持容器化趋势,简化快速部署和交付,保证环境一致性,实现资源隔离和安全性,以及促进持续集成与持续部署。Dockerfile 指令如 FROM(指定基础镜像)、RUN(执行命令)、CMD(容器启动命令)和 EXPOSE(声明端口)。编写规则包括使用大写指令、创建 .dockerignore 文件排除无关文件等。
100 0
|
4月前
|
Cloud Native NoSQL Redis
云原生 Docker Dockerfile 构建应用
【1月更文挑战第9天】云原生 Docker Dockerfile 构建应用
|
4月前
|
Cloud Native Docker 容器
云原生 Docker Dockerfile 构建配置
【1月更文挑战第9天】云原生 Docker Dockerfile 构建配置
|
4月前
|
分布式计算 Java Linux
【深入浅出Docker原理及实战】「原理实战体系」零基础+全方位带你学习探索Docker容器开发实战指南(Dockerfile使用手册)
Docker 是一套构建在 Linux 内核之上的高级工具,旨在帮助开发人员和运维人员更轻松地交付应用程序和依赖关系,实现跨系统和跨主机的部署。使用安全且轻量级的容器环境来实现这一目标。容器可以手动创建,也可以通过编写 Dockerfile 自动创建。开发人员和运维人员可以将应用程序及其依赖打包到容器中,实现应用程序的可移植性和环境一致性。
126 5
【深入浅出Docker原理及实战】「原理实战体系」零基础+全方位带你学习探索Docker容器开发实战指南(Dockerfile使用手册)
|
4月前
|
Java 持续交付 Docker
Docker 项目如何使用 Dockerfile 构建镜像?
Docker 简介:讲述 Docker 的起源、它是如何革新现代软件开发的,以及它为开发者和运维团队带来的好处。重点强调 Docker 的轻量级特性和它在提高应用部署、扩展和隔离方面的优势。
|
6天前
|
数据库 Docker 容器
【Docker 专栏】使用 Dockerfile 自动化构建 Docker 镜像
【5月更文挑战第8天】Dockerfile是构建Docker镜像的关键,它包含一系列指令,用于描述应用运行环境及所需软件包。通过自动化构建,能提高效率、保证可重复性并提升灵活性。确定基础镜像、安装依赖、设置环境后,执行Dockerfile生成镜像,用于应用程序部署。虽然需要熟悉Docker技术和应用细节,但其带来的益处使其成为现代软件开发和部署的重要工具。
【Docker 专栏】使用 Dockerfile 自动化构建 Docker 镜像
|
16天前
|
应用服务中间件 Shell nginx
制作docker镜像的dockerfile编写规则汇总
制作docker镜像的dockerfile编写规则汇总
|
20天前
|
应用服务中间件 Shell nginx
[Docker] Dockerfile
[Docker] Dockerfile
|
21天前
|
JavaScript Java Docker
使用 Dockerfile 构建和定制 Docker 镜像
Dockerfile是构建Docker镜像的文本文件,包含一系列指令,如`FROM`, `WORKDIR`, `COPY`, `RUN`, `EXPOSE`和`CMD`。它用于自动化`docker build`命令来创建Image。使用Dockerfile可以基于官方镜像定制应用镜像,方便应用容器化和扩展。基本流程包括选择基础镜像、设置工作目录、安装依赖、暴露端口和定义启动命令。构建镜像使用`docker build`,运行容器用`docker run`。了解并熟练使用Dockerfile能提升容器化部署效率。
24 0