Docker超详细使用指南
一:Docker到底是什么?
很多新手一上来就背命令,结果越学越懵——其实先理解Docker的核心概念,再学命令会事半功倍。
简单来说,Docker是一个开源的容器化平台,它能将应用程序及其依赖项打包成一个独立的“容器”,这个容器可以在任何支持Docker的环境中运行,无需担心环境差异、依赖缺失等问题。
举个通俗的例子:你开发的SpringBoot项目,在自己的电脑上能正常运行,但部署到服务器上就报错,大概率是服务器的JDK版本、依赖包和本地不一致。而Docker就像一个“集装箱”,把你的项目、JDK、依赖包全部打包进去,不管放到哪台电脑(只要装了Docker),都能原样运行。
Docker核心概念
- 镜像(Image):可以理解为“容器的模板”,是一个只读的文件,包含了运行应用所需的所有环境、代码、依赖。比如:JDK镜像、MySQL镜像、Nginx镜像,我们可以基于镜像创建容器。
- 容器(Container):镜像的“运行实例”,是一个可读写的隔离环境,应用程序在容器中运行。一个镜像可以创建多个容器(比如用MySQL镜像创建10个MySQL容器,各自独立运行)。
- 仓库(Repository):存放镜像的“仓库”,类似GitHub存放代码,Docker官方仓库(Docker Hub)有大量现成的镜像,我们可以直接下载使用,也可以上传自己的镜像。
关系:从仓库拉取镜像 → 用镜像创建容器 → 容器中运行应用
Linux系统安装(CentOS 7/8,最常用)
Linux安装Docker最简洁,直接执行以下命令(全程复制粘贴即可):
# 1. 卸载旧版本(如果有) sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 2. 安装必要的依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 3. 设置Docker仓库(阿里云仓库,速度更快) sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 4. 安装Docker CE(社区版,免费) sudo yum install docker-ce docker-ce-cli containerd.io # 5. 启动Docker服务 sudo systemctl start docker # 6. 设置Docker开机自启(可选,推荐) sudo systemctl enable docker # 7. 验证安装 docker --version docker run hello-world # 运行hello-world镜像,测试是否正常docker常见命令:
官方文档:docker | Docker Docs
命令 | 说明 | 文档地址 |
|---|---|---|
docker pull | 拉取镜像 | |
docker push | 推送镜像到DockerRegistry | |
docker images | 查看本地镜像 | |
docker rmi | 删除本地镜像 | |
docker run | 创建并运行容器(不能重复创建) | |
docker stop | 停止指定容器 | |
docker start | 启动指定容器 | |
docker restart | 重新启动容器 | |
docker rm | 删除指定容器 | |
docker ps | 查看容器 | |
docker logs | 查看容器运行日志 | |
docker exec | 进入容器 | |
docker save | 保存镜像到本地压缩文件 | |
docker load | 加载本地压缩文件到镜像 | |
docker inspect | 查看容器详细信息 |
重点参数说明(docker run 常用):
-d:后台运行容器(守护进程模式),不会占用终端;
-p:端口映射,格式“主机端口:容器端口”,比如3306:3306,外部可以通过主机3306端口访问容器的3306端口;
--name:给容器起一个别名,方便操作;
-e:设置环境变量,比如MySQL的root密码、编码等。
用一张图表示各个命令关系:

