首先,让我们来介绍一下对于大多数人来说容易有疑惑的地方
WORKDIR 指定工作目录
什么是工作目录?为什么要指定?
拿 window 系统的 powershell 控制台来类比。打开 powershell 命令行控制台,显示的是默认目录,如:C:\Users\18154
刚创建容器的时候,执行的命令也是在默认的目录下执行的,使用 WORKDIR 命令则是切换到我们指定目录。有点类似 cd 命令(但还是有区别)切换到指定目录,后面的命令都是在切换后的目录下执行,即在工作目录下执行。
PS: 执行 WORKDIR 时,如果目录不存在容器会自动创建
VOLUME 持久化
在 Dockerfile 中,VOLUME /data 指的是容器中的目录?
是的,VOLUME /data
是一个指令,用于在容器中创建一个挂载点(volume),并将其挂载到 /data
目录。PS: 如果目录不存在,容器会自行创建。
Dockerfile 中指定了 volume,在启动容器时,需要 -v 参数吗?
在 Dockerfile 中使用 VOLUME 指令指定了一个默认的挂载点,则在使用该镜像运行容器时,会自动为这个挂载点创建一个匿名卷。因此,在启动容器时可以不再使用-v
参数来显式地指定挂载。
例如,如下 Dockerfile 文件
FROM ubuntu:latest
VOLUME /data
CMD ["echo", "Container with data volume"]
那么,在使用该镜像运行容器时,不需要再显式指定挂载点,只需使用docker run
命令即可
docker run demoApp
这样,Docker 将会自动为容器创建一个匿名卷,并将其挂载到容器中的/data
目录
注意:Dockerfile 中的 VOLUME 指令只是在镜像层面指定了默认的挂载点,而具体的挂载操作是在运行容器时通过命令行选项或 Compose 文件进行配置。如果你希望将挂载点与主机上的目录进行关联,可以在运行容器时使用-v
参数来指定具体的主机目录和挂载点,但不是必需的。
Docker volume create my-volume 命令,指向的是主机目录还是容器目录?具体的目录在哪里?
docker volume create 命令创建的 Volume 实际上是一个在主机上的持久性存储卷,并不直接指向主机或容器中的具体目录。
使用 docker volume create 命令创建的 Volume 会在 Docker 守护进程所在的主机上创建一个特定的存储目录。这个目录是专门用于存储 Volume 数据的,可以被一个或多个容器使用,通过容器中的挂载点与该存储卷进行关联。
对挂载及共享持久化不是很理解,什么意思?
举个栗子,在Linux系统中,插入 U盘一般都是不能立刻查看修改 U盘中的文件的,这个时候需要将 U盘与系统关联(手动挂载)。之后就可以直接操作 U盘中的文件(持久化),电脑坏了或系统崩了也没关系,文件在 U盘,可以使用其他电脑(共享)。也可以联想Window系统插入使用 U盘,只是系统已自动挂载 U盘。当然,类比操作系统与虚拟机(类似Vmware)的共享目录更形象。
ENV 设置环境变量
举个栗子:在启动容器时,重新定义端口
myapp 应用的 Dockerfile 文件
FROM openjdk:11
ENV APP_PORT=8080
EXPOSE $APP_PORT
COPY ./target/myapp.jar /app/myapp.jar
CMD ["java", "-jar", "/app/myapp.jar", "--server.port=${APP_PORT}"]
本例,使用ENV
指令设置了APP_PORT
环境变量。然后使用EXPOSE
指令将容器内的APP_PORT
端口暴露出来。最后,使用COPY
指令将构建好的Java程序拷贝到镜像中,并使用CMD
指令运行Java程序。
在启动容器时,可以重新定义端口
docker run -p 8082:8082 -e APP_PORT=8082 myapp
Dockerfile 的常见指令及详解
- FROM描述: 指定基础镜像 语法 FROM <基础镜像名>[:<标签>]
eg. FROM ubuntu:latest
示例,指定ubuntu最新版本
- MAINTAINER描述:指定镜像维护者信息(已废弃,推荐使用LABEL) 语法 MAINTAINER <作者姓名>
eg. MAINTAINER jike <jike@example.com>
示例,指定镜像维护者名称和电子邮件地址
- LABEL描述:给镜像添加元数据 语法 LABEL maintainer=<作者姓名>
eg. LABEL maintainer="jike <jike@example.com>"
示例,使用LABEL添加镜像维护者的姓名和邮箱
- RUN描述:在镜像中执行命令 语法 RUN <命令>
eg. RUN java -jar xxx.jar
示例,运行一个jar包
- COPY描述:将文件从主机复制到镜像中 语法 COPY <源路径> <目标路径>
eg. COPY ./src/demoFile /app/demoFile
示例,将主机中的 src/demoFile 复制到镜像中 /app/demoFile
- ADD描述:类似 COPY, 但可以自动解压压缩文件和获取远程文件 语法 ADD <源路径> <目标路径>
eg. ADD https://example.com/file.tar.gz /app/data/
示例,从指定url下载tar.gz 文件并解压到镜像中 /app/data/目录
- WORKDIR描述:设置工作目录 语法 WORKDIR <工作目录路径>
eg. WORKDIR /app/data
示例,将工作目录设置为 /app/data
- ENV描述:设置环境变量 语法 ENV <变量名>=<值> <变量名2>=<值2>
eg1. ENV PORT=18089
eg2. ENV USERNAME=san
ENV PORT=18088
eg3. ENV USERNAME=shi \
PORT=18087 \
YEAR=2023
示例1,将 PORT 环境变量设置为 18089
示例2,设置多个环境变量,使用多个ENV,每行设置一个环境变量
示例3,设置多个环境变量,使用一个ENV,一行设置多个环境变量
- EXPOSE描述:声明容器运行时需要监听的端口 语法 EXPOSE <端口> EXPOSE <端口1> [<端口2>...]
eg. EXPOSE 8081 8082
示例,声明容器监听8081,8082两个端口
- CMD描述:指定容器启动时要执行的命令 语法 CMD <命令>
eg. CMD ["java", "-jar", "app.jar"]
示例,容器启动后会执行 java -jar app.jar 命令
- ENTRYPOINT描述:与 CMD 类似,但不会被 docker run 命令后的参数覆盖
eg. ENTRYPOINT ["java", "-jar", "app.jar"]
示例,容器启动后会执行 java -jar app.jar 命令,并且无法被 docker run 命令后的参数覆盖
- VOLUME指令:
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。这样做可以避免重要的数据,因容器重启而丢失,这是非常致命的。也能避免容器不断变大。
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
各位读者有不同的见解请留言。
关注我的公众号(追寻9)了解更多开发相关知识!!!
docker官网指南:
https://docs.docker.com/engine/reference/builder/