大家好,上一个系列我们使用docker安装了一系列的基础服务,但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间,更是容易遗忘,下面我们进行Docker的进阶教程,帮助我们更快速的部署和演示项目。
一、什么是Dockerfile?
Dockerfile 是一个文本文件,其中包含了一系列指令,用于自动化创建 Docker 镜像的过程。通过Dockerfile,你可以定义应用程序的环境,包括所需的软件、库和依赖项。简单的说就是把我们的安装一个基础服务的所有操作命令都编排在一个文件里,包含了拉取镜像,环境变量设置,容器启动等等一系列的操作。
二、如何使用Dockerfile?
2.1 Dockerfile文件解读
下面是一个简单的springboot项目的Dockerfile文件
# 使用官方Java运行环境作为基础镜像
# 命令解释:如果本地没有openjdk:8-jre镜像 则会自动从远程镜像仓库拉取镜像
FROM openjdk:8-jre
# 设置docker容器内jar工作目录
# docker容器内部的jar工作目录 也就是jar将部署在这个目录下 并非宿主机中的文件目录
WORKDIR /kim
# 暴露docker容器内9200端口
EXPOSE 9200
# 设置容器时区
ENV TZ=Asia/Shanghai
# 将你的jar包添加到容器中 将打包好的jar添加到容器中去
ADD kingoffice-auth.jar /kim/kingoffice-auth.jar
# 声明日志卷,容器内应用生成的日志将被存储在这个位置
VOLUME /kim/logs
# 设置容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "/kim/kingoffice-auth.jar"]
2.2 构建镜像
下面执行 docker build
命令,运行脚本文件,构建镜像,注意请在Dockerfile同级目录下执行命令。
# 注意后面有一个"点"
docker build -t kingoffice-auth:1.0.0 .
docker build
:这是 Docker 的构建命令,用于根据Dockerfile
中的指令创建 Docker 镜像-t kingoffice-auth:1.0.0
:指定构建的镜像的名称为kingoffice-auth,同时设置版本标签为 1.0.0.
:这个参数指定了Dockerfile
所在的路径,.
表示当前目录。Docker 会在当前目录下寻找名为Dockerfile
的文件,并根据其中的指令构建镜像,也可不使用.
可以使用绝对路径读取Dockerfile文件,此处不再赘述。
构建完成后可以在本地看到构建好的镜像文件。
2.3运行镜像
docker run -d -p 9200:9200 --restart=always -v /kim/logs/gateway:/kim/logs kingoffice-auth
-d
:表示后台运行-p
:表示端口映射(宿主机端口:容器端口)--restart=always
:容器停止后自动重启-v
:挂载目录映射(宿主机目录:容器目录),将日志文件夹映射到主机上,方便查看日志。
通过 docker ps
命令,可以查看容器已经运行:
三、Dockerfile 常用命令
1. FROM
指明构建的新镜像是基于哪个基础镜像,如果没有选择 tag,那么默认值为 latest。
- 语法:
FROM <image>:<tag>
- 示例:
FROM openjdk:8-jre
2. LABEL
向镜像添加元数据,提供关于镜像的描述信息。
- 语法:
LABEL <key>=<value> <key>=<value> ...
- 示例:
LABEL version="1.0" description="My custom Docker image"
3. RUN
在构建镜像时执行命令。
- Shell形式语法:
RUN <command>
- Exec形式语法:
RUN ["apt", "update", "&&", "apt", "install", "-y", "vim"]
4. COPY
拷贝文件或目录到镜像中。
- 语法:
COPY <src> <dest>
- 示例:
COPY hello-springboot-0.0.1-SNAPSHOT.jar app.jar
5. ADD
类似于COPY,支持更多功能,如下载URL并解压缩。
- 语法:
ADD <src> <dest>
- 示例:
ADD https://example.com/file.tar.gz /tmp/
6. WORKDIR
设置工作目录,后续命令在该目录下执行。
- 语法:
WORKDIR /path/to/directory
7. ENV
在构建镜像过程中设置环境变量,这些环境变量是一直存在于镜像中的。
- 语法:
ENV key value
或ENV key1=value1 key2=value2
举例:
# 设置一个名为 "WORK_HOME" 的环境变量
ENV WORK_HOME /kim
# 引用WORK_HOME环境变量
WORKDIR $WORK_HOME
如果在 Dockerfile 中使用 ENV
指令设置了环境变量,那么在使用 docker run
命令的时候,可以使用 -e
参数覆盖 Dockerfile 中设置的值。这在需要动态配置容器时非常有用,比如根据运行时的条件来设置不同的环境变量值。
8. ARG
ARG
命令与 ENV
命令作用一样,和 ENV
命令不同的是:这些变量只在构建过程中有效,构建完成后不会被保留在最终的镜像中。
语法:ARG key[=value]
name
:参数的名称。default_value
:参数的默认值,可以缺省。
构建过程中,ARG
定义的参数可以用于在 Dockerfile 中的各个指令中,并在 docker build
命令中被覆盖。它对于在构建时动态地传递参数非常有用。
举例:
# 定义构建参数
ARG VERSION=latest
ARG BUILD_DATE
# 使用构建参数设置环境变量
ENV APP_VERSION=$VERSION
ENV BUILD_DATE=$BUILD_DATE
在构建的时候,可以通过 --build-arg 传递参数:
# 可以传递多个参数
docker build --build-arg VERSION=1.0.0 --build-arg BUILD_DATE=$(date) -t my-image .
9. EXPOSE
EXPOSE
命令的作用就是对外暴漏端口。但是并不是打开端口,而是声明,实际还是在运行 docker run
命令的时候,通过 -p
参数指定。
- 语法:
EXPOSE <port>
或EXPOSE <port> [<port>/<protocol>]
- 示例:
EXPOSE 80
10. CMD
CMD
命令用于为容器指定默认的执行命令或应用程序。当容器启动时,这个命令将被执行,可以用来启动容器中的应用程序。
前面的 RUN
命令是在构建镜像的时候执行,也就是执行 docker build
命令的时候执行;而 CMD
命令是启动容器的时候执行,也就是执行 docker run
命令的时候执行。
查看官方的 Tomcat 镜像的 Dockerfile,可以看到最后一行脚本是:
CMD ["catalina.sh", "run"]
1
catalina.sh run
命令也就是启动 Tomcat 的命令。如果没有这行命令,在使用 docker run
命令启动 Tomcat 容器的时候,容器是启动起来了,但是容器中的 Tomcat 没有被启动。所以 CMD
命令可以用来启动容器中的应用程序的。
如果在 Dockerfile 中存在多个 CMD
命令,只有最后一个会生效。
CMD
命令的语法和 RUN
命令相似,也支持 Shell
和 Exec
两种格式:
# Shell格式
CMD <command>
# Exec格式
CMD ["参数1", "参数2", ...]
需要注意:CMD中定义的命令会被 docker run 之后的参数替换。
什么意思呢?看下面的指令:
docker run -it -p 8080 tomcat /bin/bash
上面的 /bin/bash
就是 docker run 之后的参数,会替换掉 Tomcat Dockerfile文件中的 CMD ["catalina.sh", "run"]
命令中的参数,导致容器启动了,但是 Tomcat 没有被启动,所以一定要注意。
11. VOLUME
-
作用:做匿名挂载,在启动容器时忘记挂载数据卷时会自动挂载到匿名卷。
-
语法:
VOLUME <path>
VOLUME <path1> <path2>
VOLUME ["<path1>", "<path2>", ...]
例如:
FROM openjdk:8-jre
VOLUME /data
VOLUME /config
在运行容器时,你可以使用 -v
选项来将宿主机上的目录挂载到 VOLUME
声明的目录上。例如:
docker run -v /kim/data:/data -v /kim/config:/config my-image
这样宿主机上的/kim/data目录就挂载到了 容器内/data目录下。
四、虚悬镜像
虙悬镜像(Dangling Image)是指镜像名称和标签均为 <none>
的镜像。这些镜像通常出现在构建过程中出现问题、取消构建或其他异常情况下。由于这些镜像没有有效的名称和标签,它们被视为"悬浮"在Docker中,没有被任何容器所使用,也不会被Docker清理工具自动删除。
虙悬镜像的产生概率并不高,但一旦出现,可能会对系统造成一些潜在的风险和占用存储空间。因此,及时发现并删除虙悬镜像是很重要的。
查看虚悬镜像
docker image ls -f dangling=true
删除虚悬镜像
docker image prune --filter "dangling=true"
虚悬镜像会占用磁盘空间,并可能对系统造成潜在风险,因此建议及时查看和删除虚悬镜像。