数据卷挂载
先想一个问题:容器是“临时的”,如果容器被删除,容器内部的数据(比如MySQL的数据、项目日志)会跟着丢失,这在生产环境中是致命的!
而数据卷(Volume)就是解决这个问题的核心——它是Docker中用于持久化数据的机制,将容器内部的目录和主机的目录绑定,容器中的数据会同步到主机,即使容器删除,主机上的数据也不会丢失。
数据卷核心概念
- 数据卷:Docker管理的主机目录(默认在 /var/lib/docker/volumes/ 下),独立于容器生命周期,容器删除后数据卷依然存在。
- 绑定挂载:将主机任意目录直接挂载到容器,灵活度高,适合开发环境。
- 核心价值:数据持久化、容器间数据共享、主机与容器数据同步。
- 最常用的两种挂载方式,直接复制命令即可使用:
# 方式1:使用数据卷(推荐,Docker自动管理目录) # 1. 创建数据卷(可选,docker run时会自动创建) docker volume create mysql-data # 2. 启动容器,挂载数据卷(将mysql-data数据卷挂载到容器的/var/lib/mysql目录) docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -v mysql-data:/var/lib/mysql mysql:8.0 # 方式2:绑定挂载(主机目录挂载,适合开发调试) # 启动容器,将主机的/root/mysql-data目录挂载到容器的/var/lib/mysql docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -v /root/mysql-data:/var/lib/mysql mysql:8.0关键参数说明:
-v 挂载格式 → 数据卷名:容器内目录 或 主机目录:容器内目录;
MySQL的数据默认存储在 /var/lib/mysql 目录,挂载这个目录即可实现数据持久化。

