上一篇 下一篇 分享链接 返回 返回顶部

Docker 入门避坑指南:新手常见问题一次讲清

发布人:慈云数据-客服中心 发布时间:22小时前 阅读量:3

Docker 常见问题汇总|零基础可学

Docker 是近几年后端开发、运维部署、测试环境搭建中非常常见的工具。对于零基础学习者来说,Docker 一开始看起来像是“虚拟机”“服务器”“镜像仓库”“命令行工具”的混合体,概念比较多,但只要理解了它的核心思想,入门并不困难。

本文将以“常见问题汇总”的形式,围绕 Docker 的基础概念、安装使用、镜像与容器、网络、数据卷、Dockerfile、Docker Compose、常见报错以及学习建议等内容进行整理,适合零基础读者系统学习和查漏补缺。


一、Docker 是什么?

Docker 是一种容器化技术,它可以把应用程序以及运行应用所需的环境、依赖、配置一起打包起来,然后在不同机器上快速运行。

简单来说,Docker 可以帮助我们解决一个经典问题:

“为什么我的电脑上可以运行,到了服务器上就不行?”

在传统开发中,一个项目可能依赖特定版本的 Java、Python、Node.js、MySQL、Redis 等环境。开发环境、测试环境、生产环境稍有差异,就可能出现各种问题。Docker 的作用就是把这些环境封装成一个相对独立的“容器”,让应用在不同环境中保持一致。


二、Docker 和虚拟机有什么区别?

很多初学者会把 Docker 理解成虚拟机,其实二者有相似之处,但本质不同。

1. 虚拟机

虚拟机会模拟一整套操作系统。例如你在 Windows 上安装 VMware,然后在里面运行 Ubuntu。虚拟机通常包含完整的操作系统内核、系统服务和应用环境。

优点是隔离性强,缺点是资源占用高、启动慢。

2. Docker 容器

Docker 容器不是完整虚拟机,它共享宿主机的操作系统内核,只隔离进程、文件系统、网络等运行环境。

优点是轻量、启动快、资源占用少,缺点是隔离性相比虚拟机略弱。

3. 简单对比

对比项 虚拟机 Docker 容器
启动速度 通常较慢 通常很快
资源占用 较高 较低
是否包含完整系统
隔离程度 更强 较强
使用场景 多系统模拟、强隔离 应用部署、环境统一

三、Docker 的核心概念有哪些?

学习 Docker,最重要的是理解三个核心概念:镜像、容器、仓库。


1. 镜像 Image

镜像可以理解为一个“模板”或“安装包”。它包含运行某个应用所需要的文件系统、依赖环境和默认配置。

例如:

  • mysql:8.0 是 MySQL 8.0 的镜像;
  • redis:7 是 Redis 7 的镜像;
  • nginx:latest 是 Nginx 最新版本镜像。

镜像本身是静态的,不能直接修改运行状态。


2. 容器 Container

容器是镜像运行起来后的实例。

可以这样理解:

镜像像是类,容器像是对象;
镜像像是安装包,容器像是运行中的软件。

一个镜像可以创建多个容器。例如你可以用同一个 Nginx 镜像启动多个 Nginx 容器,每个容器互相隔离。


3. 仓库 Registry

仓库用于存放和分发镜像。最常见的是 Docker Hub,类似于镜像世界的“应用商店”。

常见镜像仓库包括:

  • Docker Hub;
  • 阿里云容器镜像服务;
  • 腾讯云镜像仓库;
  • Harbor 私有仓库。

四、Docker 常用命令有哪些?

下面整理一些最常见的 Docker 命令,适合初学者记忆。


1. 查看 Docker 版本

docker version

或者:

docker --version

2. 查看 Docker 运行信息

docker info

该命令可以查看 Docker 的存储驱动、镜像数量、容器数量、系统信息等。


3. 搜索镜像

docker search nginx

这条命令会在镜像仓库中搜索 Nginx 相关镜像。


4. 拉取镜像

docker pull nginx

如果不指定版本,默认拉取 latest 标签版本。

指定版本:

docker pull mysql:8.0

5. 查看本地镜像

docker images

或者:

docker image ls

6. 删除镜像

docker rmi 镜像ID

如果镜像正在被容器使用,需要先删除相关容器。


7. 创建并运行容器

docker run nginx

