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

Docker 新手最容易踩的坑,一篇讲清楚怎么避开

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

Docker 使用避坑指南|零基础可学

在学习后端开发、运维部署、微服务、云原生等技术时,Docker 几乎是绕不开的工具。它可以把应用和运行环境一起打包,让程序在不同机器上尽可能保持一致,解决“我电脑上能跑,服务器上跑不了”的经典问题。

不过,对于零基础用户来说,Docker 刚开始看似简单:docker run 一条命令就能启动服务。但真正使用时,很容易遇到镜像拉不下来、容器数据丢失、端口冲突、容器删了服务就没了、权限不足、磁盘爆满等问题。

本文将从零基础角度出发,系统介绍 Docker 的核心概念、常用命令、实际使用中的常见坑,以及对应的避坑方法,帮助你少走弯路。


一、先搞懂 Docker 到底是什么

Docker 是一种容器化技术。你可以把它理解为一个“轻量级运行环境打包工具”。

传统部署方式通常是:

  1. 在服务器安装操作系统;
  2. 安装运行环境,比如 Java、Node.js、Python、MySQL;
  3. 配置环境变量;
  4. 上传代码;
  5. 启动服务。

这个过程中,任何一个环境差异都可能导致程序运行失败。

Docker 的思路是:
把应用程序、依赖环境、配置文件等打包成一个“镜像”,然后基于镜像启动“容器”。这样应用在哪里运行,都尽量保持一致。


二、Docker 的几个核心概念

学习 Docker,最容易混淆的是镜像、容器、仓库、数据卷这些概念。先把它们搞清楚,后面会轻松很多。

1. 镜像 Image

镜像可以理解为“模板”或“安装包”。

比如:

nginx:latest
mysql:8.0
redis:7
ubuntu:22.04

这些都是镜像。

镜像本身是静态的,不能直接提供服务。你需要基于镜像启动容器。


2. 容器 Container

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

举个例子:

  • mysql:8.0 是镜像;
  • 你通过它启动了一个 MySQL 服务,这个正在运行的 MySQL 就是容器。

一个镜像可以启动多个容器。就像一个安装包可以在多台电脑上安装出多个程序一样。


3. 仓库 Registry

仓库是存放镜像的地方。

最常见的是 Docker Hub,类似于 GitHub,只不过 GitHub 存代码,Docker Hub 存镜像。

当你执行:

docker pull nginx

Docker 就会从远程镜像仓库拉取 Nginx 镜像到本地。


4. 数据卷 Volume

数据卷用于持久化保存容器中的数据。

这是 Docker 使用中最重要的概念之一。

很多新手会以为:容器里产生的数据会一直存在。
实际上,如果你删除容器,容器内部的数据通常也会随之消失。

所以运行 MySQL、Redis、Nginx、应用日志等服务时,一定要考虑数据持久化。


三、Docker 安装后的第一个检查

安装 Docker 后,可以先执行:

docker version

查看 Docker 客户端和服务端版本。

再执行:

docker info

查看 Docker 运行状态。

如果出现权限问题,比如:

permission denied while trying to connect to the Docker daemon socket

说明当前用户没有权限访问 Docker 服务。

在 Linux 中可以执行:

sudo usermod -aG docker $USER

然后退出终端重新登录。

注意:把用户加入 docker 用户组等同于赋予较高系统权限,不要随便给不可信用户开放。


四、常用命令入门

1. 拉取镜像

docker pull nginx

指定版本:

docker pull nginx:1.25

如果不指定版本,默认使用 latest 标签。


2. 查看本地镜像

docker images

3. 启动容器

docker run nginx

这样会以前台方式运行,终端会被占用。

更常用的是后台运行:

docker run -d nginx

4. 查看正在运行的容器

docker ps

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

docker ps -a

5. 停止容器

docker stop 容器ID或容器名

6. 删除容器

docker rm 容器ID或容器名

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

docker rm -f 容器ID或容器名

7. 删除镜像

docker rmi 镜像ID或镜像名

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


五、新手最容易踩的坑

下面是 Docker 使用中非常常见的问题,也是本文的重点。


坑 1:以为容器删除后数据还在

这是 Docker 新手最容易踩的坑。

例如你运行 MySQL:

docker run -d \
  --name mysql-demo \
  -e MYSQL_ROOT_PASSWORD=123456 \
  mysql:8.0

此时 MySQL 数据默认存储在容器内部。

如果你执行:

docker rm -f mysql-demo

容器被删除后,里面的数据库数据也可能一起消失。

正确做法:使用数据卷

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

这里的:

-v mysql-data:/var/lib/mysql

表示把 MySQL 的数据目录挂载到 Docker 数据卷 mysql-data

即使容器删除,数据卷仍然存在。下次重新创建容器时,继续挂载这个数据卷即可恢复数据。

查看数据卷:

docker volume ls

删除数据卷:

docker volume rm mysql-data

避坑建议:凡是数据库、中间件、上传文件、日志文件,都要提前规划数据持久化。


