☰
Docker 学习笔记(原理、命令、Dockerfile、Nginx 镜像构建、面试热点)
2026/10/17 6:53:33 网站建设 项目流程

文章目录

    • 一、Docker原理
    • 二、Docker常用参数(docker run)
      • docker ps(查看容器)
      • docker exec(进入正在运行的容器)
    • 三、Dockerfile 参数详解
      • 3.1 基础指令
      • 3.2 镜像内执行操作指令
      • 3.3 容器运行相关(容器启动后生效,build 阶段不执行)
      • 3.4 启动命令(CMD / ENTRYPOINT 高频面试重点!)
      • 3.5 挂载相关
      • 3.6 其他指令
    • 四、Dockerfile构建nginx镜像实操
      • 4.1 编写 Dockerfile
      • 4.2 构建镜像
      • 4.3 查看已构建镜像
      • 4.4 运行镜像
      • 4.5 测试访问
      • 4.6 通过挂载方式启动容器
      • 4.7 测试挂载方式启动容器是否正常
    • 五、面试常考题
      • 5.1 为什么要用 Docker(面试简答)
      • 5.2 Docker 优缺点
      • 5.3 Dockerfile 关键面试坑点总结
      • 5.4 CMD 和 ENTRYPOINT 的区别?
      • 5.5 Docker镜像分层原理(高频面试)
        • 面试追问1:为什么要分层?
        • 面试追问2:容器删除,镜像层会消失吗?
        • 面试追问3:Dockerfile优化(分层优化考点)
      • 5.6 写时复制 CoW(Copy-on-Write)
        • 原理
        • 面试追问1:容器删除后,复制出来的文件会怎么样?
      • 5.7 容器生命周期管理
        • 重点区分面试考点
      • 5.8 什么是容器退出策略 --restart?4 种重启策略
        • 实操示例

一、Docker原理

Docker 底层依赖 Linux 内核三大技术:

  1. Namespace:实现进程、网络、文件系统等隔离
  2. Cgroups:限制 CPU、内存等资源
  3. UnionFS 联合文件系统:实现镜像分层、写时复制

容器本质是宿主机上一个被隔离和资源限制的进程,共享宿主机内核,所以相比虚拟机更加轻量。

二、Docker常用参数(docker run)

参数简要说明
-d–detach,后台守护运行容器
-i–interactive,保持标准输入打开
-t–tty,分配伪终端;-it组合进入交互式 shell
--name 容器名指定容器名称
--rm容器退出后自动删除容器(测试临时容器)
-p 宿主机端口:容器端口–publish,端口映射
-P–publish-all,自动随机宿主机端口,映射镜像 EXPOSE 端口
-v 宿主机路径:容器内路径–volume,挂载数据卷 / 绑定挂载
-e KEY=VAL–env,设置环境变量
--env-file xxx.env从文件批量导入环境变量
--restart重启策略:no/on-failure/always/unless-stopped
--network 网络名指定容器加入的 docker 网络
--tmpfs /目录内存临时文件系统,容器销毁数据丢失
--read-only容器根文件系统只读
--cpus N数量限制最大 CPU 核数
-m 512m–memory,限制最大内存
-w /path–workdir,设置容器内工作目录
-h hostname设置容器主机名
-u uid–user,指定容器运行用户,避免 root
--privileged特权容器,获取宿主机高权限,慎用

docker ps(查看容器)

参数简要说明
无参数查看正在运行的容器
-a–all,查看所有容器(包含已停止)
-q–quiet,只输出容器 ID
-f filter过滤,例-f name=mysql
--no-trunc不截断,显示完整容器 ID

docker exec(进入正在运行的容器)

参数简要说明
-i保持标准输入打开
-t分配伪终端,一般组合-it

三、Dockerfile 参数详解

Dockerfile 用来构建镜像,构建命令:docker build -t xxx:v1 .
规则:从上往下顺序执行;每一条指令生成一层镜像层;尽量合并指令减少层数;大写是规范(不强制,但约定俗成)。

3.1 基础指令

指令用法示例简单说明
FROMFROM mysql:8.0✅必须第一条,指定基础镜像。所有镜像都要有 FROM;FROM scratch代表空白镜像
MAINTAINERMAINTAINER zhangsan <xxx@163.com>维护者信息,已经废弃,推荐用 LABEL 替代
LABELLABEL author="test" version="v1"给镜像添加元数据标签,key=value;替代 MAINTAINER

