在 Docker 中创建镜像最常用的方式,就是使用 Dockerfile。Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。官方文档:https://docs.docker.com/engine/reference/builder/

  

Dockerfile 常用指令

  

FROM

  

  语法:FROM <image>:<tag>

  指明构建的新镜像是来自于哪个基础镜像,如果没有选择 tag,那么默认值为 latest。

FROM centos:7

  如果不以任何镜像为基础,那么写法为:FROM scratch。官方说明:scratch 镜像是一个空镜像,可以用于构建 busybox 等超小镜像,可以说是真正的从零开始构建属于自己的镜像。

  

MAINTAINER(deprecated)

  

  语法:MAINTAINER <name>

  指明镜像维护者及其联系方式(一般是邮箱地址)。官方说明已过时,推荐使用 LABEL。

MAINTAINER mrhelloworld <mrhelloworld@126.com>

  

LABEL

  

  语法:LABEL <key>=<value> <key>=<value> <key>=<value> ...

  功能是为镜像指定标签。也可以使用 LABEL 来指定镜像作者。

LABEL maintainer="mrhelloworld.com"

  

RUN

  

  语法:RUN <command>

  构建镜像时运行的 Shell 命令,比如构建的新镜像中我们想在 /usr/local 目录下创建一个 java 目录。

RUN mkdir -p /usr/local/java

  

ADD

  

  语法:ADD <src>... <dest>

  拷贝文件或目录到镜像中。src 可以是一个本地文件或者是一个本地压缩文件,压缩文件会自动解压。还可以是一个 url,如果把 src 写成一个 url,那么 ADD 就类似于 wget 命令,然后自动下载和解压。

ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

  

COPY

  

  语法:COPY <src>... <dest>

  拷贝文件或目录到镜像中。用法同 ADD,只是不支持自动下载和解压。

COPY jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

  

EXPOSE

  

  语法:EXPOSE <port> [<port>/<protocol>...]

  暴露容器运行时的监听端口给外部,可以指定端口是监听 TCP 还是 UDP,如果未指定协议,则默认为 TCP。

EXPOSE 80 443 8080/tcp

如果想使得容器与宿主机的端口有映射关系,必须在容器启动的时候加上 -P 参数。

  

ENV

  

  语法:ENV <key> <value> 添加单个,ENV <key>=<value> ... 添加多个。

  设置容器内环境变量。

ENV JAVA_HOME /usr/local/java/jdk-11.0.6/

  

CMD

  

  语法:

  • CMD ["executable","param1","param2"],比如:CMD ["/usr/local/tomcat/bin/catalina.sh", "start"]
  • CMD ["param1","param2"] ,比如:CMD [ "echo", "$JAVA_HOME" ]
  • CMD command param1 param2,比如:CMD echo $JAVA_HOME

  启动容器时执行的 Shell 命令。在 Dockerfile 中只能有一条 CMD 指令。如果设置了多条 CMD,只有最后一条 CMD 会生效。

CMD ehco $JAVA_HOME

  如果创建容器的时候指定了命令,则 CMD 命令会被替代。假如镜像叫 centos:7,创建容器时命令是:docker run -it --name centos7 centos:7 echo "helloworld" 或者 docker run -it --name centos7 centos:7 /bin/bash,就不会输出 $JAVA_HOME 的环境变量信息了,因为 CMD 命令被 echo "helloworld"/bin/bash 覆盖了。

  

ENTRYPOINT

  

  语法:

  • ENTRYPOINT ["executable", "param1", "param2"],比如:ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh", "start"]
  • ENTRYPOINT command param1 param2,比如:ENTRYPOINT ehco $JAVA_HOME

  启动容器时执行的 Shell 命令,同 CMD 类似,不会被 docker run 命令行指定的参数所覆盖。在 Dockerfile 中只能有一条 ENTRYPOINT 指令。如果设置了多条 ENTRYPOINT,只有最后一条 ENTRYPOINT 会生效。

ENTRYPOINT ehco $JAVA_HOME
  • 如果在 Dockerfile 中同时写了 ENTRYPOINT 和 CMD,并且 CMD 指令不是一个完整的可执行命令,那么 CMD 指定的内容将会作为 ENTRYPOINT 的参数;
  • 如果在 Dockerfile 中同时写了 ENTRYPOINT 和 CMD,并且 CMD 是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效

  

WORKDIR

  

  语法:WORKDIR /path/to/workdir

  为 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 设置工作目录。

WORKDIR /usr/local

  

VOLUME

  

  指定容器挂载点到宿主机自动生成的目录或其他容器。一般的使用场景为需要持久化存储数据时。

# 容器的 /var/lib/mysql 目录会在运行时自动挂载为匿名卷,匿名卷在宿主机的 /var/lib/docker/volumes 目录下
VOLUME ["/var/lib/mysql"]

一般不会在 Dockerfile 中用到,更常见的还是在 docker run 的时候通过 -v 指定数据卷。

  

构建镜像

  

  Dockerfile 文件编写好以后,真正构建镜像时需要通过 docker build 命令。

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

