基础概念
什么是Docker?
答:Docker是一个开源的容器化平台,它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中,从而在任何Docker运行的环境中实现一致的运行。
Docker容器和虚拟机的区别是什么?
答案:
| 特性 | 容器 | 虚拟机 |
|---|---|---|
| 虚拟化级别 | 操作系统级虚拟化 | 硬件级虚拟化 |
| 隔离性 | 进程级别隔离(较弱) | 完全隔离(更强) |
| 启动速度 | 秒级(非常快) | 分钟级(较慢) |
| 性能 | 接近原生性能 | 有性能损耗(约5-15%) |
| 资源占用 | 非常小(共享主机内核) | 较大(每个VM需要完整OS) |
什么是Docker镜像?
答:Docker镜像是一个轻量级、只读的模板,用于创建Docker容器。它包含运行容器所需的代码、库、环境变量和配置文件。
如何创建Docker容器?
答:可以使用docker run命令来从镜像创建容器。例如,docker run -d -p 80:80 nginx会基于nginx镜像启动一个新的容器,并将容器的80端口映射到宿主机的80端口。
Docker Hub是什么?
答:Docker Hub是一个公共的容器镜像仓库,可以用来存放、分享和管理Docker镜像。用户可以从Docker Hub下载公共镜像或上传自己的私有镜像。
docker容器有几种状态
docker容器4种状态:运行+已暂停+重新启动+已退出
docker技术的三大核心概念是什么?
- 镜像:镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
- 容器:容器是基于镜像创建的,是镜像运行起来之后的一个实例,容器才是真正运行业务程序的地方。如果把镜像比作程序里面的类,那么容器就是对象。
- 镜像仓库:存放镜像的地方,研发工程师打包好镜像之后需要把镜像上传到镜像仓库中去,然后就可以运行有仓库权限的人拉取镜像来运行容器了
DockerFile
什么是 DockerFile?
答:Dockerfile 是一个文本文件,其中包含我们需要运行以构建 Docker 映像的所有命令。Docker 使用 Dockerfile 中的指令自动构建镜像。我们可以docker build用来创建按顺序执行多个命令行指令的自动构建。
Dockerfile中最常见的指令是什么?
- FROM:指定基础镜像;
- RUN:运行指定的命令;
- CMD:容器启动时要运行的命令
- WORKDIR:(默认在/根目录)终端登录进去的落脚点。类似于cd,如果无该目录,则自动创建后再cd进去;
- ENV:设置环境常量,方便下文引用
- ONBUILD:触发器,当镜像用作另一个镜像构建的基础(例如可使用特定于用户的配置自定义的应用程序构建环境或守护程序)时
- VOLUME:自建容器卷
- EXPOSE:当前容器对外界暴露出的端口
- LABEL:为镜像指定标签;
- MAINTAINER:镜像维护者的姓名和邮箱地址
Dockerfile中的命令COPY和ADD命令有什么区别?
- 二者都是只复制目录中的文件,而不包含目录本身。
- COPY能干的事ADD都能干,甚至还有附加功能。
- ADD可以支持拷贝的时候顺带解压缩文件,以及添加远程文件(不在本宿主机上的文件),COPY的只能是本地文件
- 只是文件拷贝的话可以用COPY,有额外操作可以用ADD代替。
- docker官方建议当要从远程复制文件时,尽量用curl/wget命令来代替ADD。因为用ADD的时候会创建更多的镜像层。镜像层的size也大。
常用命令
如何查看当前运行的Docker容器?
答:使用docker ps命令可以查看当前运行的容器。加上-a参数可以看到所有容器,包括未运行的。
如何停止和启动Docker容器?
答:使用docker stop <容器ID或名称>可以停止容器。使用docker start <容器ID或名称>可以启动容器。
如何进入正在运行的Docker容器?
答:可以使用docker exec -it <容器ID或名称> /bin/bash命令进入容器。这里-it表示交互式终端。
如何删除Docker镜像和容器?
答:使用docker rmi <镜像ID>删除镜像,使用docker rm <容器ID>删除容器。如果容器正在运行,首先需要停止容器。
如何查看Docker容器的日志?
答:使用docker logs <容器ID或名称>可以查看容器的日志输出。
Docker基础与命令
描述Dockerfile和其用途。
答:Dockerfile是一个文本文件,包含了构建Docker镜像所需的一系列指令和命令。
Docker镜像和容器之间有什么区别?
答:Docker镜像是静态的定义,类似于类;而容器是镜像的实例,类似于对象。
怎样使用Dockerfile创建镜像?
答:使用docker build命令,如docker build -t myimage:latest .。
如何列出本地的Docker镜像?
答:使用docker images命令。
怎样检查Docker容器的资源使用情况?
答:使用docker stats命令。
Docker网络
Docker中如何实现容器间的网络隔离?
答:通过创建不同的Docker网络并将容器连接到这些网络,可以实现网络隔离。
解释Docker的网络模式中的bridge和host。
答:bridge是默认的网络模式,为容器提供了一个私有的内部网络。host模式使容器共享宿主机的网络栈。
Docker的--link选项是用来做什么的?
答:--link用于链接两个容器,使它们可以相互通信(已被弃用,推荐使用自定义网络)。
Docker的默认网络模式有哪些?
答:
- bridge:默认网络模式,为容器创建独立的网络栈
- host:容器共享宿主机的网络栈
- none:容器没有网络接口
- container:容器共享另一个容器的网络栈
- 自定义网络:用户可以创建自定义网络
如何创建Docker网络?
答:使用docker network create命令可以创建Docker网络。例如,docker network create --driver bridge my_bridge_network创建了一个bridge类型的网络。
Docker容器间通信是如何工作的?
答:容器可以通过Docker网络进行通信。在同一网络中的容器可以使用容器名称互相解析,实现容器间通信。
Docker存储
什么是Docker卷(Volume)?
答:Docker卷是一种持久化存储数据的机制。它独立于容器的生命周期存在,可以用来存储容器的数据。
如何创建和使用Docker卷?
答:可以使用docker volume create命令创建卷。使用卷的一个常见场景是在docker run命令中通过-v选项将卷挂载到容器内部。
Docker的存储类型有哪些?
答案:
- aufs:早期的存储驱动
- overlay/overlay2:当前推荐的存储驱动
- btrfs:适合大数据量场景
- devicemapper:适合企业级场景
- zfs:适合高性能存储
解释Docker的持久化存储。
答:Docker通过卷(Volumes)和绑定挂载(Bind Mounts)实现数据持久化。
什么是Docker卷的主要用途?
答:用于数据持久化和数据共享。
Docker卷和绑定挂载有什么区别?
答:卷由Docker管理,存储在Docker主机的指定区域;绑定挂载可以存储在主机系统的任意位置。
Docker Compose
什么是Docker Compose?
答:Docker Compose是一个工具,用于定义和运行多容器Docker应用程序。
如何启动使用Docker Compose定义的服务?
答:使用docker-compose up命令。
在Docker Compose文件中,links参数的作用是什么?
答:用于定义容器间的依赖和通信规则(在Docker网络普及后,这个选项的重要性下降)。
怎样在Docker Compose中设置环境变量?
答:可以在docker-compose.yml文件中使用environment键设置环境变量。
Docker Swarm
Docker Swarm是什么?
答:Docker Swarm是Docker的原生集群管理工具,用于在多个主机上部署和管理Docker容器。
如何创建一个Docker Swarm集群?
答:使用docker swarm init在主节点上初始化集群。
Docker Swarm中的服务(Service)和任务(Task)是什么?
答:服务定义了应用的状态,例如运行的副本数。任务是服务的一个实例,通常是一个容器。
如何扩展Docker Swarm中的服务?
答:使用docker service scale命令来增减服务的副本数量。
Docker Swarm和Kubernetes的主要区别是什么?
答:Kubernetes提供了更多的功能和灵活性,适用于更复杂的应用场景。Docker Swarm更简单,易于设置和管理。
安全和维护
如何保证Docker容器的安全性?
答:保持Docker和宿主机系统的更新,使用非root用户运行容器,限制容器的资源使用,使用Docker安全扫描等。
怎样更新Docker容器?
答:通常,需要停止旧容器,更新镜像,然后使用新镜像启动新容器。
Docker中的健康检查是如何工作的?
答:可以在Dockerfile中定义HEALTHCHECK指令或在docker-compose.yml中定义healthcheck来检查容器的健康状态。
Docker中的资源限制是如何实现的?
答:使用docker run命令的--memory(内存)、--cpus(CPU)等选项来限制资源。
如何清理未使用的Docker资源?
答:使用docker system prune命令可以清理悬挂的镜像、容器、网络和构建缓存。
高级话题
什么是Docker的多阶段构建?
答:多阶段构建是一种Dockerfile优化技术,允许在单个Dockerfile中使用多个构建阶段,减少最终镜像的大小。
解释Docker的存储驱动。
答:存储驱动负责管理容器的文件系统,Docker支持多种存储驱动,如overlay2、aufs、btrfs等。
Docker中的COPY和ADD命令有什么区别?
答:COPY仅用于复制本地文件,而ADD还可以解压缩文件和从URL下载文件。
Docker是如何实现容器隔离的?
答:Docker使用Linux的命名空间和控制组(cgroups)来实现容器的隔离。
解释Docker容器的重启策略。
答:Docker容器的重启策略决定了在退出时容器是否和如何重启。常用策略包括no、always、on-failure和unless-stopped。
docker的组成包含哪几大部分
一个完整的docker有以下几个部分组成:
- docker client,客户端,为用户提供一系列可执行命令,用户用这些命令实现跟 docker daemon 交互;
- docker daemon,守护进程,一般在宿主主机后台运行,等待接收来自客户端的请求消息;
- docker image,镜像,镜像run之后就生成为docker容器;
- docker container,容器,一个系统级别的服务,拥有自己的ip和系统目录结构;运行容器前需要本地存在对应的镜像,如果本地不存在该镜像则就去镜像仓库下载。
docker 使用客户端-服务器 (C/S) 架构模式,使用远程api来管理和创建docker容器。docker 容器通过 docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。
centos镜像几个G,但是docker centos镜像才几百兆,这是为什么?
一个完整的Linux操作系统包含Linux内核和rootfs根文件系统,即我们熟悉的/dev、/proc/、/bin等目录。我们平时看到的centOS除了rootfs,还会选装很多软件,服务,图形桌面等,所以centOS镜像有好几个G也不足为奇。 而对于容器镜像而言,所有容器都是共享宿主机的Linux 内核的,而对于docker镜像而言,docker镜像只需要提供一个很小的rootfs即可,只需要包含最基本的命令,工具,程序库即可,所有docker镜像才会这么小。
讲一下镜像的分层结构以及为什么要使用镜像的分层结构?
一个新的镜像其实是从 base 镜像一层一层叠加生成的。每安装一个软件,dockerfile中使用RUN命令,就会在现有镜像的基础上增加一层,这样一层一层的叠加最后构成整个镜像。所以我们docker pull拉取一个镜像的时候会看到docker是一层层拉取的。
分层机构最大的一个好处就是 : 共享资源。比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
讲一下容器的copy-on-write特性,修改容器里面的内容会修改镜像吗?
我们知道,镜像是分层的,镜像的每一层都可以被共享,同时,镜像是只读的。当一个容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件,都只会发生在容器层中,因为只有容器层是可写的,容器层下面的所有镜像层都是只读的。镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
添加文件时:在容器中创建文件时,新文件被添加到容器层中。 读取文件:在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。 修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。 删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
如何加固docker镜像的安全?
选择最小化基础镜像
- 优先官方/可信镜像:如Alpine、Distroless等轻量级镜像(Alpine仅5MB),减少攻击面。
- 固定版本标签:避免使用
latest,明确指定版本(如nginx:1.25.4)。
dockerfileFROM python:3.9-alpine # 替代默认镜像减小90%体积多阶段构建
- 分离构建与运行环境:编译阶段使用完整工具链,最终镜像仅包含运行时必要组件。
dockerfile# 构建阶段 FROM golang:1.19 AS builder WORKDIR /app COPY . . RUN go build -o app # 运行阶段(仅10MB) FROM alpine:latest COPY --from=builder /app/app /usr/local/bin/非Root用户运行
- 创建专用用户并切换,防止容器逃逸后获取宿主机权限。
dockerfileRUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser # 禁止默认root运行清理构建痕迹
- 删除缓存、临时文件及调试工具(如curl、shell),最小化攻击面。
dockerfileRUN apk add --no-cache nginx && rm -rf /var/cache/apk/* # 清理包管理器缓存最小权限原则
- 禁用特权模式:避免
--privileged,防止容器访问宿主机设备。 - 限制Capabilities:仅开放必要权限(如
NET_BIND_SERVICE)。
bashdocker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx- 禁用特权模式:避免
文件系统加固
- 只读根文件系统:防止恶意写入,临时目录通过
tmpfs挂载。
bashdocker run --read-only --tmpfs /tmp:rw,noexec,nosuid myapp- 只读根文件系统:防止恶意写入,临时目录通过
内核级隔离
- Seccomp:限制危险系统调用(如
kernel_module)。 - AppArmor/SELinux:配置自定义策略控制文件/网络访问。
bashdocker run --security-opt seccomp=custom-profile.json --security-opt apparmor=docker-default myapp- Seccomp:限制危险系统调用(如
镜像漏洞扫描
- CI/CD集成扫描工具:如Trivy、Clair,阻断含高危CVE的镜像进入生产。
bashtrivy image --severity HIGH,CRITICAL myimage:latest # 检测高危漏洞镜像签名与验证
- 启用Docker Content Trust (DCT):确保镜像来源可信且未被篡改。
bashexport DOCKER_CONTENT_TRUST=1 # 强制签名校验 docker push myimage:verified敏感数据管理
- 避免硬编码凭证:使用环境变量或Docker Secrets动态注入。
echo "password" | docker secret create db_pass # Swarm模式专用- 运行时行为审计
- Falco异常检测:监控容器逃逸、特权提升等行为。
docker run -d --name falco --privileged -v /var/run/docker.sock:/host/var/run/docker.sock falcosecurity/falco- 镜像更新策略
- 定期重建镜像:同步基础镜像安全补丁,避免漏洞滞留。
- 合规性集成
- SBOM(软件物料清单):追踪镜像内组件来源,满足GDPR/PCI DSS等规范。
