Docker 使用:镜像、容器、日志、exec 和数据卷
Docker 日常使用手册,涵盖镜像、容器、运行与日志命令、数据卷、网络、Compose 和常见故障排查。
Docker 是容器工具。它解决的是:把应用和运行依赖打包成镜像,再用相对一致的方式在本机、测试环境或服务器上启动。
先把几个对象分清楚:
image 镜像,应用和依赖的只读模板
container 容器,由镜像启动出来的运行实例
registry 镜像仓库,例如 Docker Hub、GHCR、私有 registry
volume 持久化数据卷
network 容器之间通信的网络
Dockerfile 构建镜像的配方
Compose 用一个 YAML 编排多个容器
镜像像“安装包”,容器像“跑起来的进程”。同一个镜像可以启动多个容器,每个容器有自己的文件系统、进程空间和网络配置。
什么时候用 Docker
适合用 Docker 的场景:
本机快速启动 MySQL、Redis、Postgres、Prometheus 等依赖
把应用和运行时依赖打包成镜像
复现线上环境
跑一次性工具或构建任务
在 CI 里启动服务做集成测试
用 docker compose 拉起一组开发环境
不适合把 Docker 当成:
虚拟机完整替代品
长期保存容器内临时文件的地方
解决所有部署问题
完整的安全隔离方案
常用占位符:
<image-name>
<container-name>
<container-id>
<tag>
<host-port>
<container-port>
<volume-name>
<network-name>
基本检查
查看版本:
docker version
docker --version
查看 Docker daemon 状态:
docker info
如果 docker version 只能看到客户端而没有服务端信息,通常是 Docker Desktop 没有启动,或者当前用户无权访问 Docker 守护进程。
查看磁盘占用:
docker system df
image:镜像管理
拉取镜像:
docker pull redis:7
docker pull postgres:16
查看本地镜像:
docker images
docker image ls
删除镜像:
docker rmi <image-name>:<tag>
docker image rm <image-id>
给镜像打 tag:
docker tag local-image:latest registry.example.com/team/app:v1
推送镜像:
docker push registry.example.com/team/app:v1
查看镜像详情:
docker image inspect <image-name>:<tag>
查看镜像构建层:
docker history <image-name>:<tag>
清理悬空镜像:
docker image prune
清理所有未使用镜像:
docker image prune -a
prune -a 会删掉所有当前没有容器引用的镜像,动手前先 docker images 和 docker system df。
container:容器管理
查看运行中的容器:
docker ps
查看所有容器,包括已经退出的:
docker ps -a
启动容器:
docker start <container-name>
停止容器:
docker stop <container-name>
重启容器:
docker restart <container-name>
删除已停止容器:
docker rm <container-name>
强制删除运行中的容器:
docker rm -f <container-name>
查看容器详情:
docker inspect <container-name>
查看容器资源占用:
docker stats
docker stats <container-name>
查看容器内进程:
docker top <container-name>
run:启动一个容器
最小启动:
docker run redis:7
后台运行:
docker run -d redis:7
指定名称:
docker run -d --name redis-dev redis:7
端口映射:
docker run -d --name nginx-dev -p 8080:80 nginx:alpine
含义:
-p 8080:80
宿主机 8080 端口 -> 容器 80 端口
环境变量:
docker run -d --name postgres-dev \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=app \
-p 5432:5432 \
postgres:16
启动后自动删除,适合一次性命令:
docker run --rm alpine:3.20 echo hello
交互式 shell:
docker run --rm -it ubuntu:24.04 bash
设置工作目录:
docker run --rm -it -w /work -v "$PWD:/work" node:22 bash
指定 entrypoint:
docker run --rm --entrypoint sh nginx:alpine
限制资源:
docker run -d --name app \
--cpus="2" \
--memory="2g" \
app:latest
常用参数:
-d 后台运行
--name 容器名
-p host:container 端口映射
-e KEY=value 环境变量
-v host:container 挂载目录或 volume
--rm 容器退出后自动删除
-it 交互式终端
--network 指定网络
--restart 重启策略
logs:看日志
查看日志:
docker logs <container-name>
持续跟随:
docker logs -f <container-name>
最近 100 行:
docker logs --tail 100 <container-name>
带时间戳:
docker logs -t <container-name>
从最近 10 分钟开始:
docker logs --since 10m <container-name>
看崩溃容器的第一步通常是:
docker ps -a
docker logs --tail 200 <container-name>
docker inspect <container-name>
docker logs 只能看到容器标准输出和标准错误。如果应用把日志写到文件里,就需要 exec 进去看文件,或者把日志目录挂出来。
exec 和 cp:进入容器、拷贝文件
进入运行中的容器:
docker exec -it <container-name> bash
如果没有 bash:
docker exec -it <container-name> sh
执行单条命令:
docker exec <container-name> env
docker exec <container-name> ps aux
从容器拷贝到本机:
docker cp <container-name>:/path/in/container ./local-path
从本机拷贝到容器:
docker cp ./local-file <container-name>:/path/in/container
查看容器里的文件变更:
docker diff <container-name>
volume:持久化数据
容器删除后,容器层里的数据也会消失。数据库、缓存、构建产物等需要持久化时,用 volume 或 bind mount。
创建 volume:
docker volume create postgres-data
查看 volume:
docker volume ls
查看详情:
docker volume inspect postgres-data
使用 volume:
docker run -d --name postgres-dev \
-e POSTGRES_PASSWORD=postgres \
-v postgres-data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
使用本机目录 bind mount:
docker run --rm -it \
-v "$PWD:/work" \
-w /work \
node:22 bash
区别:
volume Docker 管理存储位置,适合数据库数据
bind mount 显式挂载宿主机目录,适合开发时代码目录
删除 volume:
docker volume rm postgres-data
清理未使用 volume:
docker volume prune
删除 volume 前确认没有重要数据。数据库数据一旦删掉,通常不能靠 Docker 恢复。
network:容器通信
查看网络:
docker network ls
创建网络:
docker network create dev-net
让两个容器在同一个网络里:
docker run -d --name redis-dev --network dev-net redis:7
docker run --rm -it --network dev-net alpine:3.20 sh
在同一个 user-defined bridge network 里,容器可以通过容器名访问:
redis-cli -h redis-dev -p 6379
查看网络详情:
docker network inspect dev-net
把已运行容器接入网络:
docker network connect dev-net <container-name>
断开:
docker network disconnect dev-net <container-name>
删除网络:
docker network rm dev-net
build:用 Dockerfile 构建镜像
一个简单 Dockerfile:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["npm", "start"]
构建:
docker build -t my-app:dev .
指定 Dockerfile:
docker build -f Dockerfile.prod -t my-app:prod .
构建时传参数:
docker build \
--build-arg APP_VERSION=1.2.3 \
-t my-app:1.2.3 .
不使用缓存:
docker build --no-cache -t my-app:debug .
多平台构建常用 buildx:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/team/app:v1 \
--push .
Dockerfile 常见写法
.dockerignore 很重要,避免把依赖、构建产物、密钥上下文传进镜像构建:
node_modules/
dist/
.git/
.env
*.log
利用缓存,把依赖安装放在源码复制前:
COPY package*.json ./
RUN npm ci
COPY . .
多阶段构建,减少最终镜像体积:
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
运行非 root 用户:
RUN addgroup -S app && adduser -S app -G app
USER app
设置健康检查:
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://127.0.0.1:3000/health || exit 1
compose:一组服务一起跑
docker compose 适合本地开发环境:应用、数据库、缓存、消息队列一起启动。
示例 compose.yml:
services:
app:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://postgres:postgres@db:5432/app
REDIS_URL: redis://redis:6379
depends_on:
- db
- redis
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app
volumes:
- postgres-data:/var/lib/postgresql/data
redis:
image: redis:7
volumes:
postgres-data:
启动:
docker compose up
docker compose up -d
查看服务:
docker compose ps
看日志:
docker compose logs
docker compose logs -f app
进入服务容器:
docker compose exec app sh
重建:
docker compose build
docker compose up -d --build
停止:
docker compose down
停止并删除 volume:
docker compose down -v
down -v 会删除 Compose 管理的数据卷,数据库数据也会被清掉。开发环境可以用,真实数据不要随手执行。
常见服务启动例子
Redis:
docker run -d --name redis-dev -p 6379:6379 redis:7
MySQL:
docker run -d --name mysql-dev \
-e MYSQL_ROOT_PASSWORD=mysql \
-e MYSQL_DATABASE=app \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
mysql:8
Postgres:
docker run -d --name postgres-dev \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=app \
-p 5432:5432 \
-v postgres-data:/var/lib/postgresql/data \
postgres:16
Prometheus:
docker run -d --name prometheus-dev \
-p 9090:9090 \
-v "$PWD/prometheus.yml:/etc/prometheus/prometheus.yml" \
prom/prometheus
一次性跑命令:
docker run --rm -it -v "$PWD:/work" -w /work alpine:3.20 sh
清理
清理停止的容器:
docker container prune
清理未使用镜像:
docker image prune
清理未使用网络:
docker network prune
清理未使用 volume:
docker volume prune
清理所有未使用对象:
docker system prune
包括未使用镜像:
docker system prune -a
清理前先看空间:
docker system df
如果你不确定 volume 里有没有数据库数据,不要执行 volume prune。
排障场景
端口被占用
报错类似 port is already allocated。
先看哪个容器占了端口:
docker ps
也可以查本机端口:
lsof -i :8080
解决方式:
docker stop <container-name>
或者换宿主机端口:
docker run -p 8081:80 nginx:alpine
容器启动后马上退出
查看退出状态:
docker ps -a
docker logs --tail 200 <container-name>
docker inspect <container-name>
常见原因:
启动命令执行完了
环境变量缺失
配置文件路径不对
端口或权限问题
应用启动时报错
可以覆盖 entrypoint 进去检查镜像:
docker run --rm -it --entrypoint sh <image-name>:<tag>
容器里访问不了宿主机服务
macOS / Docker Desktop 常用:
host.docker.internal
例如:
curl http://host.docker.internal:3000
Linux 上可能需要使用主机网络:
docker run --network host <image-name>
或者显式配置网络和路由。
bind mount 后文件权限不对
容器内用户和宿主机用户 uid/gid 不一致时容易出现。可以查看:
id
docker exec <container-name> id
临时用当前用户启动:
docker run --rm -it \
-u "$(id -u):$(id -g)" \
-v "$PWD:/work" \
-w /work \
node:22 bash
生产镜像里更推荐明确创建非 root 用户,并让目录权限匹配。
镜像太大
常见处理:
使用更小 base image,例如 alpine、distroless
使用多阶段构建
清理包管理器缓存
.dockerignore 排除无关文件
不要把测试数据、源码历史、node_modules 整包复制进去
查看层大小:
docker history <image-name>:<tag>
需要看容器真实启动命令
docker inspect <container-name> \
--format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}'
也可以直接:
docker inspect <container-name>
重点看:
Config.Env
Config.Entrypoint
Config.Cmd
HostConfig.Binds
HostConfig.PortBindings
NetworkSettings
State
本地开发时常用顺序
第一次启动依赖:
docker compose up -d db redis
docker compose ps
docker compose logs -f db
调试应用容器:
docker compose build app
docker compose up app
docker compose exec app sh
重置开发数据库:
docker compose down -v
docker compose up -d db
清理无用对象:
docker system df
docker container prune
docker image prune