# 使用当前目录的 Dockerfile 创建镜像
docker build -t mycentos:7 .
# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .
  • -f:指定要使用的 Dockerfile 路径;
  • --tag, -t:镜像的名字及标签,可以在一次构建中为一个镜像设置多个标签。

  

关于 . 理解

  

  我们在使用 docker build 命令去构建镜像时,往往会看到命令最后会有一个 . 号。它究竟是什么意思呢?

  很多人以为是用来指定 Dockerfile 文件所在的位置的,但其实 -f 参数才是用来指定 Dockerfile 的路径的,那么 . 号究竟是用来做什么的呢?

  Docker 在运行时分为 Docker 引擎(服务端守护进程)客户端工具,我们日常使用各种 docker 命令,其实就是在使用 客户端工具Docker 引擎 进行交互。

  当我们使用 docker build 命令来构建镜像时,这个构建过程其实是在 Docker 引擎 中完成的,而不是在本机环境。如果在 Dockerfile 中使用了一些 ADD 等指令来操作文件,如何让 Docker 引擎 获取到这些文件呢?

  这里就有了一个 镜像构建上下文 的概念,当构建的时候,由用户指定构建镜像时的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到上下文中的文件了。

  

  举个栗子:我的宿主机 jdk 文件在 /root 目录下,Dockerfile 文件在 /usr/local/dockerfile 目录下,文件内容如下:

ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

  那么构建镜像时的命令就该这样写:

docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root

  

  再举个栗子:我的宿主机 jdk 文件和 Dockerfile 文件都在 /usr/local/dockerfile 目录下,文件内容如下:

ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java

  那么构建镜像时的命令则这样写:

docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .

  

Dockerfile 实践

  

  接下来我们通过基础镜像 centos:7,在该镜像中安装 jdk 和 tomcat 以后将其制作为一个新的镜像 mycentos:7

  创建目录。

mkdir -p /usr/local/dockerfile

  编写 Dockerfile 文件。

vi Dockerfile

  Dockerfile 文件内容如下:

# 指明构建的新镜像是来自于 centos:7 基础镜像
FROM centos:7
# 通过镜像标签声明了作者信息
LABEL maintainer="mrhelloworld.com"
# 设置工作目录
WORKDIR /usr/local
# 新镜像构建成功以后创建指定目录
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷贝文件到镜像中并解压
ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat
# 暴露容器运行时的 8080 监听端口给外部
EXPOSE 8080
# 设置容器内 JAVA_HOME 环境变量
ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
ENV PATH $PATH:$JAVA_HOME/bin
# 启动容器时启动 tomcat 并查看 tomcat 日志信息
ENTRYPOINT /usr/local/tomcat/apache-tomcat-9.0.37/bin/startup.sh && tail -f /usr/local/tomcat/apache-tomcat-9.0.37/logs/catalina.out

  构建镜像。

docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root/

[root@localhost ~]# docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root/
Sending build context to Docker daemon 191.4MB
Error response from daemon: Dockerfile parse error line 1: unknown instruction: NTOS:7
[root@localhost ~]# vi /usr/local/dockerfile/Dockerfile
[root@localhost ~]# vi /usr/local/dockerfile/Dockerfile
[root@localhost ~]# docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root/
Sending build context to Docker daemon 191.4MB
Step 1/10 : FROM centos:7
---> 7e6257c9f8d8
Step 2/10 : LABEL maintainer="mrhelloworld.com"
---> Running in 4c561fed28a5
Removing intermediate container 4c561fed28a5
---> b536fc4e4290
Step 3/10 : WORKDIR /usr/local
---> Running in 50141816c10e
Removing intermediate container 50141816c10e
---> 030f9db632da
Step 4/10 : RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
---> Running in d1f8f4e008c8
Removing intermediate container d1f8f4e008c8
---> 68773de3525a
Step 5/10 : ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
---> 92f410a9e1ba
Step 6/10 : ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat
---> 8e0576fccd4e
Step 7/10 : EXPOSE 8080
---> Running in bb6c4ef8f4e1
Removing intermediate container bb6c4ef8f4e1
---> 01edd4710cc1
Step 8/10 : ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
---> Running in 722c2d369a2f
Removing intermediate container 722c2d369a2f
---> ef5172fb1dd6
Step 9/10 : ENV PATH $PATH:$JAVA_HOME/bin
---> Running in eaa287937565
Removing intermediate container eaa287937565
---> 0347db73b904
Step 10/10 : ENTRYPOINT /usr/local/tomcat/apache-tomcat-9.0.37/bin/startup.sh && tail -f /usr/local/tomcat/apache-tomcat-9.0.37/logs/catalina.out
---> Running in 8f93d36f4de2
Removing intermediate container 8f93d36f4de2
---> 1674e0191270
Successfully built 1674e0191270
Successfully tagged mycentos:7

  

镜像构建历史

  

docker history 镜像名称:标签|ID
docker history mycentos:7

  

使用构建的镜像创建容器

  