数据卷常用命令
docker volume create 数据卷名 # 创建数据卷 docker volume ls # 查看所有数据卷 docker volume inspect 数据卷名 # 查看数据卷详情(比如挂载路径) docker volume rm 数据卷名 # 删除数据卷(需先删除引用该数据卷的容器) docker volume prune # 清理未使用的数据卷Docker网络(容器间通信)
实际项目中,很少是单个容器运行,比如SpringBoot项目需要连接MySQL、Redis容器,这就需要解决容器间通信的问题——Docker自带网络机制,无需额外配置,就能实现容器间的互联互通。
Docker默认网络类型(3种)
- bridge(桥接网络,默认):所有容器默认加入这个网络,容器间可以通过容器名或IP通信,是最常用的网络类型。
- host(主机网络):容器直接使用主机的网络,容器端口和主机端口直接映射,无需-p参数,但安全性较低。
- none(无网络):容器没有网络,无法和外部通信,仅用于特殊场景。
实战:容器间通信(SpringBoot连接MySQL)
最推荐的方式:创建自定义桥接网络,让相关容器加入同一个网络,实现通信(比默认bridge网络更稳定,支持容器名访问)。
# 1. 创建自定义桥接网络(比如叫my-network) docker network create my-network # 2. 启动MySQL容器,加入自定义网络 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -v mysql-data:/var/lib/mysql --network my-network mysql:8.0 # 3. 启动SpringBoot容器,加入同一个网络 docker run -d --name springboot-demo -p 8080:8080 --network my-network springboot-demo:1.0核心优势:
此时SpringBoot项目连接MySQL的地址,可以直接写mysql:3306(容器名:端口),无需写主机IP,Docker会自动解析容器名对应的IP,非常灵活。
网络常用命令
docker network create 网络名 # 创建自定义网络 docker network ls # 查看所有网络 docker network inspect 网络名 # 查看网络详情(包含加入的容器) docker network connect 网络名 容器名 # 将容器加入指定网络 docker network disconnect 网络名 容器名 # 将容器退出指定网络 docker network rm 网络名 # 删除网络(需先移除所有容器)自定义镜像(Java项目打包实操,新手必看)
前面我们部署项目、运行服务,用的都是Docker Hub上别人已经准备好的镜像(比如MySQL、openjdk),但实际开发中,我们自己写的Java项目(比如SpringBoot),如何打包成一个可直接运行的Docker镜像,实现“一次打包,到处部署”呢?
这就是我们接下来要重点讲的——自定义镜像。其实自定义镜像的核心很简单:编写一个Dockerfile脚本,告诉Docker“需要哪些环境、要复制哪些项目文件、如何启动项目”,然后通过命令构建出镜像即可。下面我们就以Java项目(SpringBoot)为例,一步步教大家完成自定义镜像的打包,全程实操,跟着做就能成功!
自定义镜像核心前提
在打包镜像前,我们需要做好3个准备工作,缺一不可:
- 准备可运行的Java项目:确保你的SpringBoot项目能正常运行,并且已经打包成jar包(打包命令:mvn clean package,jar包默认在项目的target目录下)。
- 安装好Docker环境:不管是本地电脑还是服务器,确保Docker已经安装并启动(前面第二章已经讲过全平台安装方法)。
- 创建Dockerfile文件:在jar包所在的目录(建议新建一个专门的文件夹,比如docker-demo,将jar包复制进去),创建一个无后缀的Dockerfile文件(注意文件名必须是Dockerfile,首字母大写,不能改)。
编写Dockerfile
Dockerfile是自定义镜像的“灵魂”,每一行命令都有特定作用,下面我们先写一个基础版的Dockerfile
# 1. 指定基础镜像(必须有,Java项目需要JDK环境) # 这里用openjdk:8-jdk-alpine,轻量级镜像,体积小,适合生产环境 FROM openjdk:8-jdk-alpine # 2. 作者信息(可选,用于标注镜像作者,方便团队协作) MAINTAINER ZEEKLOG博主-XX # 3. 创建容器内的目录,用于存放jar包(避免文件混乱) WORKDIR /app # 4. 将本地的jar包复制到容器的/app目录下 # 格式:COPY 本地jar包路径 容器内目标路径 # 注意:本地jar包路径是相对于Dockerfile所在目录的 COPY demo-0.0.1-SNAPSHOT.jar /app/demo.jar # 5. 暴露项目运行的端口(SpringBoot项目的端口,比如8080) # 只是声明端口,不会自动映射,启动容器时需要用-p参数映射 EXPOSE 8080 # 6. 启动命令(核心,告诉Docker容器启动后如何运行Java项目) ENTRYPOINT ["java", "-jar", "/app/demo.jar"]- FROM:指定基础镜像,Java项目必须依赖JDK,我们选轻量级的alpine版本,避免镜像体积过大;
- WORKDIR:创建工作目录,后续的复制、启动命令都在这个目录下执行,避免权限问题和文件混乱;
- COPY:将本地的jar包复制到容器内部,相当于把我们的项目“放进”容器里;
- EXPOSE:声明容器要使用的端口,方便后续端口映射,不是必须的,但建议加上,增强可读性;
- ENTRYPOINT:容器启动后执行的命令,这里就是运行Java jar包的命令,固定格式。
构建自定义镜像(执行命令,一键打包)
Dockerfile编写完成后,就可以执行命令构建镜像了,步骤非常简单:
- 打开终端/CMD,进入Dockerfile和jar包所在的目录(比如docker-demo);
- 执行构建命令(注意末尾有一个“.”,表示“当前目录”,Docker会在当前目录找Dockerfile):
# 格式:docker build -t 镜像名:版本号 . # 示例:docker build -t my-springboot:1.0 . docker build -t my-springboot:1.0 .3. 等待构建完成,构建成功后,执行 docker images 命令,就能看到我们自己构建的镜像(my-springboot:1.0)。
实战:项目部署前后端
部署后端:
后端部署就和上面自定义镜像相同,核心步骤就三点:
1:打包好我们的java应用
2:编写Dockerfile文件(AI辅助)。
3构建Docker镜像,部署Docker容器,运行测试。
部署前端
1在宿主机上准备好html静态资源文件和conf配置文件
2通过-v指令挂载数据卷
-v /usr/local/tlias-web/html:/usr/share/nginx/html
-v /usr/local/tlias-web/conf/nginx.conf:/etc/nginx/nginx.conf
宿主机路径随意,容器中的路径固定
3部署nginx容器:如:
docker run -d \ --name nginx-tlias \ -v /usr/local/tlias-web/html:/usr/share/nginx/html \ -v /usr/local/tlias-web/conf/nginx.conf:/etc/nginx/nginx.conf \ --network itheima \ -p 80:80 \ nginx:1.20.2DockerCompose
大家可以看到,我们部署一个简单的java项目,其中包含3个容器:
- MySQL
- Nginx
- Java项目
而稍微复杂的项目,其中还会有各种各样的其它中间件,需要部署的东西远不止3个。如果还像之前那样手动的逐一部署,就太麻烦了。DockerCompose核心作用是:用一个YAML配置文件(docker-compose.yml),定义所有容器的配置(镜像、端口、网络、数据卷等),然后用一条命令,一键启动/停止/重启所有容器,彻底解决多容器部署繁琐的问题,是企业开发中部署复杂项目的必备工具。
而Docker Compose就可以帮助我们实现多个相互关联的Docker容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。
docker-compose.yml文件的基本语法可以参考官方文档:Legacy versions | Docker Docs
举例来说,用docker run部署MySQL的命令如下:
docker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123 \ -v ./mysql/data:/var/lib/mysql \ -v ./mysql/conf:/etc/mysql/conf.d \ -v ./mysql/init:/docker-entrypoint-initdb.d \ --network hmall mysql如果用docker-compose.yml文件来定义,就是这样
version: "3.8" services: mysql: image: mysql container_name: mysql ports: - "3306:3306" environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123 volumes: - "./mysql/conf:/etc/mysql/conf.d" - "./mysql/data:/var/lib/mysql" networks: - new networks: new: name: hmall对比如下:

