Docker 容器化技术:从入门到微服务实战
前言:为什么学 Docker?
在微服务时代,软件不仅仅是代码,还包含运行环境(OS、JDK、Libs、配置)。Docker 将这一切打包成镜像,实现了“一次构建,到处运行”,彻底解决了 “在我的机器上能跑,演示时就崩了” 的环境一致性问题。
Docker镜像交流社区:Docker Hub Container Image Library | App Containerization
第一部分:核心概念 (入门必看)
初学者必须区分 Docker 的三个基本概念,可以类比为“软件安装”的过程:
| 概念 | 类比 | 详细说明 |
|---|---|---|
| 镜像 (Image) | 安装包 | 一个只读的文件包。包含了应用程序代码、运行库、依赖环境和配置文件。镜像是一层层文件叠加而成的(分层存储)。 |
| 容器 (Container) | 运行中的软件 | 镜像运行时的实例。它是隔离的、可写的。你可以从一个镜像启动 N 个不同的容器。 |
| 仓库 (Repository) | 应用商店 | 集中存放镜像的地方。最常用的是官方的 DockerHub。 |
第二部分:环境配置 (关键步骤:镜像加速)
由于网络原因,在国内直接从 DockerHub 拉取镜像速度非常慢或容易超时。在开始学习命令前,必须配置镜像加速器。
目前国内镜像有些问题,可以自行去网上搜索可用的镜像
1. 获取加速地址
推荐使用阿里云(稳定免费)或其他国内源:
- 阿里云(https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors): 登录控制台 -> 容器镜像服务 -> 镜像工具 -> 镜像加速器 -> 复制 `https://xxxx.mirror.aliyuncs.com
2. 配置步骤 (Linux/CentOS)
直接在终端执行以下命令(注意将 URL 替换为你实际的加速地址):
# 1. 创建配置目录
sudo mkdir -p /etc/docker
# 2. 写入配置文件 daemon.json
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://你的专属ID.mirror.aliyuncs.com"
]
}
EOF
# 3. 重新加载配置并重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
3. 验证配置
执行 docker info,在输出末尾找到 Registry Mirrors,如果显示了你配置的地址,即表示成功。
第三部分:Docker 常用命令体系
1. 镜像管理命令
docker pull <镜像名>:<标签>:拉取镜像(不写标签默认latest)。- 例:
docker pull nginx:1.21
- 例:
docker images:查看本地已下载的镜像。docker rmi <镜像名/ID>:删除本地镜像。docker save/load:将镜像导出为压缩包/从压缩包导入(用于无网环境迁移)。
2. 容器操作命令 (核心)
容器的生命周期:创建 -> 运行 -> 暂停/停止 -> 删除。
docker run:创建并运行容器(参数最复杂,见下文详解)。docker ps:查看运行中的容器。docker ps -a:查看所有容器(包括已停止的)。
docker stop <容器名>:停止容器。docker start <容器名>:启动已停止的容器。docker restart <容器名>:重启容器。docker rm <容器名>:删除容器(注意:运行中的容器无法直接删除,需加-f强制删除)。docker logs -f <容器名>:持续查看容器运行日志(排错神器)。docker exec -it <容器名> bash:进入容器内部执行命令。- 例:进入 MySQL 容器修改配置
3. 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 \
mysql:8.0
-d(Detached): 后台运行,不阻塞当前终端窗口。--name: 给容器起个容易记住的名字(否则 Docker 会随机生成名字)。-p 宿主机端口:容器端口(Port): 端口映射。- 原理:外部请求 -> 宿主机 3306 -> 转发给容器 3306。
- 注意:容器端口通常由应用决定(如 MySQL 固定 3306),宿主机端口可随意指定(只要不冲突)。
-e KEY=VALUE(Environment): 设置环境变量。- 用途:覆盖容器内的默认配置(如密码、时区)。具体变量名需查阅 DockerHub 镜像说明。
-v 宿主机路径:容器路径(Volume): 挂载数据卷(见第四部分)。
第四部分:数据持久化 (进阶)
容器有一个特性:用完即焚。容器删除后,其内部产生的所有文件都会消失。为了保留数据(如数据库数据、日志、配置文件),必须使用数据卷。
1. 数据卷 (Volume) - Docker 托管
Docker 在宿主机文件系统中管理的一块特定区域(通常在 /var/lib/docker/volumes/)。
- 特点:路径较深,不方便直接修改,适合存储“不常人为修改”的数据(如 MySQL 的 data 目录)。
- 命令:
docker volume create <卷名>docker volume inspect <卷名>(查看具体存储位置)
- 挂载方式:
-v html:/usr/share/nginx/html(将名为html的卷挂载到容器)
2. 目录挂载 (Bind Mount) - 自定义路径
直接将宿主机的指定目录/文件挂载到容器内。
- 特点:路径直观,方便修改,适合配置文件或代码。
- 挂载方式:
-v ./mysql/conf:/etc/mysql/conf.d(宿主机当前目录挂载)
最佳实践:
- 数据库数据:使用 Docker 托管的数据卷或指定目录均可。
- 配置文件 (conf):强烈建议使用目录挂载,方便在宿主机直接编辑。
- 前端静态资源 (html):使用目录挂载,方便随时更新页面。
第五部分:自定义镜像 (Dockerfile)
当我们开发了自己的 Java/Web 应用,如何将其打包成镜像?这就需要 Dockerfile。
官方文档:https://docs.docker.com/engine/reference/builder/
1. 镜像的分层原理 (Layer)
镜像不是一个大文件,而是由很多层堆叠起来的。
- Base Image: 基础操作系统层(如 Ubuntu, Alpine)。
- Add-on Layers: 每安装一个软件、拷贝一个文件、执行一条命令,就增加一层。
- 优势:如果多个镜像共用同一个 Base Image,本地只需存储一份基础层,节省空间。
2. Dockerfile 核心指令
Dockerfile 是一个文本文件,包含构建镜像的指令。
| 指令 | 作用 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM openjdk:11.0-jre-buster |
| ENV | 设置环境变量 | ENV TZ=Asia/Shanghai |
| COPY | 拷贝宿主机文件到容器 | COPY ./hm-service.jar /app.jar |
| RUN | 构建时执行的 Shell 命令 | RUN apt-get update && apt-get install -y vim |
| EXPOSE | 声明容器监听端口 | EXPOSE 8080 (仅作为文档说明) |
| ENTRYPOINT | 容器启动时执行的命令 | ENTRYPOINT ["java", "-jar", "/app.jar"] |
3. 实战:打包 Java 项目
-
将打包好的
hm-service.jar和Dockerfile放在同一目录。 -
编写 Dockerfile:
FROM openjdk:11.0-jre-buster ENV TZ=Asia/Shanghai COPY hm-service.jar /app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] -
构建镜像:
# 注意最后有个点,代表当前目录 docker build -t hmall:1.0 .
第六部分:Docker 网络 (互联互通)
1. 默认桥接网络的问题
默认情况下,容器重启后 IP 地址可能会变化。如果我们在代码中写死 IP(如 JDBC URL 连接数据库),容器重启后服务就会断连。
2. 自定义网络 (User-Defined Bridge)
Docker 允许创建自定义网络,加入同一网络的容器,可以通过“容器名”互相访问(Docker 内置了 DNS 解析)。
-
创建网络:
docker network create hmall-net -
容器加入网络:
- 启动 MySQL:
docker run ... --network hmall-net --name mysql ... - 启动 Java App:
docker run ... --network hmall-net ...
- 启动 MySQL:
-
效果:
在 Java 项目的配置文件中,数据库地址不再写 IP,而是直接写容器名:jdbc:mysql://mysql:3306/hmall
第七部分:Docker Compose (微服务编排)
1. 痛点
部署一个完整的微服务系统(MySQL + Nginx + 5个 Java 服务),需要执行 7 次 docker run,且要手动管理启动顺序(先 DB 后 App),维护极难。
2. 解决方案
Docker Compose 是一个编排工具,通过一个 docker-compose.yml 文件定义一组相关联的容器。
官方文档:Docker Compose | Docker 文档 — Docker Compose | Docker Docs
3. docker-compose.yml 模板详解
version: "3.8"
services:
# --- MySQL 服务 ---
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/data:/var/lib/mysql"
networks:
- hm-net
# --- Java 后端服务 ---
hmall:
build: . # 自动寻找当前目录的 Dockerfile 构建镜像
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on: # 依赖配置:确保 mysql 先启动
- mysql
# --- Nginx 前端服务 ---
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080" # 宿主机 18080 映射到容器
volumes:
- "./nginx/html:/usr/share/nginx/html"
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
networks:
- hm-net
depends_on:
- hmall
# --- 网络声明 ---
networks:
hm-net:
name: hmall-net
4. 常用 Compose 命令
- 一键启动:
docker compose up -d(构建镜像、创建网络、按顺序启动容器) - 一键停止:
docker compose down(停止容器、删除容器、删除网络) - 查看日志:
docker compose logs -f(聚合所有服务的日志) - 查看状态:
docker compose ps
小结
- 环境: 第一步务必配置镜像加速,否则下载极其缓慢。
- 基础:熟练掌握
docker run的-p(端口),-v(挂载),-e(环境),-d(后台) 参数。 - 进阶:理解 镜像分层 概念,会写 Dockerfile 打包自己的应用。
- 实战:放弃 Shell 脚本,使用 Docker Compose 编排复杂的微服务环境。
- 网络:利用 自定义网络 实现容器间通过名字互访,解耦 IP 依赖。
更多推荐
所有评论(0)