在本篇文章中,我们将带你认识 Dockerfile —— 构建 Docker 镜像的"蓝图"。我们会介绍它的基本概念和常用指令,帮助你理解如何使用它来打包你的应用。

简单了解 Docker(背景知识)

在我们深入 Dockerfile 之前,简单回顾一下几个核心概念:

  • Docker 是什么?想象一下集装箱:无论里面装什么货物(代码、库、配置),集装箱本身(Docker)都能让货物在任何港口(任何机器环境)轻松装卸和运行。Docker 就是这样一个能打包、发布和运行应用程序的平台。
  • 容器 (Container) 是什么?它是一个运行起来的、包含了应用及其所有依赖的标准化单元。你可以把它看作一个轻量级的、隔离的"小虚拟机"。
  • 镜像 (Image) 是什么?它是创建容器的只读模板或"快照"。Dockerfile 就是用来定义如何构建这个镜像的说明书。

对中小企业的好处:使用 Docker 可以帮助团队实现开发、测试、生产环境的一致性,减少"在我电脑上明明是好的"这类问题,加快应用上线速度,并更有效地利用服务器资源。

Dockerfile 是什么?

Dockerfile 本质上是一个文本文件,里面包含了一系列的指令 (Instructions)和参数。每一条指令描述了在构建镜像过程中的一个步骤,例如:需要哪个基础环境、要安装什么软件、拷贝哪些文件进去、容器启动时要运行什么命令等等。

Dockerfile 的基本规则:

  • 指令不区分大小写,但推荐使用大写,更清晰。
  • 使用#开头的行是注释。
  • 通常,Dockerfile 的第一条指令是FROM,指定基础镜像。
  • 每一条指令都会在镜像中创建新的一层 (Layer)。

一个典型的 Dockerfile 结构可能包含:

  1. 基础镜像信息:使用FROM指令指定依赖的基础镜像。
  2. (可选) 维护者信息:使用LABEL指令添加元数据。
  3. 镜像构建指令:使用RUN,COPY,ADD等指令来安装软件、复制文件等。
  4. 容器启动指令:使用CMD,ENTRYPOINT等指令指定容器启动时执行的命令。

Dockerfile 常用指令详解

下面我们来逐一了解一些最常用的 Dockerfile 指令:

FROM

用途:指定构建新镜像所依赖的基础镜像。必须是 Dockerfile 的第一条非注释指令。

格式:

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

示例:

# 使用官方的 Ubuntu 最新版作为基础镜像
FROM ubuntu:latest
# 使用特定版本的 Alpine Linux 作为基础镜像,并给这个阶段命名为 builder
FROM alpine:3.18 AS builder

中小企业提示:选择基础镜像很重要!尽量选择官方、受信任且体积小的镜像(如alpine、debian-slim),可以显著减小最终镜像的大小,加快下载和部署速度,并减少安全风险。

LABEL

用途:为镜像添加元数据 (Metadata),如版本号、描述、作者等。这些信息不会影响镜像功能,但有助于管理和识别镜像。

格式:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

示例:

LABEL version="1.0" description="我的第一个 Web 应用镜像" maintainer="Your Name <you@example.com>"

RUN

用途:在构建镜像过程中执行指定的命令。通常用于安装软件包、创建目录、编译代码等。

格式:

# Shell 格式 (简单命令推荐)
RUN <command># Exec 格式 (官方推荐,尤其适合包含空格或特殊字符的命令)
RUN ["executable", "param1", "param2"]

示例:

# 更新软件包列表并安装 Nginx (Shell 格式)
RUN apt-get update && apt-get install -y nginx
# 创建一个目录 (Exec 格式)
RUN ["mkdir", "/app"]

最佳实践:尽量将多个RUN命令合并成一条,使用&&连接。因为每条RUN指令会创建一个新的镜像层,合并命令可以减少层数,优化镜像体积和构建速度。同时,在安装包后清理缓存(如apt-get clean)也是个好习惯。