下面我们以“SpringBoot项目+MySQL数据库”为例,一步步教大家使用Docker Compose
前置准备
- 准备好SpringBoot项目的自定义镜像(前面章节已教打包,比如my-springboot:1.0);
- 创建一个专门的部署文件夹(比如docker-compose-demo),用于存放配置文件;
- 在该文件夹下,创建一个docker-compose.yml文件(文件名固定,小写,不能改)——这是Docker Compose的核心配置文件。
6.3.2 编写docker-compose.yml配置文件(核心)
配置文件采用YAML格式,语法严格(缩进用2个空格,不能用Tab,否则会报错),下面是完整的配置文件,每一行都有详细注释,直接复制使用,只需修改镜像名、密码等关键信息即可。
# 版本号(固定写法,根据Docker Compose版本选择,v2版本用"2"或"3") version: "3" # 定义所有容器(services下的每一个key都是一个容器名) services: # 1. MySQL容器 mysql: # 使用的镜像(Docker Hub上的官方镜像) image: mysql:8.0 # 容器名(自定义,方便管理) container_name: mysql-container # 环境变量(设置MySQL root密码、编码等) environment: - MYSQL_ROOT_PASSWORD=123456 # root密码(建议修改为复杂密码) - MYSQL_DATABASE=demo_db # 自动创建的数据库名(SpringBoot项目需要的数据库) - MYSQL_CHARSET=utf8mb4 # 数据库编码(避免中文乱码) - MYSQL_COLLATION=utf8mb4_unicode_ci # 数据卷挂载(实现数据持久化,避免容器删除后数据丢失) volumes: - mysql-data:/var/lib/mysql # 数据卷名:容器内数据目录(MySQL默认数据存储目录) # 网络配置(加入自定义网络,实现和SpringBoot容器通信) networks: - my-network # 启动策略(设置容器自启,避免重启Docker后容器失效) restart: always # 可选:限制容器资源(避免占用过多服务器资源) deploy: resources: limits: cpus: '0.5' # 限制CPU使用不超过0.5核 memory: 512M # 限制内存使用不超过512M # 2. SpringBoot容器 springboot-app: # 使用我们自己打包的SpringBoot镜像(前面章节构建的my-springboot:1.0) image: my-springboot:1.0 # 容器名(自定义) container_name: springboot-container # 端口映射(主机8080端口映射到容器8080端口,外部可通过主机IP:8080访问项目) ports: - "8080:8080" # 环境变量(配置项目运行环境,核心是数据库连接地址) environment: - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/demo_db?useSSL=false&serverTimezone=Asia/Shanghai - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=123456 - SPRING_PROFILES_ACTIVE=prod # 指定生产环境配置(根据自己项目调整) # 依赖关系(关键:让SpringBoot容器在MySQL容器启动后再启动,避免连接失败) depends_on: - mysql # 网络配置(和MySQL加入同一个网络,实现容器间通信) networks: - my-network # 启动策略(随Docker自启) restart: always # 可选:限制容器资源 deploy: resources: limits: cpus: '0.5' memory: 512M # 定义数据卷(和上面volumes中引用的mysql-data对应,实现数据持久化) volumes: mysql-data: # 数据卷名,和前面MySQL容器挂载的名称一致,Docker会自动创建和管理 # 定义自定义网络(和上面services中引用的my-network对应,实现容器间通信) networks: my-network: # 自定义网络名,Docker会自动创建,无需手动执行docker network create命令关键注意点:
1. YAML语法严格,缩进必须用2个空格,不能用Tab,否则执行命令会报错;
2. 环境变量中,数据库连接地址写mysql:3306(MySQL容器名:端口),Docker会自动解析容器名对应的IP;
3. depends_on仅保证启动顺序,不保证MySQL完全启动完成,如果SpringBoot启动过快导致连接失败,可添加启动延迟
执行Docker Compose命令(一键部署)
配置文件编写完成后,进入docker-compose.yml所在的目录(比如docker-compose-demo),执行以下命令,即可一键启动所有容器,全程无需手动操作。
# 1. 启动所有容器(后台运行,推荐) # -d:后台运行,不会占用终端;--build:启动前重新构建镜像(可选,适合镜像有更新时) docker compose up -d # 2. 查看容器运行状态(查看所有容器是否正常启动) docker compose ps # 3. 查看容器运行日志(可指定容器名,查看单个容器日志) # 查看SpringBoot容器日志(实时刷新) docker compose logs -f springboot-app # 查看MySQL容器日志 docker compose logs -f mysql # 4. 停止所有容器(不删除容器和数据) docker compose stop # 5. 启动已停止的容器 docker compose start # 6. 重启所有容器 docker compose restart # 7. 停止并删除所有容器、网络、数据卷(谨慎使用,会删除容器和临时数据,数据卷数据不会丢失) docker compose down # 8. 停止并删除所有容器、网络、数据卷(包括数据卷,彻底清理,谨慎使用) docker compose down -v
常见问题解决
问题3:容器启动成功,但外部无法访问SpringBoot项目 解决方法:检查端口映射是否正确(ports配置是否为“8080:8080”),同时检查服务器防火墙是否开放8080端口(Linux系统可执行sudo firewall-cmd --add-port=8080/tcp --permanent开放端口)问题2:执行docker compose命令报错“yaml: line x: did not find expected key” 解决方法:检查docker-compose.yml文件的缩进,确保所有缩进都是2个空格,没有使用Tab,且语法格式正确(比如冒号后面有空格)。
问题1:SpringBoot容器启动失败,提示“无法连接MySQL” 解决方法:添加启动延迟,让SpringBoot等待MySQL启动完成。在springboot-app服务下添加以下配置: command: sh -c "sleep 30 && java -jar /app/demo.jar" 原理:让SpringBoot容器启动后,先睡眠30秒,再启动项目,确保MySQL已完成初始化。docker常见问题:
坑1:Docker启动失败,报错“Cannot connect to the Docker daemon”
原因:Docker服务未启动,或权限不足。
解决方案:Linux系统执行sudo systemctl start docker 启动服务;
坑2:拉取镜像速度极慢,甚至超时
原因:默认使用Docker官方仓库(国外服务器),网络延迟高。
解决方案:配置国内镜像源(阿里云、网易云等),以Linux为例:
# 1. 创建Docker配置目录 sudo mkdir -p /etc/docker # 2. 编写配置文件,添加阿里云镜像源 sudo tee /etc/docker/daemon.json <<'EOF' { "registry-mirrors": ["https://docker.mirrors.aliyun.com"] } EOF # 3. 重启Docker服务 sudo systemctl daemon-reload sudo systemctl restart docker坑3:删除镜像时,报错“image is being used by stopped container”
原因:该镜像被已停止的容器引用,无法直接删除。
解决方案:先删除引用该镜像的容器(docker rm 容器ID),再删除镜像。
坑4:容器间无法通信,提示“连接超时”
原因:容器未加入同一个网络,或端口未开放。
解决方案:将所有需要通信的容器加入同一个自定义网络,确保容器内服务端口正常启动。
坑5:自定义镜像体积过大,拉取/构建速度慢
原因:未使用轻量级基础镜像,或未清理无用文件。
解决方案:使用alpine基础镜像,合并RUN命令,清理临时文件,添加.dockerignore文件。