坑 2:不知道端口映射,服务启动了却访问不了

很多新手启动 Nginx:

docker run -d nginx

然后打开浏览器访问服务器 IP,发现访问不了。

原因是容器内部的 80 端口没有映射到宿主机。

正确做法:使用 -p 参数

docker run -d \
  --name nginx-demo \
  -p 8080:80 \
  nginx

含义是:

宿主机端口:容器端口

也就是说,访问宿主机的 8080 端口,会转发到容器的 80 端口。

浏览器访问:

http://服务器IP:8080

即可看到 Nginx 页面。

注意端口冲突

如果你看到类似错误:

Bind for 0.0.0.0:8080 failed: port is already allocated

说明宿主机的 8080 端口已经被占用。

可以换一个端口:

-p 8081:80

坑 3:盲目使用 latest 标签

很多教程里会写:

docker pull mysql

或者:

docker run nginx:latest

latest 看似代表最新版本,但它不一定适合生产环境。

问题在于:

  1. 镜像版本可能变化;
  2. 依赖行为可能变化;
  3. 重启或重新部署后可能出现不兼容;
  4. 排查问题困难。

正确做法:指定明确版本

例如:

docker run -d nginx:1.25

MySQL:

docker run -d mysql:8.0

Redis:

docker run -d redis:7.2

避坑建议:学习阶段可以用 latest,生产环境一定要固定版本。


坑 4:容器名称不固定,后续管理困难

如果你直接运行:

docker run -d nginx

Docker 会自动生成一个随机容器名,比如:

romantic_morse

刚开始可能无所谓,但容器多了之后就很难管理。

正确做法:使用 --name

docker run -d \
  --name nginx-demo \
  -p 8080:80 \
  nginx

之后你可以直接使用容器名操作:

docker stop nginx-demo
docker start nginx-demo
docker logs nginx-demo

坑 5:容器异常退出后不知道如何排查

有时执行 docker run 后,容器马上退出。新手常常不知道发生了什么。

查看容器状态

docker ps -a

如果看到状态是 Exited,说明容器已经停止。

查看日志

docker logs 容器名或容器ID

实时查看日志:

docker logs -f 容器名或容器ID

查看最后 100 行:

docker logs --tail=100 容器名或容器ID

大多数启动失败问题,都可以通过日志找到原因。


坑 6:进入容器后修改配置,却忘了容器不是虚拟机

你可以通过下面命令进入容器:

docker exec -it 容器名 bash

有些镜像没有 bash,可以用 sh:

docker exec -it 容器名 sh

但新手容易犯一个错误:
进入容器后手动安装软件、修改配置,然后以为这些修改会长期保留。

实际上,容器应当被视为“可替换”的运行实例。
如果删除容器再重新创建,手动改动通常都会丢失。

正确做法

  • 配置文件使用挂载;
  • 程序依赖写进 Dockerfile;
  • 数据使用数据卷;
  • 容器只负责运行服务,不负责长期保存手动修改。

例如挂载 Nginx 配置:

docker run -d \
  --name nginx-demo \
  -p 8080:80 \
  -v /opt/nginx/nginx.conf:/etc/nginx/nginx.conf \
  nginx

坑 7:分不清 COPY 和挂载目录

构建镜像时经常用到 Dockerfile。

示例:

FROM nginx:1.25
COPY ./html /usr/share/nginx/html

这里的 COPY 是在构建镜像时,把本地文件复制进镜像。

而运行容器时的 -v 是挂载目录:

docker run -d \
  -v /opt/html:/usr/share/nginx/html \
  nginx

二者区别:

方式 发生时间 是否改变镜像 适合场景
COPY 构建镜像时 打包应用代码
-v 挂载 运行容器时 配置、数据、开发调试

避坑建议

  • 生产部署:通常把代码打包进镜像;
  • 配置和数据:通常使用挂载;
  • 开发调试:可以挂载本地代码目录。

坑 8:不清理镜像和容器,导致磁盘爆满

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

查看 Docker 占用空间:

docker system df

清理停止的容器、无用网络、悬空镜像等:

docker system prune

如果要清理更多未使用镜像:

docker system prune -a

清理未使用数据卷:

docker volume prune

注意:清理数据卷前一定要确认没有重要数据,否则可能造成数据丢失。


坑 9:生产环境不设置重启策略

如果服务器重启,或者容器异常退出,默认情况下容器不一定会自动恢复。

正确做法:添加重启策略

docker run -d \
  --name nginx-demo \
  --restart=always \
  -p 8080:80 \
  nginx

常见策略:

参数 含义
no 默认,不自动重启
always 总是自动重启
unless-stopped 除非手动停止,否则自动重启
on-failure 失败时重启

一般生产环境常用:

--restart=unless-stopped

坑 10:不会使用 Docker Compose,命令越来越长

当你只有一个 Nginx 容器时,docker run 还可以接受。

但如果你需要同时运行:

  • 后端应用;
  • MySQL;
  • Redis;
  • Nginx;
  • 消息队列;

命令会越来越长,也难以维护。