RUN apt-get update && \apt-get install -y --no-install-recommends software-properties-common && \apt-get clean && \rm -rf /var/lib/apt/lists/*

CMD

用途:指定容器启动时默认执行的命令。一个 Dockerfile 中只应有一个CMD指令,如果写了多个,只有最后一个会生效。

格式:

# Shell 格式
CMD command param1 param2# Exec 格式 (官方推荐)
CMD ["executable","param1","param2"]# 作为 ENTRYPOINT 的默认参数 (后面会讲)
CMD ["param1","param2"]

示例:

# 容器启动时运行 python server.py (Exec 格式)
CMD ["python", "server.py"]# 容器启动时执行 /bin/bash (Shell 格式)
CMD /bin/bash

注意:如果在docker run命令后面指定了其他命令,CMD指定的命令会被覆盖。

ENTRYPOINT

用途:配置容器启动时总是执行的命令。它与CMD类似,但更常用于将容器设置为一个"可执行程序"。

格式:

# Shell 格式
ENTRYPOINT command param1 param2# Exec 格式 (官方推荐)
ENTRYPOINT ["executable", "param1", "param2"]

ENTRYPOINT和CMD的配合使用:

  • 如果只用ENTRYPOINT(Exec 格式),docker run命令行后面的参数会追加到ENTRYPOINT命令之后。
  • 如果同时使用ENTRYPOINT(Exec 格式) 和CMD(Exec 格式,且CMD提供的是参数列表),CMD的内容会作为ENTRYPOINT的默认参数。如果在docker run时提供了参数,则会覆盖CMD提供的默认参数。
    示例:
# Dockerfile
ENTRYPOINT ["ls"]
CMD ["-a"]# 运行 `docker run <image>` 时,实际执行 `ls -a`
# 运行 `docker run <image> -l` 时,实际执行 `ls -l` (-l 覆盖了 CMD 的 -a)
何时使用?如果你想让容器表现得像一个固定的可执行文件,并且允许用户传递参数给这个文件,那么ENTRYPOINT(Exec 格式) +CMD(参数格式) 是常用模式。如果只是想提供一个默认的启动命令,且允许用户完全替换它,那么单独使用CMD更简单。

EXPOSE

用途:声明容器在运行时计划监听的网络端口。这并不会自动将端口发布到主机,它更像是一个文档记录和元数据,告诉使用者这个容器打算使用哪个端口。

格式:

EXPOSE <port> [<port>/<protocol>...]
示例:# 声明容器将监听 80 端口 (默认 TCP)
EXPOSE 80# 声明容器将监听 80/tcp 和 443/tcp 端口
EXPOSE 80/tcp 443/tcp

注意:要想从主机访问容器的这个端口,你仍然需要在docker run时使用-p或-P参数来做端口映射。例如:docker run -p 8080:80 将主机的 8080 端口映射到容器的 80 端口。

VOLUME

用途:创建一个挂载点,用于持久化存储数据或在容器间共享数据。它可以将主机的目录或 Docker 管理的卷挂载到容器内的指定路径。

格式:

VOLUME ["<path1>", "<path2>"...]
VOLUME <path>

示例:

# 声明 /data 目录用于存储持久化数据VOLUME ["/data"]# 声明 /app/config 和 /app/logs 用于挂载配置和日志
VOLUME /app/config /app/logs

注意:VOLUME指令创建的挂载点,其数据默认不会包含在镜像中,并且在容器删除后,Docker 管理的卷通常仍然存在(除非显式删除)。这使得数据可以在容器生命周期之外保持不变。在docker run时,可以使用-v参数将主机目录或命名卷挂载到这里。

COPY

用途:将构建上下文(通常是 Dockerfile 所在的目录及其子目录)中的文件或目录复制到镜像内的指定路径。

格式:

COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"] # 路径含空格时推荐

示例:

# 将当前目录下的 app.py 文件复制到镜像的 /app/ 目录下
COPY app.py /app/# 将当前目录下的 config 目录复制到镜像的 /etc/myapp/config/ 目录下
COPY config/ /etc/myapp/config/

最佳实践:

  • 只复制你需要的文件和目录,避免将不必要的文件(如.git目录、临时文件)复制进镜像。可以使用.dockerignore文件来排除它们。
  • 相比ADD,COPY的行为更明确(只复制本地文件),通常是首选。

ADD

用途:与COPY类似,但功能更强大:

  1. 可以复制本地文件/目录到镜像。
  2. 如果源是一个URL,它会尝试下载文件并复制到。
  3. 如果源是一个本地的tar 压缩包(如.tar.gz,.tar.bz2,.tar.xz),它会自动解压到。
    格式:与COPY相同。

示例:

# 下载一个文件并放到 /tmp/
ADD https://example.com/file.zip /tmp/# 复制本地的 myapp.tar.gz 并自动解压到 /usr/src/
ADD myapp.tar.gz /usr/src/

注意:由于ADD的行为(特别是自动解压和下载)有时不够透明和可控,官方更推荐:

  • 复制本地文件/目录:使用COPY。
  • 下载文件:使用RUN wget或RUN curl,这样更清晰,且可以在同一步骤中进行解压、清理等操作。

ENV

用途:设置环境变量。这些变量在后续的RUN指令中可用,并且在容器运行时也会保留。

格式:

ENV <key>=<value> ...
ENV <key> <value> # 旧格式,不推荐

示例:

# 设置应用版本和工作目录
ENV APP_VERSION="1.0" WORK_DIR="/app"# 在后续指令中使用环境变量
WORKDIR $WORK_DIR
RUN echo "Building version $APP_VERSION" > version.txt

注意:使用ENV设置的环境变量会持久存在于镜像和容器中。如果只是想在构建过程中临时使用变量,应该考虑使用ARG。

ARG

用途:定义构建时变量。这些变量只在docker build过程中有效,容器运行时不可用(除非用ENV重新定义)。可以通过docker build --build-arg =来传递值。

格式:

ARG <name>[=<default value>]

示例:

# 定义一个构建时参数 USER,默认值为 guest
ARG USER=guest# 定义一个没有默认值的参数 PASSWORD
ARG PASSWORDRUN useradd $USER
# RUN echo "Password is $PASSWORD" # 可以在构建时使用# 如果希望构建参数在容器中也可用,可以结合 ENV
ARG APP_PORT=8080
ENV PORT=$APP_PORT
EXPOSE $PORT
构建时传递参数:# 传递 USER 参数
docker build --build-arg USER=admin -t myimage .# 同时传递 USER 和 PASSWORD 参数
docker build --build-arg USER=admin --build-arg PASSWORD=secret -t myimage .

何时使用?当你需要根据不同的构建环境(如开发、测试、生产)传入不同的配置(如代理服务器地址、特定版本号),或者不想将敏感信息(如密码、token)硬编码到 Dockerfile 或ENV中时,ARG是很好的选择。

WORKDIR

用途:设置后续RUN,CMD,ENTRYPOINT,COPY,ADD指令的工作目录。如果指定的目录不存在,它会自动创建。

格式:

WORKDIR /path/to/workdir

示例:

WORKDIR /app# 下面的 COPY 和 RUN 都在 /app 目录下执行
COPY . .
RUN pip install -r requirements.txtWORKDIR /data
# 现在工作目录切换到了 /data# 可以使用相对路径
WORKDIR /app
WORKDIR sub-dir # 现在的工作目录是 /app/sub-dir
RUN pwd # 输出 /app/sub-dir

最佳实践:推荐使用绝对路径,并尽量在 Dockerfile 开头就设置好主要的工作目录,避免在根目录 (/) 下执行过多操作。

以上就是 Dockerfile 中一些最核心、最常用的指令。理解并熟练运用它们,是编写高效、规范 Dockerfile 的基础。
你也可以查阅Docker 官方文档获取更全面的指令列表和详细信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/86306.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/86306.shtml
英文地址,请注明出处:http://en.pswp.cn/web/86306.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

技术伦理之争:OpenAI陷抄袭风波,法院强制下架宣传视频

在AI巨头OpenAI宣布以65亿美元天价收购苹果前设计总监Jony Ive的硬件公司IO仅一个月后&#xff0c;一场抄袭指控将这家科技明星企业推上风口浪尖。 源自谷歌X实验室的初创企业IYO将OpenAI告上法庭&#xff0c;指控其窃取智能耳塞核心技术&#xff0c;并通过巨额收购试图掩盖抄袭…

前沿解读:缺陷如何操控二维半导体中的电子摩擦耗散超快动力学

摩擦能耗约占全球一次能源损耗的1/3&#xff0c;在微纳器件中尤为突出。二维半导体&#xff08;如WS₂&#xff09;因其独特的电子特性成为研究热点&#xff0c;但电子摩擦的动态机制因电子行为的超快特性长期难以捕捉。近期清华团队在Nature Communications发表的研究[1]&…

什么是物联网 (IoT)?

你家是否安装了智能恒温器&#xff1f;或者你属于三分之一的美国健身追踪器用户&#xff0c;通过设备记录运动习惯&#xff1f;如果是&#xff0c;你已在使用物联网技术。这项技术不仅融入日常生活&#xff0c;更深刻改变着组织的运营方式。物联网通过多种技术连接数字与物理世…

[特殊字符] Windows 查看端口占用及服务来源教程(以 9018 端口为例)

下面是一份详细的 Windows 系统中排查 某端口&#xff08;如 9018&#xff09;被哪个程序占用 并确定其具体服务来源的完整教程&#xff0c;适合用于日常运维、开发部署排障等场景。 &#x1f3af; Windows 查看端口占用及服务来源教程&#xff08;以 9018 端口为例&#xff09…

异步爬虫 原理与解析

先遍历100遍一个程序 import requests import logging import timelogging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s: %(message)s) TOTAL_NUMBER 100 BASE_URL https://ssr4.scrape.center/start_time time.time() for id in range(1,TOTAL_NUM…

vscode管理go多个版本

#1.下载go安装包 https://developer.aliyun.com/mirror/golang/?spma2c6h.25603864.0.0.55ea7c45IsI4GM # 2.创建 sdk 目录&#xff08;如果不存在&#xff09; mkdir -p ~/sdk # 3.解压下载的 go1.16.15 到 ~/sdk/ tar -C ~/sdk -xzf go1.16.15.linux-amd64.tar.gz # 4.重…

香港维尔利健康科技集团推出AI辅助医学影像训练平台,助力医护人才数字化转型

香港维尔利健康科技集团近日正式发布其自主研发的“AI辅助医学影像训练平台&#xff08;V-MedTrain&#xff09;”&#xff0c;这一创新平台的上线&#xff0c;标志着医学影像教育迈入智能化辅助教学新时代。依托人工智能与大数据分析技术&#xff0c;香港维尔利健康科技集团在…

互联网+医疗,医疗服务的全方位革新

近年来&#xff0c;互联网医疗行业迅速崛起&#xff0c;为医疗健康服务带来了翻天覆地的变革。新模式、新业态层出不穷&#xff0c;不仅大幅提升了医疗健康服务的可及性&#xff0c;也使得群众就医体验更为舒适、便捷。互联网技术的广泛应用&#xff0c;不仅改变了医疗核心业务…

酒店智能门锁系统常见问题解决方法——东方仙盟

重做系统后 usb发卡器与注册时发卡器不一致 解决发方法: 用总卡重新注册软件,要可以开房间的总卡 房号不存在 2声---正确提示&#xff0c;表示是设置卡 3声---门锁已反锁&#xff0c;解决方法&#xff1a;用能开反锁的卡或解除反锁 6声---房号不对&#xff0c;解决方法&#…

从零开始理解百度语音识别API的Python实现

大家好&#xff01;今天我要给大家详细讲解一个使用百度语音识别API的Python代码。这个代码可以将音频文件转换成文字&#xff0c;非常适合做语音转文字的应用。我会从最基础的概念开始讲起&#xff0c;确保没有任何编程基础的朋友也能理解。 翻译 一、代码概览 这段代码主要…

中小企业适用的几种会议签到工具

对企业行政来说&#xff0c;会议签到是件小事&#xff0c;但处理不好&#xff0c;会直接拖慢会议流程、影响管理效率、降低参会体验。尤其是面对人数多、时间紧、场地临时变动等情况&#xff0c;靠传统纸笔或简单Excel管理&#xff0c;往往应对乏力。 实际上&#xff0c;签到看…

android 11.0 打开ALOGV ALOGI ALOGD日志输出的方法

1.前言 在11.0的系统rom定制化开发中,在某些时候,需要打印ALOGV,ALOGI等TAG日志,在系统中,默认是关闭这些日志的, 防止日志打印过多,系统过于卡顿,但是有时候会为了调试,需要打开日志开关,所以就需要在系统源码中查看哪里 需要打开日志的开关,来实现日志的打印解决…

语言大模型or时序大模型?原理、应用与未来发展

引言 随着人工智能技术的飞速发展&#xff0c;大规模预训练模型已成为当前研究的热点。其中&#xff0c;语言模型和时序大模型作为两类重要的模型架构&#xff0c;分别在自然语言处理和时间序列分析领域展现出卓越的性能。然而&#xff0c;这两类模型在基本原理和应用场景上存…

【Excel数据分析】花垣县事业单位出成绩了,用Excel自带的M语言做一个数据分析

这里写自定义目录标题 花垣县事业单位出成绩了&#xff0c;用Excel自带的M语言做一个数据分析需求 花垣县事业单位出成绩了&#xff0c;用Excel自带的M语言做一个数据分析 Power Query M 语言&#xff0c;简称 M 语言&#xff0c;全名叫 Power Query Formula Language。 需求…

微处理器原理与应用篇---音频采集与串口传输功能的系统设计

这段内容是基于 STM32F407VGT6 单片机&#xff0c;实现音频采集与串口传输功能的嵌入式系统设计方案&#xff0c;包含硬件架构、软件逻辑和代码实现&#xff0c;核心是通过 ADC 采集音频、串口收发指令与数据 &#xff0c;以下分模块拆解&#xff1a; 一、系统设计概述 硬件&…

【大模型学习 | 量化】pytorch量化基础知识(1)

pytorch量化 [!note] 官方定义&#xff1a;performing computations and storing tensors at lower bitwidths than floating point precision.支持INT8量化&#xff0c;可以降低4倍的模型大小以及显存需求&#xff0c;加速2-4倍的推理速度通俗理解&#xff1a;降低权重和激活值…

ES和 Kafka 集群搭建过程中的典型问题、配置规范及最佳实践

Kafka 集群搭建与配置经验库文档&#xff08;完整会话汇总&#xff09; 一、会话问题分类与解决方案 1. Elasticsearch 映射解析错误 问题现象&#xff1a; {"error":{"root_cause":[{"type":"mapper_parsing_exception","re…

Linux-信号量

目录 POSIX信号量 信号量的原理 信号量的概念 申请信号量失败被挂起等待 信号量函数 二元信号量模拟实现互斥功能 基于环形队列的生产消费模型 下面环形队列采用数组模拟&#xff0c;用模运算来模拟环状特性&#xff0c;类似如此 空间资源和数据资源 生产者和消费者申请…

Unity2D 街机风太空射击游戏 学习记录 #14 环射和散射组合 循环屏幕道具

概述 这是一款基于Unity引擎开发的2D街机风太空射击游戏&#xff0c;笔者并不是游戏开发人&#xff0c;作者是siki学院的凉鞋老师。 笔者只是学习项目&#xff0c;记录学习&#xff0c;同时也想帮助他人更好的学习这个项目 作者会记录学习这一期用到的知识&#xff0c;和一些…

vue3 定时刷新

在Vue 3中实现定时刷新&#xff0c;你可以使用多种方法。这里列举几种常见的方法&#xff1a; 方法1&#xff1a;使用setInterval 这是最直接的方法&#xff0c;你可以在组件的mounted钩子中使用setInterval来定时执行某些操作&#xff0c;例如重新获取数据。 <template&…