从零开始使用 Docker。每个命令都解释清楚参数含义,每一步都有预期结果。
安装 Docker#
Linux(发行版包示例)
以下保留发行版包管理命令,包名和来源随发行版版本变化,不保证提供 Docker 官方仓库的最新版本;安装前查对应发行版与 Docker Engine 安装文档。加入 rootful docker 组意味着授予近似 root 的控制权限。NixOS 不使用这些安装命令。
# Ubuntu / Debian
sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# ↑ 把自己加入 docker 组(重新登录后生效),此后不用 sudo
# Fedora
sudo dnf install docker docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# Arch
sudo pacman -S docker docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker $USER安装后验证:
docker version # 显示客户端和服务端版本
docker info # 显示系统信息(存储驱动、内核版本等)
docker run hello-world # 跑一个测试容器NixOS 用户:见 第七篇 NixOS 管理实践。
Docker Desktop(跨平台 GUI)
从 docker.com 下载安装。自带 GUI、K8s 集成、文件共享等。注意:许可不仅按员工数判断,年营收及使用场景也有关;按 Docker Desktop 当前条款核实。Linux Desktop 使用自己的 VM/context,不与宿主 Engine 自动共享镜像库。
镜像操作#
搜索与拉取
# 搜索 Docker Hub 上的镜像
docker search nginx
# 输出:NAME(镜像名) DESCRIPTION STARS OFFICIAL
# OFFICIAL = [OK] 表示 Docker Official Images 项目收录,非所有镜像均由 Docker 公司直接维护
# 从 Docker Hub 拉取镜像
docker pull nginx:alpine
# │ └─ 标签(版本),alpine = 基于 Alpine Linux 的精简版
# └────── 镜像名,不写仓库默认从 docker.io 拉
# 拉取指定版本
docker pull python:3.12-slim
docker pull node:20-bookworm
# 一次性拉取 + 运行(本地没有时会自动拉)
docker run nginx:alpine查看与管理镜像
# 列出本机所有镜像
docker images
# 或 docker image ls
# 输出列:REPOSITORY(来源) TAG IMAGE ID CREATED SIZE
# 查看镜像各层信息
docker history nginx:alpine
# 显示镜像历史元数据;不保证逐行还原原始 Dockerfile
# 查看镜像详细 JSON(环境变量、入口命令、暴露端口等)
docker inspect nginx:alpine
# 删除镜像
docker rmi nginx:alpine
# 删除所有未使用镜像(释放空间)
docker image prune -a
# -a 包括未使用的镜像;不加 -a 只删标签 <none> 的悬空镜像给镜像打标签
# 为本地镜像添加标签
docker tag myapp:latest myapp:1.0
# 两个标签指向同一镜像,不占额外空间
# 为推送到私有仓库做准备
docker tag myapp:latest registry.example.com/myapp:1.0
docker push registry.example.com/myapp:1.0容器操作#
运行容器
# 最简运行(前台,Ctrl+C 停止)
docker run nginx:alpine
# 后台运行 + 命名 + 端口
docker run -d --name myweb -p 8080:80 nginx:alpine
# └┘ └───────┘ └───────┘
# detach 容器名 宿主机:容器
# (后台)
# 运行后自动删除(一次性任务,退出后删除容器;镜像、命名卷和日志/外部副作用仍可能存在)
docker run --rm alpine echo "hello"
# 交互式(进入容器内 shell)
docker run -it ubuntu bash
# └┘└┘
# interactive 分配虚拟终端
# 指定重启策略
docker run -d --restart=always --name web nginx:alpine
# --restart=always 容器退出时总是自动重启
# --restart=on-failure:3 只在异常退出时重启,最多 3 次
# --restart=unless-stopped 除非手动 stop,否则一直重启常用 run 参数速查
| 参数 | 作用 | 示例 |
|---|---|---|
-d |
后台运行 | docker run -d ... |
--name |
命名容器 | --name myweb |
-p |
端口映射 | -p 8080:80 |
-v |
挂载卷/目录 | -v myvol:/data 或 -v /host/path:/container/path |
--rm |
退出自动删除 | --rm |
-e |
环境变量 | -e DB_URL=postgres://... |
--env-file |
从文件加载环境变量 | --env-file .env |
-it |
交互 + 终端 | -it |
--restart |
重启策略 | --restart=always |
--memory |
内存限制 | --memory=256m |
--cpus |
CPU 限制 | --cpus=1.5 |
查看容器状态
# 正在运行的容器
docker ps
# CONTAINER ID IMAGE COMMAND STATUS PORTS
# abc123def... nginx:alpine "nginx -g..." Up 2 minutes 0.0.0.0:8080->80/tcp
# 所有容器(含已停止)
docker ps -a
# 查看容器日志
docker logs myweb # 全部日志
docker logs -f myweb # 实时跟踪(Ctrl+C 退出)
docker logs --tail 50 myweb # 最近 50 行
# 查看容器内进程
docker top myweb
# 查看容器资源使用(实时,类似 top)
docker stats myweb
# 输出 CPU%、内存使用/限制、网络 I/O、磁盘 I/O
# 查看容器详细信息
docker inspect myweb管理容器生命周期
# 停止(发送 SIGTERM,等 10s 后再强杀)
docker stop myweb
# 立即强杀(发送 SIGKILL)
docker kill myweb
# 启动已存在的容器(不是新建)
docker start myweb
# 重启
docker restart myweb
# 暂停/恢复(暂停期间不消耗 CPU,不释放内存)
docker pause myweb
docker unpause myweb
# 进入正在运行的容器
docker exec -it myweb sh
# └┘└┘ └───┘ └──┘
# 交互 终端 容器名 命令
# 如果容器里没有 bash,试试 sh
# 以不同用户身份进入
docker exec -it -u root myweb sh
# 删除已停止的容器
docker rm myweb
# 强制删除(即使正在运行)
docker rm -f myweb
# 清理所有已停止的容器
docker container prune卷(Volume)#
为什么需要卷
删除容器会移除可写层;命名卷、绑定挂载等独立数据按自己的生命周期保留。卷把数据存在宿主机上,可以在容器间共享和持久化。
# 创建命名卷
docker volume create mydata
# 列出卷
docker volume ls
# 带卷启动容器
docker run -d --name db \
-e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \
--mount type=bind,src=/path/to/protected-password-file,dst=/run/secrets/db_password,readonly \
-v mydata:/var/lib/postgresql/data \
postgres:16-alpine
# └─┬─┘ └──────────┬──────────┘
# 宿主机卷名 容器内路径
# 绑定挂载(直接挂宿主机路径,开发常用)
docker run -v /home/alice/project:/app nginx:alpine
# └──────┬──────┘ └─┘
# 宿主机绝对路径 容器内
# 卷详情(存在哪、哪个容器在用)
docker volume inspect mydata
# 当前 API 默认清理未被任何容器引用的匿名卷;--all 扩至命名卷,删除前确认数据
docker volume prune两种挂载对比
| 命名卷 (Volume) | 绑定挂载 (Bind Mount) | |
|---|---|---|
| 管理方式 | Docker 管理 | 你自己管理 |
| 路径 | /var/lib/docker/volumes/... |
你指定的宿主机任意路径 |
| 初始内容 | 如果卷是空的,容器内的数据会复制进去 | 覆盖容器内目录 |
| 适用场景 | 数据库、持久化数据 | 开发时代码同步 |
网络(Network)#
# 列出网络
docker network ls
# bridge(默认)、host、none
# 创建自定义网络(同一网络中的容器可用容器名互访)
docker network create mynet
# 在指定网络中运行容器
docker run -d --name web --network mynet nginx:alpine
docker run -d --name db --network mynet \
-e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \
--mount type=bind,src=/path/to/protected-password-file,dst=/run/secrets/db_password,readonly \
postgres:16-alpine
# 在 web 容器中 ping db(通过容器名)
docker exec web ping db # 镜像需有 ping;此为预期用途,网络策略和工具决定实际结果
# 查看网络和接入的容器
docker network inspect mynet
# 删除网络
docker network rm mynet日常维护#
# 查看磁盘占用
docker system df
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 5 2 1.2GB 800MB (66%)
# Containers 3 1 50MB 30MB (60%)
# Volumes 2 1 200MB 100MB (50%)
# 删除停止容器、未用网络、未用镜像和构建缓存;--volumes 另清未用匿名卷
docker system prune -a --volumes
# 确认无需停止容器的可写层及匿名卷,已有备份后才执行;命名卷不是此参数全部删除对象
# 查看 Docker 事件流
docker events
# 实时输出:容器创建、启动、停止、删除等事件Docker 命令 vs Podman 命令#
两个引擎的常用 CLI 相似,但并非完全等价。详细对比见 Docker 与 Podman 关系篇。
# 大部分命令可以直接互换
docker run -d --name web -p 8080:80 nginx:alpine
podman run -d --name web -p 8080:80 nginx:alpine
# 主要差异:
# docker 默认 rootful,podman 默认 rootless
# docker compose(原生) vs podman-compose(社区)
# docker swarm(Docker 独有) vs podman pod + play kube执行与数据边界#
所有 prune、rm 与 rmi 示例都需要先确认对象及备份。卷目录因 daemon 的 data-root、rootless 或 Desktop VM 而变,不能固定理解为宿主机 /var/lib/docker。默认端口发布通常面向全部宿主接口;本机开发可显式 -p 127.0.0.1:8080:80。停止信号与超时可配置,重启策略的手动停止和 daemon 重启语义需按策略核对。环境变量可能被有管理权限的人 inspect,不能作为秘密保险箱。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。