这时应该使用 Docker Compose。

示例:docker-compose.yml

services:
  nginx:
    image: nginx:1.25
    container_name: nginx-demo
    ports:
      - "8080:80"
    restart: unless-stopped

启动:

docker compose up -d

停止:

docker compose down

查看日志:

docker compose logs -f

Docker Compose 的优势是:
把容器配置写进文件,方便保存、复制、部署和版本管理。


六、一个完整的 MySQL 示例

下面是一个比较规范的 MySQL 启动示例:

docker run -d \
  --name mysql8 \
  --restart=unless-stopped \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=your_password \
  -e TZ=Asia/Shanghai \
  -v mysql8-data:/var/lib/mysql \
  mysql:8.0

说明:

参数 作用
--name mysql8 指定容器名称
--restart=unless-stopped 自动重启
-p 3306:3306 映射端口
-e MYSQL_ROOT_PASSWORD 设置 root 密码
-e TZ=Asia/Shanghai 设置时区
-v mysql8-data:/var/lib/mysql 持久化数据
mysql:8.0 使用指定版本镜像

查看运行状态:

docker ps

查看日志:

docker logs -f mysql8

进入容器:

docker exec -it mysql8 bash

七、一个完整的 Redis 示例

docker run -d \
  --name redis7 \
  --restart=unless-stopped \
  -p 6379:6379 \
  -v redis7-data:/data \
  redis:7.2 \
  redis-server --appendonly yes

这里的:

redis-server --appendonly yes

表示开启 AOF 持久化,避免 Redis 数据在重启后丢失。


八、Dockerfile 入门示例

假设你有一个简单的 Node.js 项目,可以写一个 Dockerfile:

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

解释一下:

指令 作用
FROM 指定基础镜像
WORKDIR 设置工作目录
COPY 复制文件到镜像
RUN 构建时执行命令
EXPOSE 声明容器端口
CMD 容器启动时执行命令

构建镜像:

docker build -t my-node-app:1.0 .

运行容器:

docker run -d \
  --name my-node-app \
  -p 3000:3000 \
  my-node-app:1.0

九、Docker 使用安全建议

Docker 很方便,但不能忽视安全问题。

1. 不要随便运行陌生镜像

镜像中可能包含恶意脚本、后门程序或挖矿程序。优先选择官方镜像或可信来源镜像。

2. 不要把敏感信息写死在镜像里

例如不要在 Dockerfile 中写:

ENV PASSWORD=123456

生产环境应使用环境变量、配置中心、密钥管理工具等方式管理敏感信息。

3. 避免容器使用特权模式

不要轻易使用:

--privileged

它会让容器拥有过高权限,增加安全风险。

4. 不要直接暴露数据库端口到公网

比如 MySQL 的 3306、Redis 的 6379,不建议直接暴露到公网。

如果必须访问,应配置防火墙、安全组、强密码和访问白名单。


十、新手推荐学习路线

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

  1. 理解镜像、容器、仓库、数据卷;
  2. 掌握 docker rundocker psdocker stopdocker logs
  3. 学会端口映射和目录挂载;
  4. 学会运行 Nginx、MySQL、Redis;
  5. 学会编写简单 Dockerfile;
  6. 学会 Docker Compose;
  7. 学会查看日志、清理资源、备份数据;
  8. 再进一步学习网络、镜像优化和生产部署。

不要一开始就急着研究 Kubernetes。
Docker 基础打牢之后,再学习容器编排会轻松很多。


十一、常用命令速查表

操作 命令
查看 Docker 版本 docker version
查看 Docker 信息 docker info
拉取镜像 docker pull 镜像名
查看镜像 docker images
启动容器 docker run
查看运行中容器 docker ps
查看所有容器 docker ps -a
停止容器 docker stop 容器名
启动已停止容器 docker start 容器名
删除容器 docker rm 容器名
删除镜像 docker rmi 镜像名
查看日志 docker logs 容器名
进入容器 docker exec -it 容器名 bash
查看数据卷 docker volume ls
查看空间占用 docker system df
清理无用资源 docker system prune

十二、总结

Docker 的核心价值是让应用和环境一起交付,提升部署一致性和效率。对于零基础学习者来说,刚开始不需要追求复杂架构,只要先掌握几个关键点:

  • 镜像是模板,容器是运行实例;
  • 容器删除后,内部数据可能丢失;
  • 数据库等服务必须使用数据卷;
  • 访问容器服务需要端口映射;
  • 生产环境不要盲目使用 latest
  • 容器异常时先看 docker logs
  • 多容器项目建议使用 Docker Compose;
  • 定期清理无用资源,避免磁盘爆满。

只要理解这些基本原则,Docker 就不再神秘。它不是只能由运维工程师使用的复杂工具,而是每个开发者都应该掌握的基础能力。

真正的 Docker 学习,不是背命令,而是理解容器的运行方式。掌握了镜像、容器、端口、挂载、日志和 Compose,你就已经能够完成大多数日常开发和部署任务。

目录结构
全文