3.2 镜像内执行操作指令

指令用法示例简单说明
RUNRUN apt update && apt install -y nginx在镜像构建阶段执行 Shell 命令;每一条 RUN 产生一层镜像;多条命令用&&合并,减少层数。
COPYCOPY ./index.html /usr/share/nginx/html/复制宿主机本地文件/目录到镜像内;只支持本地源;不会解压压缩包。
ADDADD test.tar.gz /opt/增强版 COPY:①本地文件复制;②自动解压 tar 压缩包;③支持远程 URL 下载文件;
✅日常优先用 COPY,需要解压才用 ADD。

3.3 容器运行相关(容器启动后生效,build 阶段不执行)

指令用法示例简单说明
WORKDIRWORKDIR /app设置容器内工作目录;目录不存在自动创建;等价cd,推荐替代RUN mkdir && cd
ENVENV TZ=Asia/Shanghai设置环境变量,镜像和启动后的容器都生效;可多条,构建和运行阶段都能用
EXPOSEEXPOSE 80 443声明容器要开放的端口,不是真正开放端口!仅文档说明,-p才是真正端口映射
USERUSER www指定容器运行的用户;后续 RUN/CMD/ENTRYPOINT 都会用这个用户,默认 root;安全最佳实践

3.4 启动命令(CMD / ENTRYPOINT 高频面试重点!)

指令用法示例简单说明
CMDCMD ["nginx","-g","daemon off;"]容器默认启动命令。✅ 可以被docker run 镜像 新命令覆盖
一个 Dockerfile只能最后一条 CMD 生效
ENTRYPOINTENTRYPOINT ["/bin/sh","-c"]容器入口程序。✅docker run后面跟的参数追加传给 entrypoint,不会覆盖
常用来做固定入口脚本

面试一句话区分:
CMD:默认命令,run 后面加参数直接替换 CMD;
ENTRYPOINT:固定入口,run 后面的参数是传给入口的参数。

3.5 挂载相关

指令用法示例简单说明
VOLUMEVOLUME ["/data/mysql"]声明数据卷。构建镜像时预先定义挂载点,容器启动自动创建匿名卷;
⚠️ Dockerfile 里 VOLUME不能指定宿主机路径,宿主机挂载路径只能在docker run -v指定

3.6 其他指令

指令用法示例简单说明
ARGARG VERSION=1.0构建阶段变量,只在docker build构建镜像时生效;容器运行时无效。build 时可通过--build-arg VERSION=2.0传参覆盖
HEALTHCHECKHEALTHCHECK --interval=20s --timeout=3s --retries=2 --start-period=10s \
CMD curl -fs http://localhost/
容器健康检查,周期性检测容器内应用可用性;docker ps可查看状态,分为starting/healthy/unhealthy,仅标记状态,不会自动重启容器
SHELLSHELL ["/bin/bash", "-c"]修改 RUN 指令默认使用的 shell 解释器

四、Dockerfile构建nginx镜像实操

4.1 编写 Dockerfile

FROM rockylinux:9 # 维护者信息 LABEL maintainer="test" # 安装编译环境和必要工具 RUN yum install -y gcc make gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel zlib zlib-devel wget curl # 获取 Nginx 源码 RUN wget https://nginx.org/download/nginx-1.29.0.tar.gz # 解压源码 RUN tar xf nginx-1.29.0.tar.gz # 配置 Nginx RUN cd nginx-1.29.0 && ./configure --prefix=/data/server/nginx # 编译并安装 RUN cd nginx-1.29.0 && make && make install # 定制首页 RUN echo "Nginx Web Page from RockyLinux" > /data/server/nginx/html/index.html # 暴露 HTTP 端口 EXPOSE 80 # 健康检查(已注释,可选) # interval: 检测间隔 20s;timeout 单次超时 3s;retries 连续失败 2 次标记 unhealthy #HEALTHCHECK --interval=20s --timeout=3s --retries=2 --start-period=10s \ # CMD curl -fs http://127.0.0.1/ || exit 1 # 设置容器启动命令 ENTRYPOINT ["/data/server/nginx/sbin/nginx", "-g", "daemon off;"]

4.2 构建镜像

dockerbuild-tnginx-test:1.29.0.

4.3 查看已构建镜像

docker images

输出示例:

REPOSITORY TAG IMAGE ID CREATED SIZE nginx-test 1.29.0 0a0a482642a7 10 seconds ago 1.04GB

