在后端开发、运维、DevOps面试中,Docker是必考知识点,无论是初级工程师还是资深从业者,熟练掌握Docker的核心概念、常用操作、底层原理,都是面试加分项。本文整理了13道最常考的Docker面试题,每道题均补充详细解析、原理延伸、实战技巧及易错点,帮你吃透Docker核心知识,轻松应对各类面试场景,避免死记硬背,真正理解并灵活运用。
一、Docker 是什么?
这是Docker面试的开篇基础题,考察对Docker的核心定位、开发语言、核心价值的掌握,回答时需突出“开源”“容器引擎”“一次封装、到处运行”的核心标签,补充其诞生背景和实际价值,避免过于简洁。
答案解析:
Docker 是一个开源的应用容器引擎,由Docker Inc.公司开发维护,基于 Go 语言编写,遵循 Apache 2.0 开源协议,于2013年首次发布。它的核心目标是“解决应用部署的环境一致性问题”,让开发者能够轻松打包应用及其所有依赖(如库文件、配置、运行环境等),形成一个轻量级、可移植、自包含的容器,然后发布到任何支持Docker的主流Linux机器、Windows机器甚至云服务器上,实现“一次封装,到处运行”。
补充说明(面试加分点):
-
Docker诞生前的痛点:开发者在本地开发的应用,部署到测试环境、生产环境时,常出现“本地能跑,线上跑不起来”的问题,核心原因是不同环境的依赖、配置不一致,Docker通过容器化技术彻底解决了这一痛点。
-
Docker的核心优势:轻量级(比虚拟机体积小几个数量级)、可移植性强、启动速度快、资源占用低,同时支持隔离性,多个容器可在同一台宿主机上独立运行,互不干扰。
-
Docker与传统部署的区别:传统部署需要手动配置环境、安装依赖,而Docker只需打包一次容器,后续在任何支持Docker的环境中,只需运行容器即可,大幅提升部署效率,降低运维成本。
二、容器 vs 虚拟机(必问,高频重点)
这是Docker面试的核心必考题,考察对容器和虚拟机底层架构的理解,核心是区分两者的本质差异,回答时需从“虚拟化层级”“资源占用”“启动速度”“隔离性”等维度对比,结合通俗类比,让解析更易懂。
答案解析:
容器和虚拟机(VM)都是实现“环境隔离、资源隔离”的技术,但两者的底层架构、资源占用、启动速度差异极大,核心区别在于“是否虚拟硬件、是否拥有独立内核”,具体对比及详细说明如下:
1. 传统虚拟机(VM)的工作原理
传统虚拟机(如VMware、VirtualBox)是“硬件级虚拟化”,它会虚拟出一整套完整的硬件设备(包括CPU、内存、硬盘、网卡等),然后在虚拟硬件上安装一个完整的操作系统(如Windows、Linux),再在这个操作系统上安装和运行应用程序。
简单类比:虚拟机就像“在电脑里再装一台完整的电脑”,里面有独立的硬件、独立的系统,应用程序运行在这个“虚拟电脑”里,与宿主机(真实电脑)的系统完全隔离。
虚拟机的特点:
-
需要虚拟完整硬件,资源占用高(通常需要分配GB级内存、GB级存储空间);
-
启动速度慢(需要先启动完整的操作系统,通常需要几分钟);
-
隔离性极强(完全独立于宿主机,宿主机的环境变化不会影响虚拟机);
-
体积大(一个虚拟机镜像通常是几GB到几十GB)。
2. Docker容器的工作原理
Docker容器是“操作系统级虚拟化”,它不虚拟硬件,也没有自己的独立内核,而是直接共享宿主机的内核,容器内的应用程序直接运行在宿主机的内核上,相当于宿主机上的一个“隔离的进程”。
简单类比:容器就像“电脑里的一个独立文件夹”,里面装着应用程序和它需要的所有依赖,这个“文件夹”与其他“文件夹”(其他容器)互不干扰,但都共用电脑的操作系统和硬件资源。
容器的特点:
-
不虚拟硬件,共享宿主机内核,资源占用极低(通常只需要MB级内存、MB级存储空间);
-
启动速度快(进程级启动,无需启动完整操作系统,通常只需几秒甚至毫秒级);
-
隔离性较好(通过Linux的namespace、cgroups技术实现隔离,每个容器有自己的文件系统、网络空间,互不影响);
-
体积小(一个容器镜像通常是几十MB到几百MB);
-
可移植性强(依赖宿主机内核,只要宿主机支持Docker,容器就能运行,无需适配环境)。
核心区别总结(面试必背)
|
虚拟化层级 |
硬件级虚拟化 |
操作系统级虚拟化 |
|
是否有独立内核 |
有(每个虚拟机有自己的内核) |
无(共享宿主机内核) |
|
资源占用 |
高(GB级内存、存储) |
低(MB级内存、存储) |
|
启动速度 |
慢(几分钟) |
快(几秒/毫秒) |
|
隔离性 |
极强(完全独立) |
较好(进程级隔离) |
|
体积 |
大(几GB-几十GB) |
小(几十MB-几百MB) |
三、Docker 三大核心概念(必背)
这是Docker的基础核心知识点,考察对Docker核心组件的理解,回答时需明确每个概念的定义、作用、特点,补充实战场景,避免只记字面意思,让面试官看到你的实际应用认知。
答案解析:
Docker的整个生命周期,围绕“镜像、容器、仓库”三大核心概念展开,三者相互关联、缺一不可,具体说明如下:
1. 镜像(Image)—— 容器的“模板”
定义:镜像就是一个只读的模板,包含了运行应用程序所需的所有依赖(库文件、配置、运行环境、代码等),是创建Docker容器的基础。
核心特点:
-
只读性:镜像一旦创建,就无法修改,若需要修改,只能基于原镜像创建新的镜像(分层构建);
-
分层存储:镜像采用“联合文件系统(UnionFS)”分层存储,每一层都是只读的,不同镜像可以共享相同的层,大幅节省存储空间;
-
可复用性:一个镜像可以创建多个容器,多个容器可以共享同一个镜像的底层 layers,提升效率。
实战场景:我们从Docker Hub拉取的“nginx:latest”“mysql:5.7”,都是镜像;我们通过Dockerfile构建的,也是镜像。
2. 容器(Container)—— 镜像的“运行实例”
定义:容器是镜像的可运行实例,相当于“基于镜像模板启动的一个隔离进程”,它在镜像的只读层之上,增加了一个可写层,用于存储容器运行过程中产生的数据(如日志、配置修改、业务数据等)。
核心特点:
-
可启动、停止、重启、删除:容器是动态的,生命周期可管理;
-
可写层:容器运行过程中产生的所有数据,都存储在可写层中,若删除容器,可写层的数据会被删除(除非挂载数据卷);
-
隔离性:每个容器有自己的文件系统、网络空间、进程空间,与其他容器、宿主机互不干扰。
实战场景:通过“docker run nginx”命令,基于nginx镜像启动一个nginx容器,这个容器就是镜像的运行实例,我们可以在容器内部署web应用。
3. 仓库(Repository)—— 镜像的“存储仓库”
定义:仓库是用于存放Docker镜像的地方,相当于“镜像的网盘”,开发者可以将自己构建的镜像推送到仓库,也可以从仓库拉取别人分享的镜像。
核心分类:
-
公有仓库:公开可访问,最常用的是Docker Hub(Docker官方仓库,包含大量官方镜像和第三方镜像,如nginx、mysql、redis等),国内有阿里云容器仓库、腾讯云容器仓库等(拉取速度更快);
-
私有仓库:仅自己或团队可访问,通常用于企业内部,存放企业自研的应用镜像,避免敏感代码和配置泄露。
实战场景:通过“docker pull nginx”从Docker Hub拉取nginx镜像;通过“docker push 私有仓库地址/镜像名”,将自己构建的镜像推送到私有仓库,供团队内部使用。
三者关系总结(面试加分)
从仓库拉取镜像 → 基于镜像创建容器 → 容器运行应用;修改容器内的配置/代码后,可通过“docker commit”将容器打包成新的镜像,再推送到仓库,供其他人复用。
四、Docker 为什么快?(核心原理题)
这是考察Docker底层原理的高频题,回答时需围绕“内核共享”“启动层级”“存储机制”三个核心点展开,补充原理细节,避免只说表面现象,体现你的技术深度。
答案解析:
Docker之所以比传统虚拟机快,核心原因是它规避了虚拟机“虚拟硬件、启动完整操作系统”的繁琐流程,从内核、启动方式、存储三个层面优化,具体如下:
-
核心原因1:容器共享宿主机内核,无需启动完整操作系统 这是Docker最快的核心原因。传统虚拟机需要虚拟硬件,再启动一个完整的操作系统(如Linux),这个过程需要几分钟;而Docker容器不虚拟硬件,直接共享宿主机的Linux内核,容器内的应用程序直接运行在宿主机内核上,无需启动完整操作系统,节省了大量启动时间和资源。 补充:Docker容器只能运行在与宿主机内核兼容的系统上(如Linux宿主机只能运行Linux容器,Windows宿主机可运行Windows容器和Linux容器,需开启WSL2)。
-
核心原因2:容器是进程级启动,启动速度极快 传统虚拟机启动时,需要先启动操作系统的内核、系统服务,再启动应用程序,属于“系统级启动”;而Docker容器本质上是宿主机上的一个隔离进程,启动容器相当于启动一个进程,属于“进程级启动”,无需加载系统服务,启动时间通常只需几秒甚至毫秒级。 举例:启动一个nginx虚拟机可能需要3-5分钟,而启动一个nginx容器只需1-2秒。
-
核心原因3:联合文件系统(UnionFS),分层存储,复用层 Docker镜像采用联合文件系统分层存储,每一层都是只读的,不同镜像可以共享相同的底层 layers(如多个镜像都基于ubuntu镜像构建,它们可以共享ubuntu的底层 layers),无需重复存储,大幅节省存储空间;同时,启动容器时,只需在镜像的只读层之上添加一个可写层,无需复制整个镜像,进一步提升启动速度和效率。
补充:Docker的“快”不仅体现在启动速度,还体现在资源占用低——因为共享内核、无需虚拟硬件,一个宿主机可以同时运行上百个容器,而传统虚拟机只能运行几个,这也是Docker在高并发、微服务场景中广泛应用的原因。
五、Docker 常用命令(必背,实战题)
这是基础送分题,但考察的是“实战熟练度”,回答时需明确每个命令的作用、常用参数、实战场景,补充易错点,避免只罗列命令,让面试官看到你实际用过Docker。
答案解析:
Docker的常用命令主要分为“镜像操作”“容器操作”两大类,以下是面试高频命令,每一个都补充详细说明和实战示例:
1. 镜像相关命令(核心4个)
# 1. 搜索镜像(从仓库搜索镜像)
docker search 镜像名
# 示例:搜索nginx镜像
docker search nginx
# 说明:搜索结果中,STARS越多,镜像越受欢迎;OFFICIAL为OK的是官方镜像,更稳定
# 2. 拉取镜像(从仓库下载镜像到本地)
docker pull 镜像名:标签
# 示例1:拉取最新版nginx镜像(标签为latest,可省略)
docker pull nginx
# 示例2:拉取指定版本的mysql镜像(标签为5.7,不可省略)
docker pull mysql:5.7
# 说明:标签用于区分不同版本的镜像,若不指定标签,默认拉取latest(最新版)
# 3. 查看本地镜像
docker images
# 说明:输出结果包含镜像ID、仓库名、标签、大小,镜像ID是镜像的唯一标识
# 4. 删除本地镜像
docker rmi 镜像ID/镜像名:标签
# 示例1:通过镜像ID删除nginx镜像(镜像ID可只写前3-4位,唯一即可)
docker rmi 1234
# 示例2:通过镜像名+标签删除mysql镜像
docker rmi mysql:5.7
# 易错点:若镜像已创建容器,需先删除容器,再删除镜像;可加 -f 参数强制删除(不推荐)
docker rmi -f 镜像ID
2. 容器相关命令(核心8个)
# 1. 搜索镜像(从仓库搜索镜像)
docker search 镜像名
# 示例:搜索nginx镜像
docker search nginx
# 说明:搜索结果中,STARS越多,镜像越受欢迎;OFFICIAL为OK的是官方镜像,更稳定
# 2. 拉取镜像(从仓库下载镜像到本地)
docker pull 镜像名:标签
# 示例1:拉取最新版nginx镜像(标签为latest,可省略)
docker pull nginx
# 示例2:拉取指定版本的mysql镜像(标签为5.7,不可省略)
docker pull mysql:5.7
# 说明:标签用于区分不同版本的镜像,若不指定标签,默认拉取latest(最新版)
# 3. 查看本地镜像
docker images
# 说明:输出结果包含镜像ID、仓库名、标签、大小,镜像ID是镜像的唯一标识
# 4. 删除本地镜像
docker rmi 镜像ID/镜像名:标签
# 示例1:通过镜像ID删除nginx镜像(镜像ID可只写前3-4位,唯一即可)
docker rmi 1234
# 示例2:通过镜像名+标签删除mysql镜像
docker rmi mysql:5.7
# 易错点:若镜像已创建容器,需先删除容器,再删除镜像;可加 -f 参数强制删除(不推荐)
docker rmi -f 镜像ID
补充:面试时,若面试官让你演示“启动一个nginx容器并进入查看配置”,可直接说出完整命令,体现实战能力。
六、`docker run` 常用参数(必背,实战高频)
`docker run` 是Docker最核心的命令,其参数众多,面试常考高频参数,回答时需明确每个参数的作用、使用场景和示例,避免混淆参数含义(如 `-p` 和 `-P` 的区别)。
答案解析:
`docker run` 用于创建并启动容器,常用参数如下,每个参数均补充说明、示例,重点区分易混淆参数:
-
-d:后台运行容器(守护进程模式) 作用:容器启动后,不会占用当前终端,后台运行,适合长期运行的服务(如nginx、mysql)。 示例:后台启动nginx容器 docker run -d nginx 易错点:若不加 `-d`,容器会前台运行,关闭终端,容器就会停止。
-
-p:端口映射(宿主机端口:容器端口) 作用:将宿主机的端口映射到容器的端口,实现外部(宿主机/其他机器)访问容器内的服务。 示例:将宿主机的80端口映射到容器的80端口,外部访问宿主机80端口,即可访问容器内的nginx服务 docker run -d -p 80:80 nginx 补充:可映射多个端口,如同时映射80(http)和443(https)端口 docker run -d -p 80:80 -p 443:443 nginx
-
-P:随机端口映射 作用:Docker自动为容器的暴露端口(EXPOSE指定)分配一个宿主机的随机端口(范围通常是49153-65535),适合临时测试,无需手动指定端口。 示例:随机映射nginx的80端口 docker run -d -P nginx 查看映射的随机端口:用 `docker ps` 查看,PORTS列会显示“0.0.0.0:随机端口->80/tcp”。
-
–name:指定容器名称 作用:为容器起一个自定义名称,方便后续操作(如启动、停止、进入容器),避免用容器ID操作(不方便记忆)。 示例:指定容器名称为nginx-container docker run -d -p 80:80 –name nginx-container nginx 易错点:容器名称必须唯一,不能重复,否则会报错。
-
-v:挂载目录(数据卷挂载,宿主机目录:容器目录) 作用:将宿主机的目录挂载到容器内部,实现“数据持久化”(容器删除后,数据仍保存在宿主机目录),或“宿主机与容器共享数据”。 示例:将宿主机的/root/nginx/html目录,挂载到容器的/usr/share/nginx/html目录(nginx的静态资源目录) docker run -d -p 80:80 -v /root/nginx/html:/usr/share/nginx/html nginx 补充:挂载后,修改宿主机/root/nginx/html目录下的文件,容器内对应的目录会同步变化,无需进入容器修改。
-
–restart=always:容器开机自启 作用:宿主机重启后,容器会自动启动,适合需要长期运行的服务(如数据库、web服务),避免宿主机重启后,容器需要手动启动。 示例:启动nginx容器,设置开机自启 docker run -d -p 80:80 –restart=always nginx 补充:其他restart参数:no(默认,不自动重启)、on-failure(容器故障时自动重启)。
-
-e:设置环境变量 作用:向容器内部传递环境变量,用于配置容器内的应用(如数据库密码、端口等)。 示例:启动mysql容器,设置root用户密码为123456 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
实战组合示例(面试加分):启动一个nginx容器,要求后台运行、端口映射80:80、指定名称、挂载静态资源目录、开机自启。
docker run -d -p 80:80 –name nginx-container -v /root/nginx/html:/usr/share/nginx/html –restart=always nginx
七、Docker 数据卷(Volume)是什么?(实战重点)
这是考察Docker数据持久化的高频题,回答时需明确数据卷的定义、作用、核心优势,补充实战场景和常用命令,体现对数据持久化的理解(面试常结合“容器删除后数据丢失”的问题考察)。
答案解析:
Docker数据卷(Volume)是宿主机上的一个目录或文件,通过 `-v` 参数挂载到容器内部,相当于“宿主机和容器之间的一个共享文件夹”,核心作用是解决“容器删除后数据丢失”的问题,实现数据持久化。
1. 数据卷的核心作用(必背)
-
数据持久化:容器的可写层数据会随着容器删除而丢失,而数据卷挂载的是宿主机的目录/文件,容器内的数据会同步存储到宿主机,即使容器删除,宿主机上的数据依然存在,下次启动新容器时,可重新挂载该数据卷,恢复数据。 示例:mysql容器挂载数据卷,容器删除后,数据库数据仍保存在宿主机,重新启动mysql容器,挂载相同数据卷,即可恢复数据。
-
宿主机与容器共享数据:宿主机可以直接修改数据卷目录下的文件,容器内会同步生效;容器内修改的文件,宿主机也能看到,无需进入容器操作,提升效率。 示例:nginx容器挂载静态资源目录,宿主机直接修改html文件,容器内的web页面会实时更新。
-
多个容器共享数据:多个容器可以挂载同一个数据卷,实现数据共享,适合微服务场景(如多个服务共享配置文件、静态资源)。 示例:两个nginx容器挂载同一个宿主机目录,修改宿主机目录下的静态资源,两个容器的web页面都会同步更新。
2. 数据卷的核心优势
-
独立于容器生命周期:数据卷的生命周期不受容器影响,容器删除,数据卷依然存在;
-
性能高:数据卷直接挂载宿主机目录,无需经过Docker的分层文件系统,读写性能优于容器的可写层;
-
可管理性强:可以直接在宿主机上操作数据卷,方便备份、恢复、修改数据。
3. 数据卷常用命令(实战)
# 1. 创建数据卷(自定义数据卷,Docker会在宿主机/var/lib/docker/volumes目录下创建对应目录)
docker volume create my-volume
# 2. 查看所有数据卷
docker volume ls
# 3. 查看数据卷详细信息(如挂载路径)
docker volume inspect my-volume
# 4. 挂载自定义数据卷(推荐,比直接挂载宿主机目录更规范)
docker run -d -p 80:80 -v my-volume:/usr/share/nginx/html nginx
# 5. 删除数据卷(删除未被使用的数据卷)
docker volume rm my-volume
# 6. 删除所有未被使用的数据卷(实战常用,清理无用数据卷)
docker volume prune
补充:数据卷分为“自定义数据卷”和“绑定挂载”(直接挂载宿主机目录),生产环境中推荐使用自定义数据卷,管理更规范,避免因宿主机目录路径变化导致挂载失败。
八、Docker 网络模式(必问,核心难点)
这是Docker面试的核心难点题,考察对Docker网络隔离和通信的理解,回答时需明确四种常用网络模式的定义、作用、适用场景,补充实战示例,重点区分bridge(默认)和host模式,同时结合你提供的重要链接,补充关键知识点。
答案解析:
Docker默认提供四种网络模式,通过 `–net` 参数指定(如 `docker run –net=bridge nginx`),不同网络模式的隔离性、网络配置不同,适用于不同场景,具体说明如下:
1. bridge 模式(默认模式,最常用)
定义:Docker默认的网络模式,Docker会创建一个名为“docker0”的虚拟网桥,每个启动的容器都会被分配一个独立的IP地址(如172.17.0.2、172.17.0.3),容器通过docker0网桥与宿主机、其他容器通信。
核心特点:
-
容器有独立的网络空间,与宿主机、其他容器隔离;
-
需要通过 `-p` 端口映射,才能实现外部访问容器内的服务;
-
同一宿主机上的容器之间,可通过容器IP或容器名相互通信(需配置容器名解析)。
适用场景:大多数场景,如部署web服务、数据库服务,需要隔离性和端口映射,推荐使用bridge模式。
示例:默认启动nginx容器,就是bridge模式,通过 `-p 80:80` 映射端口,外部可访问。
2. host 模式(共享宿主机网络)
定义:容器不创建独立的网络空间,直接共享宿主机的网络栈(IP地址、端口、网卡等),容器内的服务直接使用宿主机的IP和端口,无需端口映射。
核心特点:
-
无网络隔离,容器与宿主机共享IP和端口;
-
无需端口映射,容器内的服务直接通过宿主机IP+端口访问;
-
性能高(无网络转发开销),但安全性和隔离性差。
适用场景:对网络性能要求高,且不需要隔离的场景,如内部测试、高性能服务(如消息队列)。
示例:启动nginx容器,使用host模式,容器内的80端口直接使用宿主机的80端口,外部访问宿主机IP:80即可。
docker run -d –net=host nginx
易错点:host模式下,容器内的端口不能与宿主机上其他服务的端口冲突,否则容器启动失败。
3. none 模式(无网络)
定义:容器不配置任何网络,没有IP地址,无法与宿主机、其他容器、外部网络通信,只有一个本地回环地址(127.0.0.1)。
核心特点:完全隔离网络,无法对外通信。
适用场景:不需要网络的场景,如仅用于本地计算、生成文件的容器(如数据处理脚本)。
示例:启动一个centos容器,使用none模式,无法ping通宿主机和外部网络。
docker run -it –net=none centos /bin/bash
4. container 模式(与另一个容器共享网络)
定义:容器不创建自己的网络空间,而是共享另一个已存在容器的网络空间,两个容器拥有相同的IP地址、端口,可直接通过localhost相互通信,相当于“两个进程共享一个网络”。
核心特点:
-
与指定容器共享网络,IP、端口相同;
-
无需端口映射,两个容器可通过localhost直接通信;
-
隔离性差,仅适用于特定场景。
适用场景:两个容器需要紧密通信,且不想暴露端口的场景,如一个容器运行应用,另一个容器运行日志收集服务,共享网络可直接获取应用日志。
示例:先启动一个nginx容器(名称为nginx-container),再启动一个centos容器,共享nginx-container的网络。
# 启动nginx容器
docker run -d –name nginx-container nginx
# 启动centos容器,共享nginx-container的网络
docker run -it –net=container:nginx-container centos /bin/bash
# 在centos容器内,可通过localhost:80访问nginx服务
重要补充:关于Docker网络的更详细配置(如自定义网络、跨宿主机容器通信),可参考阿里云官方文档:https://developer.aliyun.com/article/1688008,其中包含自定义网桥、网络模式实战配置等,面试时若被问到复杂网络场景,可提及该文档的知识点,体现你的学习能力。
九、Dockerfile 是什么?(核心实战题)
这是考察Docker镜像构建的基础题,回答时需明确Dockerfile的定义、作用、构建流程,补充实战场景,避免只说表面意思,体现你会用Dockerfile构建镜像。
答案解析:
Dockerfile 是一个用于构建Docker镜像的文本脚本文件,包含了一条条有序的指令(如指定基础镜像、安装依赖、拷贝文件、暴露端口等),每一条指令对应镜像的一层,Docker通过读取Dockerfile中的指令,自动构建出符合需求的镜像,无需手动操作容器、打包镜像。
核心作用
-
标准化镜像构建:通过Dockerfile,可明确镜像的构建步骤、依赖、配置,实现“一次编写,多次构建”,确保每次构建的镜像一致;
-
可复用、可维护:Dockerfile是文本文件,可版本控制(如提交到Git),方便团队协作、修改和复用;
-
自动化构建:可结合CI/CD工具(如Jenkins),实现镜像的自动构建、推送、部署,提升开发运维效率。
镜像构建流程(实战)
创建Dockerfile文件,编写构建指令;
进入Dockerfile所在目录,执行 `docker build` 命令,Docker会逐行执行Dockerfile中的指令,构建镜像;
构建完成后,通过 `docker images` 查看构建好的镜像;
通过 `docker run` 命令,基于构建好的镜像启动容器。
实战示例
创建一个简单的Dockerfile,构建一个基于centos的nginx镜像:
# Dockerfile内容
FROM centos:7 # 基础镜像
RUN yum install -y nginx # 安装nginx
EXPOSE 80 # 暴露80端口
CMD ["nginx", "-g", "daemon off;"] # 启动nginx
执行构建命令(注意末尾的“.”表示当前目录,指定Dockerfile所在路径):
docker build -t my-nginx:v1 .
说明:`-t` 参数用于指定镜像的名称和标签(my-nginx:v1),构建完成后,即可通过 `docker run -d -p 80:80 my-nginx:v1` 启动容器。
十、Dockerfile 常用指令(必背,实战重点)
这是考察Dockerfile编写能力的高频题,回答时需明确每个指令的作用、语法、使用场景,区分易混淆指令(如ADD和COPY、CMD和ENTRYPOINT),补充实战示例,体现你会编写Dockerfile。
答案解析:
Dockerfile的指令大小写不敏感,但约定俗成用大写(便于区分指令和参数),每条指令对应镜像的一层,常用指令如下,每一条均补充详细说明和示例:
# 1. FROM:指定基础镜像(必选指令,位于Dockerfile首行)
# 语法:FROM 镜像名:标签
# 说明:构建镜像必须基于一个基础镜像,基础镜像可以是官方镜像(如centos、nginx),也可以是自定义镜像
FROM centos:7 # 基于centos7构建镜像
FROM nginx:latest # 基于最新版nginx构建镜像
# 2. MAINTAINER:指定镜像作者(可选,已被LABEL替代,推荐用LABEL)
# 语法:MAINTAINER 作者信息
MAINTAINER "xxx@163.com"
# 推荐用法(LABEL):
LABEL maintainer="xxx@163.com"
# 3. RUN:构建镜像时执行的命令(常用指令)
# 语法1:RUN 命令(shell模式,相当于在终端执行命令)
# 语法2:RUN ["命令", "参数1", "参数2"](exec模式,更规范)
# 说明:每条RUN指令会创建一层镜像,建议合并多条RUN命令(减少镜像层数)
RUN yum install -y nginx # 安装nginx(shell模式)
RUN ["yum", "install", "-y", "nginx"] # exec模式
# 合并命令(推荐,用&&连接,减少镜像层数)
RUN yum update -y && yum install -y nginx && yum clean all
# 4. CMD:容器启动时执行的默认命令(可被命令行参数覆盖)
# 语法1:CMD 命令(shell模式)
# 语法2:CMD ["命令", "参数1", "参数2"](exec模式,推荐)
# 说明:一个Dockerfile只能有一个CMD指令,多个则只执行最后一个;启动容器时,可在命令行指定命令,覆盖CMD
CMD ["nginx", "-g", "daemon off;"] # 启动nginx(exec模式)
# 示例:启动容器时,覆盖CMD,执行/bin/bash
# docker run -it my-nginx:v1 /bin/bash
# 5. ENTRYPOINT:容器启动时执行的固定命令(不可被命令行参数覆盖)
# 语法1:ENTRYPOINT 命令(shell模式)
# 语法2:ENTRYPOINT ["命令", "参数1", "参数2"](exec模式,推荐)
# 说明:一个Dockerfile只能有一个ENTRYPOINT指令,多个则只执行最后一个;常与CMD配合使用(CMD作为ENTRYPOINT的参数)
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"] # CMD的参数会传递给ENTRYPOINT,相当于执行nginx -g "daemon off;"
# 6. EXPOSE:暴露容器的端口(声明式指令,不实际映射端口)
# 语法:EXPOSE 端口1 端口2
# 说明:仅用于声明容器运行时会使用的端口,方便开发者查看;实际映射端口仍需用-p参数
EXPOSE 80 443 # 声明容器暴露80(http)和443(https)端口
# 7. ENV:设置环境变量(可在Dockerfile中后续指令、容器内使用)
# 语法:ENV 变量名=变量值
# 说明:设置的环境变量,在容器内可通过echo $变量名查看,也可在后续RUN指令中使用
ENV MYSQL_ROOT_PASSWORD=123456 # 设置mysql密码
ENV PATH=/usr/local/nginx/sbin:$PATH # 设置环境变量PATH
# 8. ADD/COPY:拷贝文件到镜像中(核心区别:ADD可自动解压压缩包,COPY不能)
# 语法:ADD/COPY 宿主机文件/目录 镜像内目录
# COPY(推荐,仅拷贝文件,更安全)
COPY index.html /usr/share/nginx/html/ # 将宿主机的index.html拷贝到镜像的对应目录
# ADD(可解压压缩包)
ADD nginx.tar.gz /usr/local/ # 将宿主机的nginx.tar.gz拷贝到镜像,并自动解压
# 9. VOLUME:声明数据卷(指定容器内需要挂载的目录)
# 语法:VOLUME ["容器内目录1", "容器内目录2"]
# 说明:声明后,启动容器时,若未指定挂载目录,Docker会自动创建一个匿名数据卷,挂载到该目录
VOLUME ["/usr/share/nginx/html", "/var/log/nginx"] # 声明两个数据卷目录
# 10. WORKDIR:设置容器启动后的工作目录(后续指令如RUN、CMD、ENTRYPOINT会在该目录下执行)
# 语法:WORKDIR 目录路径
# 说明:若目录不存在,Docker会自动创建;可多次使用WORKDIR,切换工作目录
WORKDIR /usr/share/nginx/html # 设置工作目录
RUN echo "hello docker" > index.html # 在工作目录下创建index.html文件
补充:Dockerfile编写原则(面试加分):① 基础镜像选择体积小的(如alpine,比centos体积小很多);② 合并RUN指令,减少镜像层数;③ 删除无用缓存(如yum clean all、apt-get clean);④ 使用.dockerignore文件,排除不需要拷贝的文件(如日志、临时文件)。
十一、CMD vs ENTRYPOINT(必问,易混淆)
这是Dockerfile面试中最易混淆的考点,考察对两种启动指令的理解,回答时需明确两者的核心区别(是否可被覆盖),补充配合使用的场景和示例,让面试官看到你对指令的熟练掌握。
答案解析:
CMD和ENTRYPOINT都是Dockerfile中用于“指定容器启动时执行命令”的指令,两者的核心区别在于“是否可被命令行参数覆盖”,具体对比及详细说明如下:
1. CMD 指令
核心特点:可被命令行参数覆盖,是容器启动时的“默认命令”,若启动容器时在命令行指定了命令,则CMD指令会被覆盖,不执行。
示例:
# Dockerfile中设置CMD
FROM nginx
CMD ["nginx", "-g", "daemon off;"]
-
正常启动容器,执行CMD命令:docker run -d my-nginx,容器启动后执行 nginx -g "daemon off;";
-
启动容器时指定命令,覆盖CMD:docker run -it my-nginx /bin/bash,此时CMD指令被覆盖,容器启动后执行 /bin/bash,不会启动nginx。
2. ENTRYPOINT 指令
核心特点:不可被命令行参数覆盖,是容器启动时的“固定命令”,无论启动容器时是否指定命令,ENTRYPOINT指令都会执行,命令行参数会作为ENTRYPOINT的参数传递。
示例:
# Dockerfile中设置ENTRYPOINT
FROM nginx
ENTRYPOINT ["nginx"]
-
正常启动容器,执行ENTRYPOINT命令:docker run -d my-nginx,容器启动后执行 nginx(默认参数,可能后台运行,导致容器退出);
-
启动容器时指定参数,传递给ENTRYPOINT:docker run -d my-nginx -g "daemon off;",此时ENTRYPOINT执行 nginx -g "daemon off;",符合预期。
3. 两者配合使用(最常用场景)
实际开发中,常将ENTRYPOINT和CMD配合使用:ENTRYPOINT指定“固定命令”,CMD指定“默认参数”,这样既保证了容器启动时一定会执行固定命令,又可以通过命令行参数修改默认参数,灵活度更高。
实战示例:
# Dockerfile
FROM nginx
# ENTRYPOINT:固定启动nginx
ENTRYPOINT ["nginx"]
# CMD:默认参数,若命令行指定参数,会替换该参数
CMD ["-g", "daemon off;"]
-
正常启动:docker run -d my-nginx,执行 nginx -g "daemon off;"(ENTRYPOINT + CMD参数);
-
修改参数启动:docker run -d my-nginx -g "daemon off;" -c /etc/nginx/nginx.conf,执行 nginx -g "daemon off;" -c /etc/nginx/nginx.conf(CMD参数被替换)。




