docker知识点笔记
docker
一、docker是什么?
Docker 本质上是基于 Linux 内核特性(如命名空间和控制组)的容器化技术。在 Windows 和 macOS 上,Docker 通过运行一个轻量级的 Linux 虚拟机(如 WSL2 或 HyperKit)来提供所需的运行环境,从而实现跨平台支持。
Docker vs 虚拟机
| 对比项 | Docker 容器 | 虚拟机(VM) |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 体积 | MB 级(共享宿主内核) | GB 级(含完整操作系统) |
| 性能 | 接近原生(无虚拟化开销) | 有虚拟化层损耗 |
| 隔离性 | 进程级隔离(共享内核) | 完全隔离(独立内核) |
| 适用场景 | 微服务、CI/CD、快速部署 | 强隔离需求、不同操作系统 |
一句话总结:容器是进程级隔离,虚拟机是系统级隔离。Docker 更轻量但隔离性弱于 VM,实际项目中常结合使用。
二、安装步骤
1.Windows安装 在“启用或关闭Windows功能”中,同时勾选“windows虚拟机监控程序平台”、“虚拟机平台”和“适用于Linux的Windows子系统”
2.重启电脑
3.安装WSL:以管理员身份打开PowerShell或命令提示符,执行
wsl --set-default-version 2
wsl --update --web-download
执行wsl --update安装WSL(国内网络建议添加--web-download参数减少下载失败)。
4.下载并安装Docker Desktop: 从官方网站下载对应CPU架构的安装包(Windows通常为AMD64),按提示完成安装。
5.启动Docker Desktop: 需保持Docker Desktop软件运行。
6.验证安装: 在Windows终端输入docker --version,若能打印版本号则表示安装成功。
配置国内镜像加速
国内拉取 Docker Hub 镜像经常超时,可以配置镜像加速器。
打开 Docker Desktop → Settings → Docker Engine,在 JSON 配置中添加:
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://registry.docker-cn.com"
]
}
点击 Apply & Restart 生效。验证是否生效:
docker info | grep -A 5 "Registry Mirrors"
三、Docker 镜像
Docker Pull 命令用来从仓库下载镜像。
docker pull docker.io/library/nginx:latest
一个 Docker 镜像下载地址包含 4 部分内容:
docker.io:registry / 仓库地址,如果是 Docker 官方仓库,则可以省略这个地址.
– 作用:指定从哪个仓库服务拉取镜像。
– 默认值:如果不写,默认为 Docker Hub(docker.io)。
– 示例:registry.cn-hangzhou.aliyuncs.com(阿里云)、ghcr.io(GitHub)
library:命名空间(镜像作者)/項目組,为了防止不同用户上传同一个名字的镜像发生冲突。
– “library” 是 docker 官方仓库的命名空间,这个空间下的所有镜像都是由 Docker 官方维护。如果是官方的命名空间则可以省略不写。
– 通常代表拥有该镜像的个人用户名、组织名称或项目组名称。
– 作用:用于管理和隔离镜像,类似于文件路径中的“文件夹”。
– 默认值:如果是 Docker Hub 官方认证的镜像,默认为 library。
nginx:镜像名
– 软件包的名称,即实际使用的镜像功能名称
– 作用:标识具体的应用软件,如 Nginx、MySQL、Python 等。
– 示例:nginx、mysql、redis。
latest:标签名、版本号。写 “latest” 或者不写表示获取最新版本的镜像
– 镜像的特定版本标识符。
– 作用:区分同一个镜像的不同版本(如系统版本、Alpine 轻量版或特定构建版本)。
– 默认值:如果不写,默认为 latest(最新版)。
– 示例:22.04、alpine、1.21.6。
查看镜像
docker images
删除镜像
docker rmi [镜像标识]
使用此命令可以删除 pull 到本地的镜像,镜像标识可以选择 镜像的 ID(image id)或者镜像的名称(repository)
镜像标签选择建议
● alpine:基于 Alpine Linux,仅 5MB 左右,适合生产环境,但使用 musl libc 可能存在兼容问题
● slim:基于 Debian 精简版,比 alpine 兼容性更好,体积适中
● latest / 默认:完整版,包含所有工具,适合开发调试
● 生产环境不要用 latest,应指定明确版本号,避免不可控变更
构建镜像
docker build -t my-app:1.0 .
● -t:指定镜像名称和标签,格式为 名称:标签
● .:表示 Dockerfile 所在目录(构建上下文路径)
给镜像打标签并推送
docker tag my-app:1.0 registry.cn-hangzhou.aliyuncs.com/myname/my-app:1.0
docker push registry.cn-hangzhou.aliyuncs.com/myname/my-app:1.0
推送前需要先登录仓库:docker login registry.cn-hangzhou.aliyuncs.com
四、Docker 容器
创建并运行容器
docker run [镜像标识]
使用 run 命令可以通过镜像创建一个容器,并启动它。镜像标识可以是镜像 ID 或者镜像名称。
例如:docker run nginx 就是创建一个 Nginx 容器。
docker pull 命令可以省略,直接使用 docker run 运行,如果 docker 发现本地没有这个镜像则会自动拉取。
分离模式
默认情况下 docker run 创建容器后会导致当前终端挂起,不能进行其他操作,可以增加 -d 参数表示容器在后台运行,不阻塞当前窗口
docker run -d nginx
端口映射
容器的网络和宿主机的网络是隔离的,例如运行了一个 Nginx 容器,容器内的 Nginx 监听了 80 端口。这时通过宿主机的 80 端口是无法访问到 Nginx 服务的。
所以需要 -p {宿主机端口}:{容器的端口} 命令进行映射,例如 -p 80:80 表示将 Nginx 容器的 80 端口映射到宿主机的 80 端口。
目录映射(绑定挂载)
与端口映射类似的就是目录映射,将容器外和容器内的目录进行绑定,容器内对文件的修改会影响宿主机的文件夹,宿主机的修改也会影响容器内文件夹。
-v {宿主机目录}:{容器的目录}
这种目录也被称为挂载卷,他的最大作用是数据的持久化。 当容器删除时,容器内的所有数据都会被删除,但通过挂载卷映射到宿主机的文件夹将得以保留。
docker run -d -p 80:80 -v ./:/usr/share/nginx/html nginx
传环境变量(常用于数据库密码、配置,敏感信息需注意安全)
可以在命令行通过 -e 参数传递环境变量到容器内部,例如创建一个数据库应用,需要在创建容器时就指定数据库的账户、密码等信息。
docker run -d -p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=admin123 \
mongo
如果不知道容器的环境变量有哪些,可以在 Docker Hub 上搜索一下,都有详细的描述。
容器命名与重启策略
docker run -d --name my-nginx --restart=always -p 80:80 nginx
● --name:给容器指定名称,方便后续管理,不指定则随机生成
● --restart:重启策略
| 策略 | 说明 |
|---|---|
no |
默认值,容器退出不重启 |
always |
容器退出总是重启(开机也自动启动) |
on-failure[:max] |
仅非正常退出时重启,可限制次数 |
unless-stopped |
类似 always,但手动 stop 后不会重启 |
启停容器
每次使用 docker run 运行都会创建一个新的容器,对同一个容器进行持续的操作,可以通过容器的启停命令来控制。
# 启动容器
docker start {容器标识}
# 停止容器
docker stop {容器标识}
# 重启容器
docker restart {容器标识}
查看容器
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
# 只显示容器 ID
docker ps -q
进入容器
docker exec -it {容器标识} /bin/bash
● -i:保持标准输入打开
● -t:分配伪终端
● 如果镜像基于 Alpine,bash 可能不存在,改用 /bin/sh
docker exec -it {容器标识} /bin/sh
查看容器日志
# 查看全部日志
docker logs {容器标识}
# 实时跟踪日志(类似 tail -f)
docker logs -f {容器标识}
# 查看最后 100 行
docker logs --tail 100 {容器标识}
查看容器详情
# 查看容器完整配置信息(IP、挂载、环境变量等)
docker inspect {容器标识}
# 只看 IP 地址
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' {容器标识}
删除容器
# 删除已停止的容器
docker rm {容器标识}
# 强制删除运行中的容器
docker rm -f {容器标识}
# 删除所有已停止的容器
docker container prune
容器与宿主机互传文件
# 从容器复制文件到宿主机
docker cp {容器标识}:/app/config.yml ./config.yml
# 从宿主机复制文件到容器
docker cp ./config.yml {容器标识}:/app/config.yml
五、数据持久化(Volume 卷)
解决痛点:容器删除,数据即消失。
三种存储方式:
Bind Mount(开发常用):挂载宿主机任意目录(如 -v ./:/app)。
Volume(生产推荐):由 Docker 管理(存放在 /var/lib/docker/volumes/),通过 docker volume create 创建,适合数据库、日志等高IO场景。
tmpfs:存内存,容器重启即清空(存临时敏感数据)。
创建卷
docker volume create {卷名称}
查看所有卷
docker volume list
删除卷
docker volume rm nginx_html
删除所有没有容器在使用的卷
docker volume prune -a
使用 Volume 运行容器
docker run -d -v mydata:/var/lib/mysql mysql
● 不以 / 或 ./ 开头的路径会被识别为 Volume 名称
● 以 / 或 ./ 开头的路径会被识别为 Bind Mount
Bind Mount vs Volume 选择
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 开发时代码热更新 | Bind Mount | 直接映射源码目录,修改即时生效 |
| 数据库数据存储 | Volume | Docker 管理,权限和性能更优 |
| 配置文件注入 | Bind Mount | 方便在宿主机直接编辑 |
| 日志持久化 | Volume | 不依赖宿主机目录结构 |
六、Docker 网络
容器间通信是微服务架构的基础,Docker 提供了多种网络模式。
网络模式
| 模式 | 说明 |
|---|---|
bridge |
默认模式,容器通过虚拟网桥通信 |
host |
容器直接使用宿主机网络,无端口映射开销 |
none |
容器无网络,适合安全敏感场景 |
overlay |
跨主机通信,用于 Docker Swarm 集群 |
自定义网络
默认 bridge 网络下容器只能通过 IP 互访,自定义网络支持容器名互访,这是最常用的方式。
# 创建自定义网络
docker network create my-net
# 运行容器并加入网络
docker run -d --name app --network my-net nginx
docker run -d --name db --network my-net mysql
加入同一网络的容器可以直接用名称通信:
# 在 app 容器内可以直接用 db 作为主机名
ping db
网络管理命令
# 查看所有网络
docker network ls
# 查看网络详情
docker network inspect my-net
# 将运行中的容器加入网络
docker network connect my-net {容器标识}
# 将容器从网络中移除
docker network disconnect my-net {容器标识}
# 删除网络
docker network rm my-net
七、Dockerfile 基础语法
7 个常用指令
FROM python:3.10 # 1. 指定基础镜像(起点)
WORKDIR /app # 2. 设置工作目录(cd /app)
COPY . . # 3. 复制文件(将本地文件拷入镜像)
RUN pip install -r requirements.txt # 4. 执行构建命令(安装依赖)
CMD ["python", "main.py"] # 5. 容器启动时执行的命令(默认)
CMD vs ENTRYPOINT
| 对比项 | CMD | ENTRYPOINT |
|---|---|---|
| 用途 | 提供默认命令和参数 | 定义容器的主命令 |
| 是否可被覆盖 | docker run 后面的命令会覆盖 CMD |
不会被覆盖,追加的参数会传给 ENTRYPOINT |
| 多次声明 | 只有最后一个生效 | 只有最后一个生效 |
| 配合使用 | 可以为 ENTRYPOINT 提供默认参数 | 固定主命令,CMD 提供可变参数 |
# ENTRYPOINT + CMD 配合使用
ENTRYPOINT ["python", "main.py"]
CMD ["--help"]
这样 docker run my-app 默认执行 python main.py --help,而 docker run my-app --version 则执行 python main.py --version。
ARG vs ENV
| 对比项 | ARG | ENV |
|---|---|---|
| 作用阶段 | 仅构建阶段有效 | 构建和运行阶段都有效 |
| 是否可被运行时覆盖 | 不可 | 可通过 -e 覆盖 |
| 典型用途 | 传入构建版本号、仓库地址 | 设置运行时配置、数据库地址 |
ARG VERSION=1.0
ENV NODE_ENV=production
# ARG 在构建时传入
# docker build --build-arg VERSION=2.0 .
.dockerignore
类似 .gitignore,排除不需要拷入镜像的文件,减小构建上下文体积、加速构建、避免敏感信息泄露。
node_modules
.git
.env
*.md
__pycache__
.DS_Store
dist
多阶段构建(生产环境瘦身利器)
# 阶段 1:构建阶段(包含 Node 全套环境,体积大)
FROM node:18 AS builder
COPY . .
RUN npm install && npm run build
# 阶段 2:运行阶段(仅用 Nginx 托管产物,体积极小)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# 最终镜像只有几十 MB,不包含 Node 环境
镜像构建优化
● 利用缓存:将不常变化的层(如 RUN pip install)放在前面,频繁变化的层(如 COPY . .)放在后面
● 合并 RUN 指令:每个 RUN 都会产生新层,用 && 合并减少层数
# 不推荐:产生 3 个层
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# 推荐:合并为 1 个层
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
● 选择精简基础镜像:优先使用 alpine 或 slim 变体
● 清理安装缓存:在 RUN 中及时清理 apt/yum 缓存、pip 缓存等
八、Docker Compose
当项目需要多个容器协同工作时(如 Web + 数据库 + 缓存),手动 docker run 会非常繁琐。Docker Compose 通过一个 YAML 文件定义和管理多容器应用。
安装
Docker Desktop 已内置 Compose,无需额外安装。Linux 环境需单独安装:
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose.yml 示例
version: "3.8"
services:
web:
build: .
ports:
- "3000:3000"
volumes:
- ./:/app
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=myapp
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
db_data:
redis_data:
关键字段说明
| 字段 | 说明 |
|---|---|
build |
根据 Dockerfile 构建镜像,值为 Dockerfile 所在目录 |
image |
直接使用已有镜像 |
ports |
端口映射,格式同 -p |
volumes |
挂载卷或目录,格式同 -v |
environment |
环境变量,格式同 -e |
depends_on |
依赖关系,控制启动顺序(不保证服务就绪) |
restart |
重启策略,同 docker run --restart |
networks |
指定加入的网络,默认创建默认网络 |
● Compose 默认会创建一个网络,所有服务加入同一网络,服务间可直接用服务名通信(如 db:3306)
● depends_on 只控制启动顺序,不等待服务真正就绪。如需等待就绪,建议在应用代码中加入重试逻辑
常用命令
# 启动所有服务(-d 后台运行)
docker compose up -d
# 停止并删除所有容器
docker compose down
# 停止并删除容器 + 卷(清除数据)
docker compose down -v
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f
# 重新构建镜像
docker compose build
# 只重启某个服务
docker compose restart web
# 进入某个服务的容器
docker compose exec web /bin/bash
# 扩容(启动多个实例)
docker compose up -d --scale worker=3
环境变量管理
敏感信息不应直接写在 YAML 中,推荐使用 .env 文件:
# .env 文件
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=myapp
在 docker-compose.yml 中引用:
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
● .env 文件应加入 .gitignore,避免泄露
● 也可以用 docker compose --env-file prod.env up -d 指定环境文件
九、常用命令速查
镜像相关
docker pull [镜像] # 拉取镜像
docker images # 查看本地镜像
docker rmi [镜像] # 删除镜像
docker build -t name:tag . # 构建镜像
docker tag src dst # 打标签
docker push [镜像] # 推送镜像
docker image prune # 清理无用的镜像
容器相关
docker run [选项] [镜像] # 创建并运行容器
docker ps # 查看运行中容器
docker ps -a # 查看所有容器
docker start [容器] # 启动容器
docker stop [容器] # 停止容器
docker restart [容器] # 重启容器
docker rm [容器] # 删除容器
docker rm -f [容器] # 强制删除运行中容器
docker exec -it [容器] /bin/bash # 进入容器
docker logs [-f] [容器] # 查看日志
docker inspect [容器] # 查看详情
docker cp [容器]:路径 本地路径 # 容器→宿主机
docker cp 本地路径 [容器]:路径 # 宿主机→容器
docker container prune # 清理已停止容器
网络相关
docker network create [名称] # 创建网络
docker network ls # 查看网络
docker network inspect [网络] # 查看网络详情
docker network connect [网络] [容器] # 容器加入网络
docker network disconnect [网络] [容器] # 容器离开网络
docker network rm [网络] # 删除网络
卷相关
docker volume create [名称] # 创建卷
docker volume ls # 查看卷
docker volume inspect [卷] # 查看卷详情
docker volume rm [卷] # 删除卷
docker volume prune # 清理无用卷
系统清理
docker system df # 查看 Docker 磁盘占用
docker system prune # 一键清理(停止的容器、无用镜像、网络、构建缓存)
docker system prune -a --volumes # 彻底清理(包括未使用的镜像和卷)