4.4 运行镜像

docker run -itd --name nginx-test -p 80:80 nginx-test:1.29.0

查看容器状态:

#docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9c2308bc017d nginx-test:1.29.0 "/data/server/nginx/…" 30 minutes ago Up 30 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx-test

4.5 测试访问

浏览器访问:http://服务器 IP,即可看到自定义 Nginx 页面。

4.6 通过挂载方式启动容器

cd /data/images/nginx/html/ 编写nginx静态页面 vim index.html 编辑内容如下 hello nginx docker run -itd --name nginx-test2 -p 80:80 -v /data/images/nginx/html/index.html:/data/server/nginx/html/index.html nginx-test:1.29.0

4.7 测试挂载方式启动容器是否正常

五、面试常考题

5.1 为什么要用 Docker(面试简答)

  • 解决环境不一致问题:开发、测试、生产依赖版本不同导致 bug。镜像打包全部依赖,环境统一。
  • 提升交付效率:打包镜像,一键部署,简化上线流程,适配 CI/CD 流水线。
  • 资源更省:对比虚拟机,更少内存、CPU 占用,单机可部署更多实例。
  • 快速启停,方便测试:练习环境(Redis 集群、LNMP、WordPress)一键启动,一键销毁重置。
  • 标准化:交付物是镜像,统一交付标准,不再交付源码 + 文档 + 一堆部署脚本。
  • 方便横向扩展:容器轻量,快速多副本部署,方便后续上 K8s。

一句话简括:Docker 可以把应用及其依赖打包为镜像,实现环境一致性;容器基于内核隔离,轻量快速,资源开销低,方便自动化部署、持续交付。

5.2 Docker 优缺点

✅优点:环境一致、轻量、快速启停、资源利用率高、便于 CI/CD、镜像可复用;

❌缺点:依赖宿主机内核,隔离性弱于虚拟机,有状态数据持久化需要卷管理。

5.3 Dockerfile 关键面试坑点总结

  1. RUN:构建镜像阶段执行;CMD/ENTRYPOINT:容器 run 启动时执行,构建阶段不运行。
  2. EXPOSE只是声明端口,不会真正开放端口,端口映射需要靠-p参数。
  3. ADD会自动解压 tar 包,COPY 不会;日常复制文件优先使用 COPY。
  4. VOLUME在 Dockerfile 内只能定义挂载点,不能写宿主机路径,宿主机挂载目录只能在docker run -v指定。
  5. ARG仅构建阶段有效;ENV构建 + 容器运行阶段都生效。

5.4 CMD 和 ENTRYPOINT 的区别?

答:CMD 是容器默认命令,docker run后面传命令会直接覆盖 CMD;ENTRYPOINT 是固定入口程序,docker run后面的参数会作为参数传给 ENTRYPOINT,不会覆盖入口程序。

5.5 Docker镜像分层原理(高频面试)

底层技术:联合文件系统 UnionFS

  1. 镜像由多层只读层叠加组成,每一条 Dockerfile 指令都会生成一层只读镜像层。
  2. 只读层:镜像本身所有层都是只读,容器启动时,会在镜像最上层额外添加一层可读写容器层。
  3. 写时复制(CoW,Copy-on-Write):
    • 当容器需要修改文件时,不会改动底层只读镜像;
    • 会把文件从只读层复制到顶层可读写层,在副本上做修改;底层原始文件保持不变。
  4. 层复用:构建镜像时,如果某一层内容不变,Docker 会直接复用缓存,加快构建速度。

✅ 一句话简答(面试口述)
Docker 镜像基于 UnionFS 联合文件系统,由多层只读层堆叠而成;每条 Dockerfile 指令生成一层。容器启动时新增一层可读写层,采用写时复制 CoW 机制,修改文件只复制到上层读写层,底层镜像不变;相同层可以缓存复用,提升构建效率。

面试追问1:为什么要分层?
  • 复用镜像层,减少存储空间,多个镜像共用基础层,不用重复保存;
  • 构建缓存:Docker build 会缓存每一层,修改 Dockerfile 某一行时,只重新构建后面的层,大幅加快构建速度;
  • 方便版本管理,镜像可以逐层增删。

延伸知识点:不使用缓存构建镜像(实操)
参数 --no-cache

dockerbuild --no-cache-tnginx-test:1.29.0.
面试追问2:容器删除,镜像层会消失吗?