但这样运行会占用当前终端。通常会使用后台模式:

docker run -d nginx

8. 端口映射运行容器

例如运行 Nginx,并把宿主机的 8080 端口映射到容器内的 80 端口:

docker run -d -p 8080:80 nginx

访问:

http://localhost:8080

即可看到 Nginx 页面。


9. 查看正在运行的容器

docker ps

查看所有容器,包括已停止的:

docker ps -a

10. 停止容器

docker stop 容器ID或容器名

11. 启动已停止的容器

docker start 容器ID或容器名

12. 重启容器

docker restart 容器ID或容器名

13. 删除容器

docker rm 容器ID或容器名

如果容器正在运行,需要先停止,或者强制删除:

docker rm -f 容器ID

14. 查看容器日志

docker logs 容器ID或容器名

实时查看日志:

docker logs -f 容器ID或容器名

15. 进入容器内部

docker exec -it 容器ID或容器名 bash

如果容器中没有 bash,可以使用 sh:

docker exec -it 容器ID或容器名 sh

五、Docker run 常见参数是什么意思?

docker run 是最常用也最重要的命令之一,常见参数如下。


1. -d

后台运行容器。

docker run -d nginx

2. -p

端口映射。

docker run -d -p 8080:80 nginx

含义是:

宿主机端口:容器端口

3. --name

给容器指定名称。

docker run -d --name my-nginx nginx

以后可以用 my-nginx 来操作容器。


4. -v

挂载数据卷或目录。

docker run -d -v /host/data:/container/data nginx

含义是:

宿主机目录:容器内目录

这样可以实现数据持久化。


5. -e

设置环境变量。

例如运行 MySQL:

docker run -d \
  --name mysql8 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -p 3306:3306 \
  mysql:8.0

6. --restart

设置容器重启策略。

docker run -d --restart=always nginx

常见取值:

参数 含义
no 不自动重启
always 总是自动重启
unless-stopped 除非手动停止,否则自动重启
on-failure 容器异常退出时重启

六、Docker 容器中的数据会丢失吗?

会,也不会,取决于你如何保存数据。

容器本身是临时性的。如果你把数据直接写在容器内部,当容器被删除后,数据也会随之丢失。因此,数据库、上传文件、配置文件等重要数据,通常需要使用数据卷或目录挂载。


七、什么是 Docker 数据卷?

Docker 数据卷 Volume 是 Docker 提供的数据持久化机制。它可以把容器中的数据保存到宿主机上,即使容器删除,数据仍然存在。


1. 创建数据卷

docker volume create mydata

2. 查看数据卷

docker volume ls

3. 使用数据卷

docker run -d \
  --name mysql8 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql_data:/var/lib/mysql \
  mysql:8.0

这里的 mysql_data 就是数据卷,MySQL 数据会保存到该卷中。


4. 数据卷和目录挂载有什么区别?

类型 示例 特点
数据卷 -v mysql_data:/var/lib/mysql Docker 管理,适合通用持久化
目录挂载 -v /data/mysql:/var/lib/mysql 用户指定路径,便于直接查看文件

一般来说,开发环境常用目录挂载,生产环境可以根据需求选择数据卷或指定目录。


八、Docker 网络是什么?

Docker 容器之间也需要通信,例如 Web 应用要连接 MySQL、Redis。Docker 提供了多种网络模式,其中最常见的是 bridge 网络。


1. 查看 Docker 网络

docker network ls

2. 创建自定义网络

docker network create my-net

3. 容器加入同一个网络

docker run -d --name mysql --network my-net mysql:8.0
docker run -d --name app --network my-net my-app

在同一个自定义网络中,容器可以通过容器名互相访问。例如 app 容器可以通过 mysql:3306 访问 MySQL。


4. 为什么推荐使用自定义网络?

因为在自定义网络中,Docker 会自动提供 DNS 解析能力,容器之间可以直接使用容器名访问,这比写 IP 地址更稳定。


九、Dockerfile 是什么?

Dockerfile 是用来构建镜像的脚本文件。它通过一系列指令描述如何创建一个镜像。

例如,一个简单的 Node.js 项目 Dockerfile:

FROM node:18

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

十、Dockerfile 常见指令有哪些?

1. FROM

指定基础镜像。

FROM nginx