# 创建容器
docker run -di --name mycentos7 -p 8080:8080 mycentos:7
# 进入容器
docker exec -it mycentos7 /bin/bash
# 测试 java 环境变量
[root@dcae87df010b /]# java -version
java version "11.0.6" 2020-01-14 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.6+8-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.6+8-LTS, mixed mode)
# 访问 http://192.168.10.10:8080/ 看到页面说明环境 OK!

太棒了,Dockerfile 构建镜像的方式你也学会了,再接再厉学习一下 Docker 镜像的备份恢复迁移,go ~

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

大家可以通过 分类 查看更多关于 Docker 的文章。

  

Docker 镜像构建之 Dockerfile的更多相关文章

  1. Docker镜像构建文件Dockerfile及相关命令介绍

    使用docker build命令或使用Docker Hub的自动构建功能构建Docker镜像时,都需要一个Dockerfile文件.Dockerfile文件是一个由一系列构建指令组成的文本文件,doc ...

  2. Docker镜像构建之Dockerfile

    在 Docker 中构建镜像最常用的方式就是使用 Dockerfile.Dockerfile 是一个用来构建镜像的文本文件. 官方文档:https://docs.docker.com/engine/r ...

  3. Docker镜像构建(五)

    Docker 镜像介绍 Docker镜像构建分为两种,一种是手动构建,另一种是Dockerfile(自动构建) 手动构建docker镜像 案例:我们基于centos镜像进行构建,制作自己的nginx镜 ...

  4. 4、Docker 镜像构建

    Docker 镜像构建 构建分为两种 手动构建 自动构建dockerfile 手动构建 首先启动一个Centos 容器,然后在容器中安装一个nginx [root@node ~]# docker ru ...

  5. Docker镜像构建原理解析(不装docker也能构建镜像)

    在devops流程里面 构建镜像是一个非常重要的过程,一般构建镜像是写dockerfile文件然后通过docker client来构建的image. docker client 会先检查本地有没有im ...

  6. Docker镜像构建的两种方式

    关于Docker里面的几个主要概念 这里用个不太恰当的比方来说明. 大家肯定安装过ghost系统,镜像就像是ghost文件,容器就像是ghost系统.你可以拿别人的ghost文件安装系统(使用镜像运行 ...

  7. Docker-通过docker-maven-plugin插件实现docker镜像构建并自动发布到远程docker服务器

    我们知道,docker能实现应用打包隔离,实现快速部署和迁移.如果我们开发应用使用了spring cloud + spring boot架构,那么,通过docker-maven-plugin实现快速构 ...

  8. Docker镜像构建的两种方式(六)--技术流ken

    镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...

  9. Docker镜像构建

    一.简介 在构建容器化应用时,相当重要的步骤莫过于镜像制作,本文将介绍镜像制作方法以及镜像制作的建议.通常镜像的制作有两种方式: 使用现有的容器使用docker commit 生成镜像 使用Docke ...

随机推荐

  1. PHP array_map() 函数

    实例 将函数作用到数组中的每个值上,每个值都乘以本身,并返回带有新的值的数组: <?phpfunction myfunction($v){return($v*$v);} $a=array(1,2 ...

  2. PHP mkdir() 函数

    定义和用法 mkdir() 函数创建目录. 如果成功该函数返回 TRUE,如果失败则返回 FALSE. 语法 mkdir(path,mode,recursive,context) 参数 描述 path ...

  3. C/C++编程笔记:C++入门知识丨函数和函数模板

    本篇要学习的内容和知识结构概览 函数的参数及其传递方式 1. 函数参数传递方式 传值: 传变量值: 将实参内存中的内容拷贝一份给形参, 两者是不同的两块内存 传地址值: 将实参所对应的内存空间的地址值 ...

  4. 7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆

    LINK:探险队 非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了. 首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了. 所以我们要做的其实 ...

  5. number类型转date类型

    遇到用数字记录日期时,进行查询转换. create or replace function num_to_date(s in number) return dateisbegin return to_ ...

  6. mybatis plus 更新值为null的字段

    转载请注明出处: 由于mybatis plus调用默认的更新操作方法时,不更新值为空,null或默认值等得属性字段,只更新值为非null,非空非默认值的属性字段. 以下为mybatis plus sa ...

  7. 简单配置iOS的通用链接,迅速解决“universal link 校验不通过”问题!

    对于需要使用微信支付等功能的APP来说,对接微信提供的openSDK是不可缺少的一环.随着苹果iOS 13系统版本的安全升级,为此openSDK在1.8.6版本进行了适配.1.8.6之后的openSD ...

  8. spring-Sessions are not supported by the MongoDB cluster to which this client is connected

    原因: 1.mongodb版本过低4.0以下不支持事务的情况下会报这个 2.安全认证问题参考如下连接 https://blog.csdn.net/ssehs/article/details/10530 ...

  9. Java项目中经常遇到的一些异常情况

    一. 1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存 ...

  10. 理解JavaScript的原型链

    1. 什么是对象 在JavaScript中,对象是属性的无序集合,每个属性存放一个原始值.对象或函数. 1.1 创建对象 在JavaScript中创建对象的两种方法: ① 字面上: var myObj ...