不会。容器删除,只会删除容器最上层的读写层,底层所有只读镜像层仍然保留,镜像不会被删除。

面试追问3:Dockerfile优化(分层优化考点)
  1. 合并 RUN 指令,减少镜像层数(多条命令用&&连接,避免每一条 RUN 生成一层)
  2. 把变动频繁的指令放 Dockerfile 靠后位置(比如 COPY 业务代码放后面,基础依赖放前面,更好利用缓存)
  3. 清理临时文件在同一个 RUN 层内,不要分开写,否则删除操作会新增一层,镜像体积不会变小

错误示例:

RUN wget xxx.tar.gz RUN rm xxx.tar.gz

上面写法,下载的压缩包还留在上一层,删不掉,镜像体积无法减小。
正确写法:

RUN wget xxx.tar.gz && rm xxx.tar.gz

5.6 写时复制 CoW(Copy-on-Write)

属于镜像分层的核心考点,全称:Copy on Write,写时复制。

原理

Docker 镜像所有层都是只读。
容器启动的时候,会在镜像堆叠的最顶层新增一层可读写容器层。

  • 读取文件:直接从下层只读镜像层读取;
  • 修改/新增文件:
    1. 当容器要修改底层只读层里的文件,不会直接修改底层镜像;
    2. Docker 先把这个文件复制一份,放到顶层可读写层;
    3. 在复制出来的副本上做修改;底层原始文件保持原样不变。

✅ 一句话口述答案(面试背诵)
CoW写时复制:镜像全部是只读层。容器修改文件时,不会改动底层镜像,而是把文件复制到容器读写层,在副本上修改,底层镜像保持不变。

面试追问1:容器删除后,复制出来的文件会怎么样?

容器删除,顶层读写层直接销毁,里面所有复制修改过的文件全部清除,底层镜像不受任何影响。
除非使用-v挂载(绑定挂载或数据卷)的数据保存在宿主机,不属于容器读写层,销毁容器不会自动删除数据;但是匿名卷如果执行docker rm -v会被一起删除。


5.7 容器生命周期管理

容器一共有 5 个核心状态:

  1. created(已创建):docker create创建容器,镜像文件层准备完成,未启动。只是容器元数据创建,进程没运行。
  2. running(运行中):docker start / docker run,容器内主进程正常运行。
  3. paused(暂停):docker pause,暂停容器内所有进程(cgroup 冻结进程,进程保留内存,不退出);docker unpause恢复。
  4. stopped(停止):docker stop优雅停止(发 SIGTERM,等待超时后 SIGKILL) /docker kill强制 SIGKILL。主进程退出,容器文件与元数据保留。
  5. deleted(已删除):docker rm删除容器,容器所有资源被清理,不能恢复。

状态流转简图:
create→ created →start→ running
running →pause→ paused →unpause→ running
running →stop/kill→ stopped →rm→ deleted

补充:docker run = docker create + docker start

重点区分面试考点
  • docker stop:优雅关闭,先发 SIGTERM (15) 信号给容器主进程,默认等待 10s;超时没退出,再发送 SIGKILL (9) 强制杀死。
  • docker kill:直接发送 SIGKILL (9),强制杀死进程,不会等待。

核心结论:容器生命周期由容器PID=1 的主进程控制:PID1 进程退出,容器直接进入 stopped 状态。

5.8 什么是容器退出策略 --restart?4 种重启策略

--restart控制容器退出时,Docker 引擎是否自动重启容器。

  1. no(默认):容器退出永远不重启
  2. on-failure:只有异常退出(ExitCode≠0)才重启;正常退出不重启。可加最大次数on-failure:3最多重试 3 次
  3. always:无论正常 / 异常退出,总是重启;Docker 守护进程重启,容器也跟着启动
  4. unless-stopped:和 always 类似,但如果人工手动 stop 容器,之后 Docker 重启也不会自动拉起
实操示例

示例说明:创建 nginx 容器,演示不同 --restart 参数用法

# 1. 默认 no 策略(不写--restart即为no)dockerrun-itd--namenginx-test-p80:80 nginx:1.29.0# 2. on-failure 策略,最多重试3次dockerrun-itd--namenginx-test-p80:80--restarton-failure:3 nginx:1.29.0# 3. always 策略dockerrun-itd--namenginx-test-p80:80--restartalways nginx:1.29.0# 4. unless-stopped 策略dockerrun-itd--namenginx-test-p80:80--restartunless-stopped nginx:1.29.0

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询