1 docker 原理相关问题
1.1 镜像与容器的区别
Docker镜像是一个轻量级、只读的模板,用于创建Docker容器。它包含运行容器所需的代码、库、环境变量和配置文件。
Docker容器包括应用程序及所有的依赖项,作为操作系统的独立进程运行。
1.2 容器的隔离机制是什么
Docker 容器如何实现隔离? 中 一 二 三
1.3 容器与虚拟机的区别
角度 | 虚拟机 | 容器 |
---|---|---|
隔离级别 | 操作系统级 | 进程级 |
原理 | 虚拟硬件,独立内核实现 | 通过各种namespace、cgroups、unionfs,共享宿主机内核实现。详细见1.2 |
资源占用 | 高 | 低 |
启动速度 | 慢(分钟级) | 快(秒级/毫秒级) |
使用场景 | 运行不同操作系统、强隔离需求 | 微服务、持续集成、轻量级应用隔离 |
1.4 dockerfile与docker-compose的区别?
dockerfile文件是用来写构建单个镜像逻辑的,可以执行docker build命令根据dockerfile文件生成镜像
docker-compose.yaml文件是用来定义和运行多容器的,可以执行docker-compose up启动
2 docker 常用命令
2.1 镜像
docker search 镜像名 # 还有其它一些参数,可以使用--help查看
docker images # 显示本地所有镜像(仓库名、标签、ID、大小等)
docker images -a # 包含中间镜像层
docker images -q # 仅显示镜像ID
docker images --filter "dangling=true" # 筛选悬空镜像(无标签的冗余镜像)
docker tag nginx:latest mynginx:1.22.0 # 为镜像添加新标签
docker push myusername/myapp:v1 # 推送镜像到远程仓库(需先登录)
docker rmi 镜像名 # 删除指定镜像
docker rmi -f $(docker images -q) # 强制删除所有镜像(谨慎使用!)
docker image prune -a # 清理所有未被容器引用的镜像(含中间层)
docker commit my_nginx my_nginx:v2 # 从容器创建新镜像(保存修改)
docker save -o nginx.tar nginx:latest # 导出镜像为tar包
docker load -i nginx.tar # 从tar包导入镜像
docker build -t myapp:1.0 . # 根据当前目录Dockerfile构建镜像
docker build -t myapp:1.0 --platform linux/amd64 . # 指定平台构建
docker system prune -a --volumes # 清理镜像、容器、网络、卷(慎用!)
docker history nginx:latest # 显示镜像构建历史层
docker inspect nginx:latest # 查看镜像配置、网络设置等详细信息
docker rmi $(docker images --filter "dangling=true" -q) # 删除所有悬空镜像
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:multi . # 构建多平台镜像
dockerfile中的from不要与docker build 的选项–platform 产生冲突
2.2 容器
#--name 给要运行的容器起的名字; -p 将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口; -d 表示可后台运行容器 (守护式运行)。具体样例见下
docker run --name containerName -p 80:80 -d nginx
docker ps #显示正在运行的容器
docker ps -a #-a,--all 显示全部容器,包括已停止的(默认只显示运行中的容器)
docker stop name #停止一个运行的容器(杀死进程、回收内存,仅剩文件系统)
docker start name #让一个停止的容器再次运行
docker restart name #重启容器
docker pause 容器名/容器ID #让一个运行的容器暂停
docker unpause name #让一个容器从暂停状态恢复运行
docker restart name #重启容器
#若容器已启动,希望设置开机自启动
docker update 容器名/容器ID --restart=always
docker stats
docker inspect 容器名
docker kill 容器名 #杀掉一个运行中的容器
# 查看日志
docker logs 容器名 #查看容器运行日志
docker logs -f 容器名 #持续跟踪日志
docker logs -f --tail=20 容器名 #查看末尾多少行
# 删除容器
docker rm 容器名/容器ID #删除容器
docker rm -f CONTAINER #强制删除
docker rm -f 容器名 容器名 容器名 #删除多个容器 空格隔开要删除的容器名或容器ID
docker rm -f $(docker ps -aq) #删除全部容器
#从容器退到自己服务器中(不能用ctrl+C)
exit #直接退出。未添加-d(持久化运行容器)时,执行此参数 容器会被关闭
ctrl+p+q #优雅退出。无论是否添加-d参数,执行此命令容器都不会被关闭
2.3 网络
2.3.1 网络模式
- none:无网络
- host:跟宿主机共享网络命令空间
- bridge:Docker 默认的网络模式,每个容器通过虚拟网桥(docker0)连接。容器有独立的 IP 地址(通常在 172.17.0.0/16 范围内),可互相通信。容器可通过宿主机的 NAT 访问外部网络(如互联网)。外部网络无法直接访问容器(除非映射端口)。
- container:容器与另一个容器共享网络命名空间,使用相同的 IP 地址和网络接口。两个容器可互相通过 localhost 访问。
docker run --network container:目标容器名或ID myimage
- Overlay: 跨主机的分布式网络,用于 Docker Swarm 集群。容器可在不同主机上通信,支持服务发现和负载均衡。需要 Docker Swarm 初始化
# 初始化 Swarm docker swarm init # 创建 Overlay 网络 docker network create --driver overlay my-overlay-net # 在 Swarm 服务中使用 docker service create --network my-overlay-net --name my-service myimage
- Macvlan:为容器分配独立的 MAC 地址和 IP 地址,使其
直接暴露在物理网络
中。容器可像物理设备一样被网络识别(如被其他设备直接访问)。docker network create -d macvlan \ --subnet=192.168.1.0/24 \ --gateway=192.168.1.1 \ -o parent=eth0 \ my-macvlan-net docker run --network my-macvlan-net --ip=192.168.1.100 myimage
- IPvlan: 类似 Macvlan,但共享 MAC 地址(使用子接口),减少 ARP 风暴。支持 L2 和 L3 模式。
2.3.2 网络常用命令
docker network create my_custom_network # 创建默认bridge网络
docker network create --driver=bridge --subnet=192.168.100.0/24 --gateway=192.168.100.1 my_bridge_network # 自定义子网和网关
docker network create --driver=overlay --attachable my_overlay_network # 创建覆盖网络(需Swarm模式)
--driver:指定网络驱动(默认bridge,可选host/overlay/macvlan/none)。
--subnet/--gateway:自定义子网和网关(仅对bridge驱动有效)。
--attachable:允许非Swarm服务容器连接(仅对overlay驱动有效)。
docker network ls # 显示所有网络(ID、名称、驱动、作用域)
docker network ls --filter "driver=bridge" # 筛选指定驱动的网络
docker run -d --name my_nginx --network my_custom_network nginx # 启动时连接网络
docker network connect my_custom_network my_existing_container # 将已有容器连接到网络
docker network disconnect my_custom_network my_nginx # 断开指定容器与网络的连接
docker network disconnect --force my_custom_network my_nginx # 强制断开(即使容器不存在)
docker network prune # 删除所有未被容器引用的网络(谨慎使用!)
3 dockerfile常用命令
# 基础指令
FROM 指定基础镜像(必须为第一条指令) FROM ubuntu:20.04
LABEL 添加镜像元数据(如作者、版本) LABEL maintainer="example@domain.com" version="1.0"
# 环境与配置
ENV 设置环境变量(后续指令可引用 ${VAR_NAME}) ENV APP_HOME=/app
WORKDIR 设置工作目录(后续指令的相对路径基于此目录) WORKDIR ${APP_HOME}
USER 指定后续指令的运行用户(避免使用 root) USER 1000
# 文件操作
COPY 将宿主机文件复制到镜像中(支持通配符) COPY src/ ${APP_HOME}/src/
ADD 类似 COPY,但支持解压压缩包或从 URL 下载(不推荐优先使用) ADD https://example.com/file.tar.gz /tmp/
RUN 执行命令(如安装依赖),每条 RUN 生成一个新镜像层 RUN apt-get update && apt-get install -y curl
# 端口与入口
EXPOSE 声明容器运行时监听的端口(仅文档作用,实际需用 -p 映射) EXPOSE 8080
CMD 指定容器启动时的默认命令(可被 docker run 覆盖) CMD ["python", "app.py"]
ENTRYPOINT 类似 CMD,但更强调“入口点”,参数可通过 docker run 追加 ENTRYPOINT ["/usr/bin/nginx"]
# 其它指令
ARG 定义构建时参数(可通过 --build-arg 传递) ARG VERSION=latest
FROM nginx:${VERSION}
VOLUME 声明匿名卷(持久化数据,避免被镜像层覆盖) VOLUME /data
HEALTHCHECK 定义容器健康检查命令 `HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/
ONBUILD 为镜像添加一个延迟执行的触发器,在构建基于该镜像的子镜像时自动触发特定操作;指令在子镜像的 FROM 指令之后、其他指令之前执行
docker run 后跟的 vs dockfile中的ENTRYPOINT vs dockerfile中的CMD
- docker run后没有–entrypoint时:
- 有
ENTRYPOINT
时,CMD
和docker run后跟的
都是ENTRYPOINT命令
的参数,且docker run后跟的参数
覆盖CMD中参数
; - 当没有
ENTRYPOINT
时,CMD
和docker run后跟的
都表示命令,且docker run 后跟的命令
覆盖CMD 命令
。
- 有
- docker run后有–entrypoint时:dockerfile中的ENTTRYPOINT和CMD都会失效,直接在–entrypoint 后跟容器启动时需要执行的命令
查看镜像的环境变量
- 方法1: 查看dockerfile
- 方法2: docker inspect
docker inspect <镜像名或ID> | grep -i env 或 更详细的查看 docker inspect --format='{{range .Config.Env}}{{.}}{{end}}' <镜像名或ID>
多阶段构建:
它允许在单个 Dockerfile 中使用多个 FROM 指令,从而将镜像构建过程拆分为多个阶段。每个阶段可以独立使用不同的基础镜像,最终只保留最后一个阶段生成的镜像,避免将中间过程的文件打包到最终的镜像中,显著减小最终镜像的体积
。
示例:构建 Go 应用
假设有一个简单的 Go 应用,需要编译成二进制文件并运行在 Alpine 镜像中。
传统单阶段构建的缺点
需要将 Go 编译器和依赖库打包到最终镜像中,导致镜像体积过大(通常几百 MB)。
多阶段构建的解决方案
# 第一阶段:构建阶段(使用官方 Go 镜像)
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp
# 第二阶段:运行阶段(使用轻量级 Alpine 镜像)
FROM alpine:3.18
WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]
说明
第一阶段(builder):
使用 golang:1.21 镜像编译 Go 应用。
生成二进制文件 myapp。
第二阶段:
使用 alpine:3.18 镜像作为运行环境。
通过 COPY --from=builder 从第一阶段复制二进制文件。
最终镜像仅包含 myapp 和 Alpine 的基础文件,体积大幅减小(通常几 MB)。
构建和运行
docker build -t my-go-app .
docker run -it --rm my-go-app
4 docker-compose
4.1 docker-compose.yaml
Docker–基础知识点–30–docker-compose.yaml常用配置
更多其它配置请查阅:docker compose 配置文件 .yml 全面指南
[1]
dockerfile中expose与docker-compose.yaml中expose的区别:dockerfile中expose只是一种文档式声明并不实际生效,docker-compose.yaml中expose会实际生效,表示同一网络中容器对其它容器暴露的端口,进行容器见通信
docker-compose.yaml中ports将容器的端口映射到宿主机的端口,使得外部可以访问容器
[2] docker的重启策略
- no: 默认值,不自动重启容器
- always: 无论退出状态如何,总是重启容器。【无论容器如何退出(包括手动停止),Docker 都会尝试重启它。】
- on-failure: 仅当容器非正常退出(退出代码非0)时才重启容器。你可以指定重启的次数,例如 on-failure:3 表示最多重启3次。
- unless-stopped: 在容器停止(无论是正常停止还是被杀死)时,总是重启容器,除非 Docker 本身被停止或重启。【如果容器被手动停止(如通过 docker stop 或 docker-compose down),则不会自动重启,即使之后 Docker 服务重启或主机重启。】
version: '3'
services:
web:
image: nginx
restart: on-failure:3
4.2 docker-compose常用命令
Docker Compose常用命令中 docker compose常用命令