Dockerfile语法、自定义镜像构建详解

「爱情、让人受尽委屈。」 2024-04-07 14:11 158阅读 0赞

Dockerfile语法、自定义镜像构建详解

简单的说Dockerfile就是一个文本文件。

Docker使用它就可以帮助我们构建镜像。

大部分镜像都可以在DockerHub上找到。

但是以后自己写的微服务,想要发布到Docker上运行,就需要自己来构建镜像了。

一、镜像的结构

镜像是一个分层结构,每一层称为一个Layer.

可以大致把这些层分为三部分:

1.1 基础镜像层(BaseImage)

应用依赖的函数库、环境变量、配置、文件系统等。

最底层的Layer

1.2 中间层(Layer)

BaseImage的基础上,添加安装包、依赖、配置等。

中间层并不是只单独的一层,而是基础镜像层和入口层之间的所有Layer

1.3 入口层(Entrypoint)

指镜像的运行入口,可以是程序的启动脚本。

是最顶层的Layer

1.4 镜像分层的好处

最直接的好处就是节省磁盘空间和共享资源。

比如有多个镜像都是从相同的BaseImage构建来的。

那么Docker只需要在磁盘上保持一份BaseImage,并且内存也只需加载一份BaseImage

这样就实现了BaseImage的复用。

1.5 注意点

Docker镜像一旦制作完成,层级就不能够再去更改,这也是从安全性和可维护可拓展性考虑。

如果想要修改镜像,比如拓展镜像的功能,只能够在原来的层级上加一层,再统一打包成镜像。

如果不了解这个过程,自己制作镜像时,也可以从头开始打包。

1.6 镜像的概念

镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合。

然后编写好启动脚本和上面的文件组合统统打包在一起形成的文件。

要自定义构建镜像,就是实现上述打包的过程。

二、Dockerfile及其相关命令

自己构建自定义的镜像时,并不需要把所有文件一个个拷贝,打包。

只要告诉Docker,镜像的组成,需要哪些BaseImage、需要拷贝什么文件、需要安装什么依赖、以及启动脚本。

Docker会帮助我们构建镜像。

而描述上述信息的文件就是Dockerfile文件,它相当于就是构建镜像的说明书。

因此,Dockerfile就是一个文本文件,它提供了一种可以通过描述文件来构建镜像的一种方式

用指令来说明Docker要执行什么操作去构建镜像。

每一个指令都会形成一层Layer

2.1 Dockerfile常用命令














































指令名称 说明 示例
FROM 指定基础镜像是什么 FROM centos:7
ENV 设置环境变量,可在后面指令使用 ENV key value
COPY 拷贝本地文件到镜像的指定目录 COPY <源路径> <目标路径>
ADD 将文件、目录或远程 URL 从源目录复制到镜像中的目标目录 ADD <源路径> <目标路径>
RUN 执行Linux的shell命令,一般是当前应用安装过程的命令 RUN yum install gcc
EXPOSE 指定容器运行时监听的端口 EXPOSE 80
ENTRYPOINT 镜像中应用的启动命令,容器运行时调用 ENTRYPOINT java -jar xx.jar

2)关于 ADDCOPY

ADDCOPY 都是用于将文件从主机复制到 Docker 镜像中的命令,但它们之间有一些区别。

ADD 命令的功能比 COPY 更强大。除了复制文件, ADD 命令还支持以下功能:

  • 如果源路径是一个 URL,它可以自动下载并将文件复制到镜像中。
  • 如果源文件是一个归档文件(如 tar 文件),它会自动解压缩并将文件复制到镜像中。
  • 如果目标路径不存在, ADD 命令会自动创建目标路径。

COPY 命令相对简单,只能用于将本地文件或目录复制到镜像中,不支持自动解压缩和下载功能。

但是,由于 COPY 命令的行为更明确和可预测,所以在大多数情况下,建议使用 COPY 命令而不是 ADD 命令。

总结ADD 命令在功能上更丰富,而 COPY 命令更直观和可控。根据具体需求,选择适合的命令来复制文件到 Docker 镜像中。

2)关于EXPOSE

EXPOSE 监听的端口,一般也是在docker run 运行镜像生成容器时,需要把容器和宿主机相关联的端口。

如果上面的命令满足不了构建镜像的需要时。

可以查阅官方文档 :

  1. https://docs.docker.com/engine/reference/builder/

文档里什么命令都有,但是有相当一部分是不常用的

三、使用Dockerfile一个JavaWeb程序构建为镜像

3.1 文件准备

在这里插入图片描述

  • docker-demo.jar:需要制作成镜像的SpringBoot项目。
  • Dockerfile:包含了镜像构建的全部步骤。
  • jdk-8u171-linux-x64.tar.gz:jdk安装包。

