一、镜像与容器
- 镜像(image):只读模板,包含文件系统和启动命令,类似「安装包」。
- 容器(container):镜像的运行实例,有自己的可写层,类似「进程」。
- 仓库(registry):存放镜像的地方,Docker Hub 是公共仓库。
docker pull nginx:1.27 # 拉镜像
docker images # 本地镜像
docker run -d nginx:1.27 # 由镜像启动容器
docker ps # 运行中的容器
docker ps -a # 包括已退出的
二、docker run 的四个关键参数
docker run -d --name web -p 8080:80 -v /data/html:/usr/share/nginx/html nginx:1.27
| 参数 | 作用 |
|---|---|
-d | 后台运行(detach) |
--name web | 给容器起名,方便后续操作 |
-p 8080:80 | 宿主机 8080 → 容器 80 |
-v 宿主:容器 | 挂载目录,数据持久化 |
-p 的格式是「宿主机端口:容器端口」,写反了访问不到。只写 -p 80 时 Docker 会随机分配宿主机端口。
另外常用:--restart=always(开机/崩溃自动重启)、-e KEY=VALUE(环境变量)、--network(网络)。
三、排查三件套
docker ps -a # 有没有退出,退出码是多少
docker logs -f --tail 100 web # 看输出
docker exec -it web /bin/bash # 进容器(没有 bash 用 sh)
退出码很有信息量:0 正常结束、1 应用报错、137 被 OOM 或 kill -9、143 收到 SIGTERM。
容器里没有 bash 时用 sh;连 sh 都没有(scratch/distroless 镜像)就只能靠日志,或者用 docker cp 拷文件出来看。
四、容器为什么启动就退出
核心概念:容器的生命周期 = 主进程的生命周期,主进程结束,容器就退出。
- 命令是
nginx -g 'daemon off;'这类前台命令才行;写成后台启动(如service nginx start)会立刻退出。 CMD写成了bash,没有 TTY 就直接结束。- 应用启动报错(配置错、端口占用、连不上数据库),日志里有原因。
- 内存不足被 OOM kill,
docker inspect看OOMKilled。
排查顺序:ps -a 看状态 → logs 看输出 → 手动 run -it image sh 进去跑一遍启动命令。
五、数据持久化
容器删了,可写层里的数据就没了。要保留必须挂载:
# 绑定挂载(宿主机目录,直观、便于备份)
-v /data/mysql:/var/lib/mysql
# 命名卷(由 Docker 管理,跨平台更省心)
-v mysql-data:/var/lib/mysql
绑定挂载要注意宿主机目录的权限,MySQL、Postgres 常因为目录属主不对启动失败。命名卷则不用操心路径,但位置不直观(docker volume inspect 可查)。
六、几个日常操作
docker stop web && docker rm web # 停止并删除
docker rm -f web # 强制删除运行中的
docker rmi nginx:1.27 # 删镜像
docker system df # 看空间占用
docker system prune -a # 清理无用镜像/容器(慎用)
docker cp web:/etc/nginx/nginx.conf . # 从容器拷文件
docker inspect web --format '{{.State.Status}}'
docker system prune -a 会删掉所有未被使用的镜像,包括你之后还要用的,执行前看清提示。
七、网络
docker network create appnet
docker run -d --name db --network appnet postgres:16
docker run -d --name api --network appnet myapi
同一自定义网络内可以用容器名当主机名互相访问(db:5432),比记 IP 方便。默认的 bridge 网络不支持名字解析,这是「连不上数据库」的常见原因。
八、什么时候该用 Docker
- 环境一致性要求高(开发/测试/生产同镜像)。
- 需要快速启停多个服务、做隔离。
- CI 里跑构建与测试。
不适合:需要直接访问硬件、对性能极度敏感、或者只是跑一个静态文件服务(用 Nginx 直接托管更轻)。
小结
镜像是模板、容器是进程;-d -p -v --name 四个参数覆盖大部分场景;容器退出先看 logs 和退出码;数据必须挂载;同一自定义网络内用容器名互访。