所有 Dockerfile 通常都要以 FROM 开始。


2. WORKDIR

指定工作目录。

WORKDIR /app

后续命令会在该目录下执行。


3. COPY

复制文件到镜像中。

COPY . /app

4. RUN

构建镜像时执行命令。

RUN apt-get update && apt-get install -y curl

5. EXPOSE

声明容器内部使用的端口。

EXPOSE 8080

注意:EXPOSE 只是声明,并不会自动映射端口,真正映射端口仍需要 -p


6. CMD

指定容器启动时默认执行的命令。

CMD ["npm", "start"]

7. ENTRYPOINT

也用于指定容器启动命令,通常适合封装固定入口程序。

CMDENTRYPOINT 有区别,但初学阶段可以先记住:大多数普通应用使用 CMD 就够了。


十一、如何构建自己的 Docker 镜像?

假设当前目录下有 Dockerfile,可以执行:

docker build -t my-app:1.0 .

参数解释:

  • -t my-app:1.0:给镜像命名并打标签;
  • .:表示构建上下文是当前目录。

构建完成后查看镜像:

docker images

运行镜像:

docker run -d -p 8080:8080 my-app:1.0

十二、Docker Compose 是什么?

当项目只有一个容器时,使用 docker run 比较简单。但真实项目往往不止一个容器,例如:

  • Web 应用;
  • MySQL;
  • Redis;
  • Nginx;
  • RabbitMQ。

如果每个容器都手动写 docker run,命令会很长也不方便维护。Docker Compose 就是用一个配置文件统一管理多个容器。


十三、Docker Compose 示例

下面是一个简单的 docker-compose.yml 示例:

services:
  mysql:
    image: mysql:8.0
    container_name: mysql8
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: testdb
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:7
    container_name: redis7
    ports:
      - "6379:6379"

volumes:
  mysql_data:

启动:

docker compose up -d

停止:

docker compose down

查看日志:

docker compose logs -f

十四、Docker 常见问题与解决方法


问题 1:运行 Docker 命令提示 permission denied

常见报错:

permission denied while trying to connect to the Docker daemon socket

原因通常是当前用户没有权限访问 Docker。

解决方式之一:

sudo docker ps

如果不想每次都加 sudo,可以把当前用户加入 docker 用户组:

sudo usermod -aG docker $USER

然后重新登录终端或重启系统。


问题 2:端口被占用怎么办?

报错可能类似:

Bind for 0.0.0.0:8080 failed: port is already allocated

说明宿主机的 8080 端口已经被其他程序占用。

解决方法:

  1. 换一个宿主机端口:
docker run -d -p 8081:80 nginx
  1. 查找占用端口的进程并关闭。

Linux/macOS:

lsof -i :8080

Windows 可以使用:

netstat -ano | findstr 8080

问题 3:容器启动后马上退出

可以先查看容器状态:

docker ps -a

再查看日志:

docker logs 容器ID

常见原因包括:

  • 启动命令执行失败;
  • 配置文件错误;
  • 环境变量缺失;
  • 应用程序崩溃;
  • 容器内主进程退出。

Docker 容器依赖前台主进程运行,如果主进程退出,容器也会退出。


问题 4:为什么修改容器内文件后,删除容器就没了?

因为容器本身不是用来长期保存数据的。如果需要保存文件,应该使用数据卷或目录挂载。

例如:

docker run -d \
  -v /my/data:/app/data \
  my-app

这样容器内 /app/data 的数据会保存到宿主机 /my/data


问题 5:镜像太大怎么办?

镜像过大会导致构建慢、传输慢、部署慢。

优化方式:

  1. 使用更小的基础镜像,例如 alpine
  2. 减少不必要依赖;
  3. 合并清理命令;
  4. 使用 .dockerignore 排除无关文件;
  5. 使用多阶段构建。

例如:

FROM node:18-alpine

但需要注意,alpine 使用 musl libc,某些依赖可能存在兼容问题。


问题 6:什么是 .dockerignore

.dockerignore 类似 .gitignore,用于告诉 Docker 构建镜像时忽略哪些文件。

示例:

node_modules
.git
logs
*.log
dist

这样可以减少构建上下文大小,提高构建速度,并避免把敏感文件打进镜像。


问题 7:容器之间无法访问怎么办?

排查步骤:

  1. 确认容器是否在运行:
