前言
Dockerfile是用于构建Docker镜像的文本文件,其中包含一系列指令,用于描述镜像的构建步骤和配置信息。通过Dockerfile,可以让用户自动化地构建镜像,并确保在不同的环境中获得相同的镜像。
Dockerfile的语法包括以下几个关键指令:
- FROM:指定基础镜像,格式为
FROM <image>
,用于指定构建镜像所基于的基础镜像。 - MAINTAINER:指定镜像的作者和联系方式,格式为
MAINTAINER <name>
。 - RUN:用于在镜像中执行命令,格式为
RUN <command>
,可以累积多个RUN指令以构建镜像。 - ADD和COPY:用于将文件或目录复制到镜像中,格式为
ADD <src> <dest>
或COPY <src> <dest>
。 - CMD:指定容器启动时执行的默认命令,可以在Dockerfile中只有一个CMD指令,如果有多个CMD指令,只有最后一个生效。
- EXPOSE:声明容器在运行时需要监听的端口,格式为
EXPOSE <port>
。 - ENV:设置环境变量,格式为
ENV <key> <value>
。 - WORKDIR:指定在容器中执行命令的工作目录,格式为
WORKDIR <path>
。 - ENTRYPOINT:配置容器启动时执行的命令,格式为
ENTRYPOINT <command>
。 - VOLUME:声明容器数据卷,格式为
VOLUME <path>
。
除了这些基本指令外,Dockerfile还支持其他一些指令,可以根据具体需求选择使用。
在编写Dockerfile时,建议遵循最佳实践,减少镜像大小、优化镜像构建速度,并保持Dockerfile的可读性和可维护性。
项目的根目录下添加Dockerfile
文件
基本镜像
1 | # Pull base image |
作者信息
旧版本
1 | MAINTAINER psvmc "psvmc@outlook.com" |
新版本
1 | # 使用 LABEL 指定维护者信息 |
环境
1 | # Set Charset |
安装wget
1 | # 安装 wget |
常见环境配置
YUM环境
阿里的
1 | # YUM镜像 |
或者使用华为的
1 | # YUM镜像 |
注意
在华为云的服务器上用不了阿里云的镜像
安装Python2
1 | # 安装Python |
Python3环境
1 | # Pull base image |
安装FFMpeg
1 | # 安装ffmpeg |
安装C++编译环境
1 | # 安装 gcc |
Node环境
安装NodeJS
1 | RUN wget https://mirrors.huaweicloud.com/nodejs/v10.24.0/node-v10.24.0-linux-x64.tar.xz |
NodeJS官方源地址
1 | RUN wget https://nodejs.org/dist/v10.24.0/node-v10.24.0-linux-x64.tar.xz |
设置NPM镜像
淘宝的
1 | # NPM镜像 |
华为的
1 | # NPM镜像 |
安装 node-gyp
1 | # 安装 node-gyp |
注意:
node-gyp
需要在系统中安装 C++ 编译器和 Python 环境。
项目配置
创建文件夹
1 | RUN mkdir /data |
进入文件夹
1 | RUN cd /data |
添加文件到容器内
1 | ADD startup.sh /data/school_live_record/startup.sh |
添加文件夹到容器内
1 | ADD record /data/school_live_record/record |
添加执行权限
1 | RUN chmod +x /data/school_live_record/startup.sh |
移动文件
1 | RUN mv ./Agora_Recording_SDK_for_Linux_FULL/* /data/school_live_record/record/src/sdk/ |
删除文件
1 | RUN rm -rf zxvf Agora_Recording_SDK_for_Linux_v3.0.5_20210106-1609927649_793.tar.gz |
指定启动目录和程序
WORKDIR /data/school_live_record/
:
设置工作目录为/data/school_live_record/
,这样后续的COPY
、RUN
和CMD
指令都会在这个目录下执行。
配置
1 | WORKDIR /data/school_live_record/ |
这两个指令在 Dockerfile 中扮演着不同的角色:
WORKDIR:
该指令用于设置容器中的工作目录。
在例子中,WORKDIR /data/school_live_record/
会将容器的工作目录设置为 /data/school_live_record/
,这意味着在后续的命令中,相对路径都会基于这个工作目录进行解析。
ENTRYPOINT:
该指令用于配置容器启动时执行的默认命令。
在例子中,ENTRYPOINT ./startup.sh
指定了容器启动时需要执行的脚本或命令,这个命令会成为容器的主要进程。
如果你在运行容器时提供了其他命令,它们会被作为参数传递给 ENTRYPOINT 指定的命令。
因此,这两个指令结合起来的作用是,在容器启动时,首先将工作目录设置为指定的目录,然后执行 startup.sh 脚本作为容器的主要进程。
方式1
1 | # Define default command. |
方式2
1 | # Define default command. |
run.sh
1 |
|
文件复制
只复制当前目录下的文件,不包括子目录和子目录中的文件。
1 | COPY ./* /opt/z-card-recognize/ |
复制当前目录下的所有内容,包括子目录和子目录中的文件
1 | COPY . /opt/z-card-recognize/ |
通过使用.dockerignore
文件,你可以控制复制中忽略的文件和目录。
比如.dockerignore
1 | *.log |
COPY 和 ADD 的区别
在Dockerfile中,ADD
和COPY
是两个用于将文件和目录从宿主机复制到Docker镜像中的指令。尽管它们看起来很相似,但在使用和功能上有一些显著的区别。
COPY
指令
COPY
是最常用的指令之一,它将文件或目录从宿主机的路径复制到Docker镜像中的指定路径。
语法:
1 | COPY <源路径> <目标路径> |
<源路径>
:宿主机上的文件或目录的路径。<目标路径>
:镜像中的目标路径。
特点:
COPY
只支持基本的文件和目录复制功能。COPY
不会自动解压文件。COPY
更适合复制本地文件和目录到镜像中。
示例:
1 | COPY app.py /app/ |
ADD 指令
ADD
指令的功能比COPY
更强大,但同时也更复杂。
它不仅可以复制文件和目录,还可以处理远程URL和自动解压tar文件。
语法:
1 | ADD <源路径> <目标路径> |
<源路径>
:可以是宿主机上的文件或目录的路径,也可以是一个URL(远程文件)。<目标路径>
:镜像中的目标路径。
特点:
ADD
可以处理远程URL和自动解压tar文件。
- 如果
<源路径>
是一个URL,ADD
会下载文件并将内容放置在<目标路径>
。 - 如果
<源路径>
是一个本地的tar文件(支持gzip、bzip2、xz格式),ADD
会自动将其解压到<目标路径>
。
ADD
的复杂性使得它不如COPY
透明,建议在不需要远程URL或自动解压功能时使用COPY
。
示例:
1 | ADD https://example.com/file.tar.gz /tmp/ |
总结
使用COPY
:
- 当你只需要简单地将本地文件或目录复制到镜像中时,使用
COPY
。 COPY
是更明确的指令,有助于保持Dockerfile的清晰和易读。
使用ADD
:
- 当你需要从远程URL下载文件或自动解压tar文件时,使用
ADD
。 - 建议仅在需要
ADD
的特殊功能时使用,因为它可能会引入不必要的复杂性。
在大多数情况下,COPY
是更好的选择,因为它更简单、更透明,并且更容易预测其行为。
整体示例
NodeJS项目
Dockerfile
1 | LABEL maintainer="psvmc <psvmc@outlook.com>" |
如果build_debug.sh
构建的时候进度不动,可以把
1 | RUN cd /data/school_live_record/record && chmod +x /data/school_live_record/record/build_debug.sh && /data/school_live_record/record/build_debug.sh |
替换为
1 | ADD agorasdk.node /data/school_live_record/record/agorasdk.node |
把别的服务器上容器内的agorasdk.node
放在Dockerfile
同级
Python项目
1 | # Pull base image |
构建运行
构建
1 | docker build -t psvmc/z-card-recognize . |
如果构建一直失败可以禁用缓存
1 | docker build --no-cache -t psvmc/z-card-recognize . |
运行
1 | docker run -d -p 8000:8000 --name z-card-recognize --restart=always psvmc/z-card-recognize |
查看启动日志
1 | docker logs z-card-recognize |
删除
1 | docker stop z-card-recognize |
删除中间镜像
在 Docker 中,有时候会存在一些没有标签的镜像(即 REPOSITORY
和 TAG
都是 <none>
的镜像),这些镜像通常是构建过程中产生的中间镜像或者是没有正确打标签的镜像。
删除这些镜像可以帮助清理 Docker 环境并减少磁盘空间占用。
查看所有镜像
首先,使用以下命令查看所有镜像:
1 | docker images -a |
您会看到类似以下的输出:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
删除所有 <none>
镜像
您可以使用以下命令删除所有 REPOSITORY
和 TAG
都是 <none>
的镜像:
方法 1:使用 docker rmi
1 | docker rmi $(docker images -f "dangling=true" -q) |
解释:
docker images -f "dangling=true"
:过滤出所有没有标签的镜像(即 dangling 镜像)。-q
:只显示镜像的 ID。docker rmi
:删除指定 ID 的镜像。
方法 2:使用 docker image prune
1 | docker image prune -f |
解释:
docker image prune
:删除未使用的镜像。-f
或--force
:强制执行,不需要确认。
注意事项
docker image prune -f
会删除所有未被容器使用的 dangling 镜像,因此请确保没有其他容器在使用这些镜像。- 如果您只想删除特定镜像,可以使用镜像的 ID 直接删除:
1 | docker rmi <IMAGE_ID> |
其他清理操作
如果您需要清理更多未使用的 Docker 资源(如容器、网络、卷等),可以使用以下命令:
清理所有未使用的容器、网络、卷和镜像
1 | docker system prune -f |
清理未使用的卷
1 | docker volume prune -f |
通过这些步骤,您可以有效地清理 Docker 环境中的 <none>
镜像和未使用的资源,释放磁盘空间。