Docker 问题排查手册:从安装到部署的常用命令全整理
Docker 常见问题汇总|附完整命令
Docker 是目前最常用的容器化技术之一,广泛应用于开发环境搭建、微服务部署、持续集成、测试环境隔离以及生产环境交付。它可以将应用程序及其依赖环境打包成镜像,并以容器的形式快速运行,从而解决“在我电脑上能跑,到服务器就不行”的环境一致性问题。
不过,很多人在实际使用 Docker 时,经常会遇到安装、镜像、容器、网络、数据卷、权限、日志、清理、部署等方面的问题。本文将围绕 Docker 日常使用中的高频问题进行整理,并附上常用完整命令,方便开发、测试、运维人员快速查阅。
一、Docker 基础概念常见问题
1. Docker 是什么?
Docker 是一个开源的容器化平台,它可以将应用程序、运行环境、系统依赖、配置文件等打包成一个标准化的镜像,然后通过容器运行。
简单理解:
- 镜像 Image:类似应用安装包,包含应用和依赖环境。
- 容器 Container:镜像运行后的实例。
- 仓库 Registry:存放镜像的地方,如 Docker Hub、阿里云镜像仓库、Harbor。
- Dockerfile:用于构建镜像的脚本文件。
- 数据卷 Volume:用于持久化容器数据。
- 网络 Network:用于容器之间、容器与宿主机之间通信。
2. Docker 和虚拟机有什么区别?
Docker 容器不是完整虚拟机,它共享宿主机操作系统内核,因此启动速度快、资源占用低。
| 对比项 | Docker 容器 | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 资源占用 | 较低 | 较高 |
| 隔离级别 | 进程级隔离 | 系统级隔离 |
| 操作系统 | 共享宿主机内核 | 每台虚拟机独立系统 |
| 适用场景 | 应用部署、微服务、CI/CD | 完整系统隔离、传统虚拟化 |
二、Docker 安装与启动问题
1. 如何查看 Docker 是否安装成功?
docker --version
或:
docker version
如果能够看到 Docker Client 和 Server 版本信息,说明 Docker 已正确安装并启动。
2. 如何启动 Docker 服务?
在 Linux 系统中可以使用:
sudo systemctl start docker
设置 Docker 开机自启动:
sudo systemctl enable docker
查看 Docker 服务状态:
sudo systemctl status docker
重启 Docker 服务:
sudo systemctl restart docker
停止 Docker 服务:
sudo systemctl stop docker
3. 普通用户执行 docker 命令提示权限不足怎么办?
常见报错如下:
permission denied while trying to connect to the Docker daemon socket
原因是当前用户没有访问 Docker 守护进程的权限。可以将当前用户加入 docker 用户组:
sudo usermod -aG docker $USER
然后退出当前终端,重新登录,或执行:
newgrp docker
再次测试:
docker ps
注意:将用户加入 docker 组后,该用户基本拥有等同 root 的容器管理权限,应谨慎操作。
三、Docker 镜像常见问题
1. 如何搜索镜像?
docker search nginx
示例:
docker search mysql
docker search redis
docker search openjdk
2. 如何拉取镜像?
docker pull nginx
指定版本:
docker pull nginx:1.25
拉取 MySQL 8:
docker pull mysql:8.0
拉取 Redis:
docker pull redis:7
如果不指定标签,默认拉取 latest:
docker pull nginx:latest
3. 如何查看本地镜像?
docker images
或:
docker image ls
查看镜像详细信息:
docker image inspect nginx:latest
4. 如何删除镜像?
删除指定镜像:
docker rmi nginx:latest
通过镜像 ID 删除:
docker rmi 镜像ID
强制删除镜像:
docker rmi -f 镜像ID
删除所有未被使用的镜像:
docker image prune
强制删除所有未使用镜像:
docker image prune -a
5. 镜像删除失败怎么办?
如果镜像正在被容器使用,会出现类似错误:
conflict: unable to remove repository reference
解决方法是先查看使用该镜像的容器:
docker ps -a
停止相关容器:
docker stop 容器ID或容器名
删除相关容器:
docker rm 容器ID或容器名
然后再删除镜像:
docker rmi 镜像ID
四、Docker 容器常见问题
1. 如何运行一个容器?
运行 Nginx 容器:
docker run -d --name nginx-test -p 8080:80 nginx
参数说明:
-d:后台运行--name nginx-test:指定容器名称-p 8080:80:将宿主机 8080 端口映射到容器 80 端口nginx:使用的镜像名称
访问:
curl http://localhost:8080
2. 如何查看正在运行的容器?
docker ps
查看所有容器,包括已停止的容器:
docker ps -a
只显示容器 ID:
docker ps -q
查看所有容器 ID:
docker ps -aq
3. 如何停止容器?
docker stop nginx-test
或:
docker stop 容器ID
停止所有正在运行的容器:
docker stop $(docker ps -q)
4. 如何启动已停止的容器?
docker start nginx-test
重启容器:
docker restart nginx-test
5. 如何删除容器?
删除已停止容器:
docker rm nginx-test
强制删除正在运行的容器:
docker rm -f nginx-test
删除所有已停止容器:
docker container prune
删除所有容器:
docker rm -f $(docker ps -aq)
注意:删除容器不会自动删除镜像,但容器内未挂载的数据可能会丢失。
6. 如何进入容器内部?
进入正在运行的容器:
docker exec -it nginx-test /bin/bash
如果容器没有 bash,可以使用 sh:
docker exec -it nginx-test /bin/sh
查看容器内文件:
ls
pwd
cat /etc/os-release
退出容器:
exit
7. docker attach 和 docker exec 有什么区别?
docker attach 会连接到容器主进程终端,如果退出方式不当,可能导致容器停止。
docker attach 容器名
docker exec 是在容器中启动一个新的命令进程,更适合日常排查:
docker exec -it 容器名 /bin/bash
通常推荐使用 docker exec。
五、Docker 端口映射问题
1. 容器启动后访问不了服务怎么办?
首先确认容器是否运行:
docker ps
查看端口映射:
docker port 容器名
检查容器日志:
docker logs 容器名
确认宿主机端口是否监听:
ss -lntp
或:
netstat -lntp
如果容器内服务只监听 127.0.0.1,外部可能无法访问。应让服务监听 0.0.0.0。
2. 如何映射端口?
格式:
docker run -p 宿主机端口:容器端口 镜像名
示例:
docker run -d --name web -p 8080:80 nginx
多个端口映射:
docker run -d --name app -p 8080:8080 -p 9000:9000 my-app:latest
只允许本机访问:
docker run -d --name web -p 127.0.0.1:8080:80 nginx
3. 端口被占用怎么办?
查看端口占用:
sudo lsof -i :8080
或:
sudo ss -lntp | grep 8080
结束占用进程:
sudo kill -9 进程ID
也可以更换宿主机端口:
docker run -d --name nginx-test -p 8081:80 nginx
六、Docker 数据卷与文件挂载问题
1. 容器删除后数据会丢失吗?
如果数据只保存在容器内部,删除容器后数据会丢失。因此数据库、上传文件、配置文件等通常需要挂载到宿主机目录或 Docker Volume。
2. 如何使用宿主机目录挂载?
docker run -d \
--name nginx-web \
-p 8080:80 \
-v /opt/nginx/html:/usr/share/nginx/html \
nginx
含义:
/opt/nginx/html:宿主机目录/usr/share/nginx/html:容器内目录
如果宿主机目录不存在,Docker 会自动创建,但可能会产生权限问题。
3. 如何使用 Docker Volume?
创建数据卷:
docker volume create mysql-data
查看数据卷:
docker volume ls
查看数据卷详情:
docker volume inspect mysql-data
使用数据卷运行 MySQL:
docker run -d \
--name mysql8 \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql-data:/var/lib/mysql \
mysql:8.0
删除数据卷:
docker volume rm mysql-data
清理未使用的数据卷:
docker volume prune
4. 挂载目录后容器无法写入怎么办?
通常是权限问题。可以修改宿主机目录权限:
sudo chmod -R 755 /opt/nginx/html
如果仍然无法写入,可以临时设置更宽松权限:
sudo chmod -R 777 /opt/nginx/html
更推荐修改目录属主:
sudo chown -R 1000:1000 /opt/app/data
具体 UID/GID 需要根据容器内运行用户决定:
docker exec -it 容器名 id
七、Docker 日志常见问题
1. 如何查看容器日志?
docker logs 容器名
实时查看日志:
docker logs -f 容器名
查看最近 100 行:
docker logs --tail=100 容器名
查看带时间戳日志:
docker logs -t 容器名
组合使用:
docker logs -f --tail=200 -t 容器名
2. 容器日志太大怎么办?
Docker 默认日志驱动可能会不断写入 JSON 日志文件,时间久了可能占满磁盘。
查看容器日志文件位置:
docker inspect --format='{{.LogPath}}' 容器名
清空日志文件:
sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' 容器名)
推荐配置日志轮转,编辑 Docker 配置文件:
sudo mkdir -p /etc/docker
sudo vi /etc/docker/daemon.json
写入:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
重启 Docker:
sudo systemctl daemon-reload
sudo systemctl restart docker
八、Docker 网络常见问题
1. 如何查看 Docker 网络?
docker network ls
查看网络详情:
docker network inspect bridge
2. 如何创建自定义网络?
docker network create app-net
指定网段:
docker network create \
--subnet=172.20.0.0/16 \
app-net
3. 容器之间如何通过名称访问?
如果容器在同一个自定义网络中,可以直接通过容器名访问。
创建网络:
docker network create app-net
运行 Redis:
docker run -d \
--name redis \
--network app-net \
redis:7
运行应用容器:
docker run -d \
--name app \
--network app-net \
my-app:latest
应用中可以使用:
redis:6379
访问 Redis,而不需要写 IP 地址。
4. 如何将已有容器加入网络?
docker network connect app-net 容器名
断开网络:
docker network disconnect app-net 容器名
九、Dockerfile 常见问题
1. 一个简单的 Dockerfile 示例
以 Spring Boot 项目为例:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/app.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
构建镜像:
docker build -t my-spring-app:1.0 .
运行容器:
docker run -d \
--name my-spring-app \
-p 8080:8080 \
my-spring-app:1.0
2. Dockerfile 中 CMD 和 ENTRYPOINT 有什么区别?
CMD 提供容器默认执行命令,可以被 docker run 后面的命令覆盖。
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT 更像固定入口,不容易被覆盖,适合作为容器主程序。
ENTRYPOINT ["java", "-jar", "app.jar"]
两者也可以配合使用:
ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]
3. 如何减少镜像体积?
常见做法:
- 使用更小的基础镜像,如
alpine、slim - 使用多阶段构建
- 减少无用依赖
- 合并 RUN 命令
- 清理缓存文件
Go 项目多阶段构建示例:
FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go build -o app main.go
FROM alpine:3.20
WORKDIR /app
COPY --from=builder /src/app /app/app
EXPOSE 8080
ENTRYPOINT ["/app/app"]
构建:
docker build -t go-app:1.0 .
十、Docker Compose 常见问题
1. Docker Compose 是什么?
Docker Compose 是 Docker 官方提供的多容器编排工具。它通过 docker-compose.yml 文件定义多个服务、网络、数据卷等,适合本地开发环境和中小型服务部署。
2. 一个 Nginx + MySQL 的 Compose 示例
创建文件:
mkdir docker-demo
cd docker-demo
vi docker-compose.yml
内容如下:
services:
nginx:
image: nginx:1.25
container_name: demo-nginx
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
networks:
- demo-net
mysql:
image: mysql:8.0
container_name: demo-mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_DATABASE: "demo"
volumes:
- mysql-data:/var/lib/mysql
networks:
- demo-net
volumes:
mysql-data:
networks:
demo-net:
启动:
docker compose up -d
查看服务:
docker compose ps
查看日志:
docker compose logs -f
停止服务:
docker compose down
停止并删除数据卷:
docker compose down -v
重新构建并启动:
docker compose up -d --build
十一、Docker 清理与磁盘空间问题
1. 如何查看 Docker 占用空间?
docker system df
查看更详细信息:
docker system df -v
2. 如何清理未使用资源?
清理停止的容器、未使用网络、悬空镜像、构建缓存:
docker system prune
强制清理,不询问:
docker system prune -f
清理所有未使用镜像:
docker system prune -a
同时清理数据卷:
docker system prune -a --volumes
注意:
--volumes可能删除未被容器使用的数据卷,执行前务必确认数据是否重要。
3. 如何清理构建缓存?
docker builder prune
强制清理:
docker builder prune -f
清理所有构建缓存:
docker builder prune -a
十二、Docker 容器自启动问题
1. 如何设置容器开机自启动?
运行容器时指定:
docker run -d \
--name nginx-auto \
--restart=always \
-p 8080:80 \
nginx
对已有容器设置:
docker update --restart=always nginx-auto
取消自启动:
docker update --restart=no nginx-auto
2. restart 策略有哪些?
| 策略 | 含义 |
|---|---|
| no | 默认策略,不自动重启 |
| always | 无论退出原因,都会重启 |
| unless-stopped | 除非手动停止,否则自动重启 |
| on-failure | 只有异常退出时才重启 |
示例:
docker run -d \
--name app \
--restart=unless-stopped \
my-app:latest
十三、Docker 常用排查命令
1. 查看容器详细信息
docker inspect 容器名
查看 IP 地址:
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器名
2. 查看容器资源占用
docker stats
查看指定容器:
docker stats 容器名
3. 查看容器进程
docker top 容器名
4. 在容器和宿主机之间复制文件
从宿主机复制到容器:
docker cp ./app.conf 容器名:/app/app.conf
从容器复制到宿主机:
docker cp 容器名:/app/logs ./logs
十四、常见应用部署命令示例
1. 部署 MySQL
docker run -d \
--name mysql8 \
--restart=always \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=testdb \
-v mysql-data:/var/lib/mysql \
mysql:8.0
进入 MySQL:
docker exec -it mysql8 mysql -uroot -p
2. 部署 Redis
docker run -d \
--name redis7 \
--restart=always \
-p 6379:6379 \
-v redis-data:/data \
redis:7 \
redis-server --appendonly yes
进入 Redis:
docker exec -it redis7 redis-cli
3. 部署 Nginx
docker run -d \
--name nginx \
--restart=always \
-p 80:80 \
-p 443:443 \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/conf:/etc/nginx/conf.d \
-v /opt/nginx/logs:/var/log/nginx \
nginx:1.25
测试配置:
docker exec -it nginx nginx -t
重载配置:
docker exec -it nginx nginx -s reload
十五、Docker 使用建议
-
生产环境不要长期使用 latest 标签
推荐使用明确版本,例如mysql:8.0、nginx:1.25,避免镜像更新导致不可预期问题。 -
重要数据必须挂载数据卷或宿主机目录
数据库、上传文件、配置文件、证书等不要只放在容器内部。 -
为容器设置 restart 策略
生产环境建议使用--restart=always或--restart=unless-stopped。 -
限制日志大小
避免 Docker 日志无限增长占满磁盘。 -
使用自定义网络连接多个容器
不建议依赖容器 IP,因为容器重启后 IP 可能变化。 -
定期清理无用镜像和容器
但执行清理前要确认是否包含重要数据卷。 -
尽量使用 Docker Compose 管理多容器应用
这样配置更清晰,部署和迁移更方便。
总结
Docker 极大提升了应用交付和环境管理效率,但在实际使用过程中,镜像拉取、容器启动、端口映射、数据挂载、日志管理、网络通信、磁盘清理等问题非常常见。掌握本文中的常用命令和排查思路,可以快速解决大多数 Docker 日常问题。
对于个人开发者来说,Docker 可以快速搭建 MySQL、Redis、Nginx、RabbitMQ、Elasticsearch 等开发环境;对于团队和企业来说,Docker 可以统一开发、测试、生产环境,配合 Docker Compose、Kubernetes、CI/CD 工具进一步提升交付效率。
建议在使用 Docker 时始终牢记三点:镜像要可追溯,数据要持久化,日志要可控制。只要做好这些基础规范,Docker 就能成为稳定、高效、可靠的应用部署工具。