docker ps
  1. 确认容器是否在同一个网络:
docker inspect 容器名
  1. 推荐创建自定义网络:
docker network create app-net
  1. 让容器加入同一个网络:
docker run -d --name redis --network app-net redis
docker run -d --name app --network app-net my-app

此时 app 可以通过 redis:6379 访问 Redis。


问题 8:Docker 容器时间不对怎么办?

可以挂载宿主机时区文件:

docker run -d \
  -v /etc/localtime:/etc/localtime:ro \
  nginx

也可以通过环境变量设置时区:

docker run -d \
  -e TZ=Asia/Shanghai \
  nginx

具体是否生效取决于镜像本身支持情况。


问题 9:如何清理 Docker 占用空间?

Docker 使用久了,会积累很多停止的容器、无用镜像、构建缓存和数据卷。

查看磁盘占用:

docker system df

清理未使用资源:

docker system prune

清理更彻底,包括未使用镜像:

docker system prune -a

清理未使用数据卷:

docker volume prune

注意:清理前一定要确认数据是否还需要,尤其是数据卷。


问题 10:latest 标签是不是最新版本?

不一定。

latest 只是一个标签名,并不一定代表真正意义上的最新版本。它由镜像维护者决定指向哪个版本。

生产环境建议使用明确版本,例如:

mysql:8.0
redis:7.2
nginx:1.25

这样可以避免某次重新拉取镜像后版本变化导致问题。


十五、零基础学习 Docker 的建议路线

如果你是零基础,可以按以下顺序学习:

  1. 先理解镜像、容器、仓库三个概念;
  2. 学会 docker pulldocker rundocker psdocker stopdocker rm
  3. 用 Docker 跑 Nginx、MySQL、Redis;
  4. 学习端口映射和数据卷;
  5. 学习容器网络;
  6. 学习 Dockerfile,构建自己的镜像;
  7. 学习 Docker Compose 管理多容器项目;
  8. 最后再了解镜像优化、日志管理、安全配置和 CI/CD 集成。

不要一开始就追求掌握所有底层原理。Docker 的学习适合“边用边学”,先能跑起来,再逐渐理解为什么这样设计。


十六、一个适合新手的练习案例

目标:使用 Docker 启动一个 Nginx,并挂载自己的网页文件。

1. 创建目录

mkdir -p ~/docker-demo/html

2. 创建网页文件

echo "Hello Docker" > ~/docker-demo/html/index.html

3. 启动 Nginx 容器

docker run -d \
  --name my-nginx \
  -p 8080:80 \
  -v ~/docker-demo/html:/usr/share/nginx/html \
  nginx

4. 浏览器访问

http://localhost:8080

如果看到 Hello Docker,说明你已经成功使用 Docker 运行了一个 Web 服务,并完成了目录挂载。


十七、Docker 使用中的几个好习惯

  1. 容器命名要清晰
    使用 --name 给容器命名,便于管理。

  2. 生产环境不要依赖 latest
    尽量使用明确版本号。

  3. 重要数据一定要挂载
    数据库、上传文件、配置文件不要只放在容器内部。

  4. 定期清理无用资源
    防止磁盘被镜像、容器、缓存占满。

  5. 编写 Dockerfile 时注意精简
    少装无用依赖,合理使用 .dockerignore

  6. 优先使用 Docker Compose 管理多容器项目
    可读性和可维护性更好。

  7. 不要把密码写死在镜像中
    敏感信息建议通过环境变量、配置中心或密钥管理方式注入。


十八、总结

Docker 的核心价值在于:统一环境、快速部署、隔离运行、方便迁移。对于开发者来说,它可以减少环境配置时间;对于运维人员来说,它可以提升部署效率;对于团队协作来说,它可以让每个人在相同环境下工作。

零基础学习 Docker 时,不必被复杂概念吓到。只要先掌握镜像、容器、仓库,再熟悉常用命令,能够运行 Nginx、MySQL、Redis 这类基础服务,就已经迈出了非常重要的一步。之后再逐步学习 Dockerfile、Docker Compose、网络、数据卷和镜像优化,就可以把 Docker 应用到真实项目中。

一句话记住 Docker:

镜像负责打包环境,容器负责运行应用,数据卷负责保存数据,Compose 负责管理多个容器。

目录结构
全文