先解压jdk-8u171-linux-x64.tar.gz,是因为我想知道解压出来的目录叫什么名字,在Dockerfile中有用。

3.2 编写Dockerfile文件

  1. # 指定基础镜像
  2. FROM ubuntu:16.04
  3. # 配置环境变量,JDK的安装目录
  4. ENV JAVA_DIR=/usr/local
  5. # 拷贝jdk和java项目的包
  6. COPY ./jdk-8u171-linux-x64.tar.gz $JAVA_DIR/ # 把jdk压缩包复制到/usr/local目录下
  7. COPY ./docker-demo.jar /soft/app.jar # 把java程序移动到/soft目录下并重命令为app.jar
  8. # 使用RUN命令执行Linux的shell命令
  9. RUN cd $JAVA_DIR \ # 跳转到 到/usr/local目录下
  10. && tar -xf ./jdk-8u171-linux-x64.tar.gz \ # 解压缩jdk的安装包
  11. && mv ./jdk1.8.0_171 ./java8 # 把jdk解压出来的目录重命名为java8
  12. # 其实重命名操作都是非必须的,只是用更短的名字更好操作一些
  13. # 配置环境变量
  14. ENV JAVA_HOME=$JAVA_DIR/java8 # 把jdk的安装目录配置成环境变量JAVA_HOME
  15. ENV PATH=$PATH:$JAVA_HOME/bin # 最后再配置PATH变量为jdk的安装目录
  16. # 暴露需要被监听端口,就是让被完全隔离的容器暴露出一个可以被外界访问的端口
  17. # 一般就是application.yml中配置的端口号
  18. EXPOSE 8999
  19. # 程序运行入口,就是java项目的启动命令
  20. # 这句话也是容器成功运行后,第一个执行的命令
  21. ENTRYPOINT java -jar /soft/app.jar

3.3 构建镜像

运行构建镜像命令

  1. # 写法一:默认文件名称必须叫Dockerfile
  2. # -t 代表以' Name:tag'格式命名和可选的标记 (相当于就是-tag)
  3. # . 代表构建镜像所需的文件都在Dockerfile文件所在的目录下
  4. docker build -t javaapp:1.0 .
  5. # 写法二:自己执行Dockerfile文件是谁
  6. # -f 手动指定Dockerfile的文件名称
  7. docker build -f mydockerfile -t javaapp:1.0

注意:

1)构建的镜像名称必须全部小写

2)没有特殊情况文件名称就用Dockerfile就行,容易记忆,更加直观,也符合习惯

在这里插入图片描述

可以看到Docker在一步步执行Dockerfile文件中的步骤。一共是9步。

最终构建成功!

构建成功后查看镜像:

  1. docker images

确认镜像存在后运行镜像:

  1. # --name myApp 定义容器名称为myApp
  2. # -p 把主机的8999端口和容器的8999相关联
  3. # -d 后台运行
  4. # javaapp:1.0 需要运行的镜像名称
  5. docker run --name myApp -p 8999:8999 -d javaapp:1.0

成功运行后查看正在运行的容器:

  1. docker ps

确认java程序在容器中正常运行后,就可以在浏览器中访问了。

四、使用java:8-alpine镜像去优化Dockerfile文件的编写

在微服务项目中,肯定不止一个镜像需要我们去构建。

如果每个微服务都是使用java编写的话。

那么Dockerfile文件中,选择基础镜像、安装jdk、配置环境变量的操作都是一致的。

我们没必要对每个微服务的镜像构建都做一次上面的操作。java:8-alpine这个镜像就已经做了上面的操作。

所以我们只要选择java:8-alpine,作为我们的基础镜像,就可以避免上面的重复操作了。

这也是Docker镜像分层的体现。

如果对Docker镜像分层机制不了解,可以查看我Docker专栏下的Docker的概念、架构、安装详解这篇博文。

了解了java:8-alpine镜像的作用之后,就可以这么优化Dockerfile文件了:

  1. # 指定java:8-alpine作为基础镜像,它包含了java程序部署的基本环境依赖
  2. FROM java:8-alpine
  3. # 暴露需要被监听端口(一般就是application.yml中配置的端口号)
  4. EXPOSE 8999
  5. # 程序运行入口,就是java项目的启动命令
  6. ENTRYPOINT java -jar /soft/app.jar

这样以后构建别的微服务的Dockerfile文件就方便多了。

并且使用它构建镜像时,步骤也从9步变成了4步。

发表评论

表情:
评论列表 (有 0 条评论,158人围观)

还没有评论,来说两句吧...

相关阅读