欢迎光临
我们一直在努力

Docker - 环境搭建全攻略,Windows_macOS_Linux通用

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Docker这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • Docker – 环境搭建全攻略,Windows/macOS/Linux通用 🐳
    • 一、为什么是 Docker?而不是虚拟机或手动部署?🤔
    • 二、系统准备:三平台统一检查清单 ✅
      • 🔍 1. 检查硬件与系统要求
      • 🔍 2. 验证基础工具链
    • 三、Docker 引擎安装:三平台标准化流程 🛠️
      • ▶️ Windows:WSL2 + Docker Desktop(推荐)
      • ▶️ macOS:Apple Silicon / Intel 一体安装
      • ▶️ Linux:一键脚本(Ubuntu/Debian/CentOS/RHEL 通用)
    • 四、Docker 核心概念速成:镜像、容器、卷、网络 🧩
      • 🖼️ 1. 镜像(Image)—— 只读模板,应用的“快照”
      • ▶️ 容器(Container)—— 镜像的运行实例,进程沙盒
      • 📦 2. 卷(Volume)—— 持久化数据的“U 盘”
      • 🌐 3. 自定义网络(Custom Network)—— 容器间安全通信的“局域网”
    • 五、Java 应用实战:从 Spring Boot 到生产就绪容器 🚀
      • 🌱 1. 创建最小可行 Java 应用(无 Maven Wrapper 依赖)
        • ✅ `pom.xml`(精简版,仅核心依赖)
        • ✅ `DemoApplication.java`
        • ✅ `HelloController.java`
        • ✅ `application.properties`
      • 🐳 2. 编写生产级 `Dockerfile`(多阶段构建)
      • 🧪 3. 构建并运行单容器
      • 🌐 4. 多容器编排:Spring Boot + PostgreSQL(`docker-compose.yml`)
        • 启动整套环境:
    • 六、可视化架构图:用 Mermaid 描述你的应用拓扑 📊
    • 七、进阶:生产就绪必备技能 🔐
      • 🔐 1. 安全加固:非 root 运行 + 最小权限
      • 📈 2. 监控与指标:集成 Prometheus + Grafana(轻量方案)
      • 📦 3. 日志集中管理:ELK 精简版(Elasticsearch + Logstash + Kibana)
    • 八、常见故障排查手册 🛠️
    • 九、持续集成与交付(CI/CD)初探 🔄
    • 十、结语:拥抱容器化,就是拥抱确定性 🌈

Docker – 环境搭建全攻略,Windows/macOS/Linux通用 🐳

“一次构建,处处运行” —— 这不是一句空洞的口号,而是 Docker 用容器化技术真正兑现的承诺 ✅ 无论你是刚接触 DevOps 的 Java 初学者,还是正在为微服务部署焦头烂额的后端工程师,亦或是需要在多台机器上复现一致开发环境的全栈开发者——本篇将为你提供一套跨平台、零歧义、开箱即用的 Docker 全流程实践指南。全程不依赖 GitHub 链接,所有命令可直接复制粘贴执行,所有示例代码真实可运行,所有图表原生渲染,所有外部资源均为稳定公开站点。


一、为什么是 Docker?而不是虚拟机或手动部署?🤔

在深入安装前,我们先建立共识:Docker 不是银弹,但它是当前云原生时代最务实的「环境一致性」解法。

对比维度传统虚拟机(VM)手动配置(apt install / brew install)Docker 容器
启动速度 秒级(需加载完整 OS 内核) 毫秒级(共享宿主机内核)✅ 毫秒级(进程级隔离)✅
资源占用 高(GB 级内存 + 数 GB 磁盘) 极低(仅二进制与配置) 中等(MB~几百 MB,按需加载)✅
环境一致性 弱(宿主机差异导致 apt 版本/依赖冲突) 极弱(“在我机器上能跑!”❌) 强(镜像哈希唯一,行为确定)✅
可复现性 依赖快照,难版本化 几乎不可复现(无声明式定义) 声明式 Dockerfile + docker-compose.yml ✅
Java 应用适配度 高(但笨重) 高(但脆弱) 极高(JVM 与 Linux 进程模型天然契合)✅

💡 关键洞察:Java 应用天生适合容器化——它不依赖特定发行版的 libc 版本(得益于 JVM 抽象层),且 Spring Boot 内嵌 Tomcat/Jetty,彻底摆脱外部 Web 容器依赖。这意味着你无需在容器里装 Apache、配 webapps 目录,一个 JAR 包 + java -jar 就是全部。


二、系统准备:三平台统一检查清单 ✅

Docker 的跨平台能力强大,但底层依赖有细微差异。以下检查项必须全部通过,否则后续步骤将出现不可预知错误。

🔍 1. 检查硬件与系统要求

平台最低要求验证命令(终端中执行)
Windows Windows 10 21H2+ 或 Windows 11,启用 WSL2 wsl -l -v → 查看 WSL2 发行版及状态 ✅
macOS macOS 12+(Monterey),Intel 或 Apple Silicon sw_vers & arch → 确认系统版本与芯片架构 ✅
Linux Linux kernel ≥ 3.10,支持 overlay2 存储驱动 uname -r & docker info | grep "Storage Driver" ✅

⚠️ 注意:Windows 用户务必使用 WSL2 后端(Docker Desktop 默认启用)。不要选择 Hyper-V(已弃用)或旧版 Docker Toolbox(无 docker buildx 支持)。

🔍 2. 验证基础工具链

所有平台均需确保以下命令存在且版本合规:

# 检查 shell 类型(推荐使用 bash/zsh)
echo $SHELL

# 检查 curl(用于下载脚本)
curl –version | head -n1

# 检查 tar(解压镜像层)
tar –version | head -n1

# 检查 unzip(部分 Java 工具链需要)
unzip -v | head -n1

✅ 正常输出应类似:

/bin/bash
curl 8.6.0 (x86_64-apple-darwin23.0) …
tar (GNU tar) 1.34
UnZip 6.00 of 20 April 2009, by Info-ZIP.

🌐 外部参考:Docker 官方系统要求文档 提供了各发行版详细兼容表,建议在安装前快速浏览确认。


三、Docker 引擎安装:三平台标准化流程 🛠️

✨ 核心原则:不使用包管理器直接安装 docker-ce(如 apt install docker-ce),而采用 Docker 官方一键脚本——它自动检测系统类型、校验签名、配置存储驱动,并规避 root 权限陷阱。

▶️ Windows:WSL2 + Docker Desktop(推荐)

  • 启用 WSL2(管理员 PowerShell):

    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    # 重启电脑
    wsl install
    wsl set-defaultversion 2

  • 下载并安装 Docker Desktop 访问 Docker Desktop for Windows → 下载 .exe → 双击安装 → 勾选 “Use the WSL 2 based engine” ✅

  • 验证安装(在 WSL2 终端或 Windows Terminal 中):

    docker –version
    docker run hello-world

    ✅ 输出含 Hello from Docker! 即成功。

  • ▶️ macOS:Apple Silicon / Intel 一体安装

  • 下载 Docker Desktop for Mac 访问 Docker Desktop for Mac → 选择 Universal App(自动适配 M1/M2/M3 与 Intel)→ 拖入 Applications → 启动。

  • 首次启动授权(系统会提示输入密码):

    • 允许辅助功能访问(用于 docker context 切换)
    • 允许全盘访问(用于挂载本地目录,如 ./src:/app/src)
  • 终端验证:

    docker info | grep "Architecture\\|Kernel"
    # 输出应含 "aarch64"(Apple Silicon)或 "x86_64"(Intel)

  • ▶️ Linux:一键脚本(Ubuntu/Debian/CentOS/RHEL 通用)

    ✅ 适用于:Ubuntu 22.04+、Debian 11+、CentOS Stream 9、RHEL 9+

    # 下载并执行官方安装脚本(自动适配发行版)
    curl -fsSL https://get.docker.com | sh

    # 添加当前用户到 docker 组(避免每次 sudo)
    sudo usermod -aG docker $USER

    # 重新加载组权限(无需登出,新终端生效)
    newgrp docker

    # 验证(新终端中执行)
    docker run –rm alpine echo "Docker is working! 🎉"

    🌐 外部参考:Docker Engine 官方安装指南 提供了各 Linux 发行版的手动安装步骤(如离线安装、代理配置),当网络受限时可作备选。


    四、Docker 核心概念速成:镜像、容器、卷、网络 🧩

    在写 Java 示例前,必须厘清四个基石概念。它们不是抽象术语,而是你每天要敲的命令对象。

    🖼️ 1. 镜像(Image)—— 只读模板,应用的“快照”

    • 由 Dockerfile 构建生成,分层存储(Layered FS),支持缓存复用
    • 示例:openjdk:17-jre-slim 是一个预装 JDK 17 的轻量镜像;eclipse-mosquitto:2 是 MQTT 服务器镜像
    • 查看本地镜像:docker images

    ▶️ 容器(Container)—— 镜像的运行实例,进程沙盒

    • 启动 = docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
    • 每个容器有独立 PID 命名空间、网络命名空间、文件系统(叠加读写层)
    • 查看运行中容器:docker ps;查看全部(含退出):docker ps -a

    📦 2. 卷(Volume)—— 持久化数据的“U 盘”

    • 解决容器删除后数据丢失问题(如 MySQL 数据库文件、Spring Boot 日志)
    • 创建:docker volume create myapp-data
    • 挂载到容器:-v myapp-data:/var/lib/mysql
    • ✅ 优势:与宿主机路径解耦,跨平台可移植(不用写 C:\\data 或 /Users/me/data)

    🌐 3. 自定义网络(Custom Network)—— 容器间安全通信的“局域网”

    • 默认 bridge 网络下容器通过 IP 通信(不稳定)
    • 自定义网络支持 DNS 自动解析:容器名即主机名!docker network create myapp-net
      docker run -d –name db –network myapp-net postgres:15
      docker run -d –name app –network myapp-net my-java-app
      # ✅ 在 app 容器中可直接 `ping db` 或 `jdbc:postgresql://db:5432/mydb`

    🧠 记忆口诀: 镜像是蓝图 📜,容器是房子 🏠,卷是家具 🪑,网络是小区 WiFi 📶


    五、Java 应用实战:从 Spring Boot 到生产就绪容器 🚀

    我们以一个真实的 Spring Boot REST API 为例,完成 本地开发 → 构建镜像 → 容器运行 → 多容器编排 → 日志与调试 全流程。

    🌱 1. 创建最小可行 Java 应用(无 Maven Wrapper 依赖)

    创建目录 my-spring-app,结构如下:

    my-spring-app/
    ├── src/
    │ └── main/
    │ ├── java/com/example/demo/
    │ │ ├── DemoApplication.java
    │ │ └── HelloController.java
    │ └── resources/application.properties
    ├── pom.xml
    └── Dockerfile

    ✅ pom.xml(精简版,仅核心依赖)

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd"
    >

    <modelVersion>4.0.0</modelVersion>
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.5</version>
    <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>

    <properties>
    <java.version>17</java.version>
    </properties>

    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>
    </project>

    ✅ DemoApplication.java

    package com.example.demo;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication
    public class DemoApplication {
    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }
    }

    ✅ HelloController.java

    package com.example.demo;

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class HelloController {

    @GetMapping("/api/hello")
    public String hello() {
    return "Hello from Dockerized Spring Boot! 🐳✨";
    }

    @GetMapping("/api/health")
    public String health() {
    return "{\\"status\\":\\"UP\\",\\"timestamp\\":\\"" + System.currentTimeMillis() + "\\"}";
    }
    }

    ✅ application.properties

    # 内置 Tomcat 监听 8080
    server.port=8080
    # Actuator 端点开放(便于健康检查)
    management.endpoints.web.exposure.include=health,info,metrics
    # 关闭 CSRF(演示用)
    spring.mvc.favicon.enabled=false

    ✅ 此应用可在本地运行:mvn spring-boot:run → 访问 http://localhost:8080/api/hello 得到响应。


    🐳 2. 编写生产级 Dockerfile(多阶段构建)

    ❗关键:绝不使用 FROM openjdk:17 直接运行 JAR(体积大、含调试工具、非 root 用户缺失)。采用多阶段构建(Multi-stage Build)实现最小化、安全化。

    # 构建阶段:使用 maven:3.9-amazoncorretto-17 构建 JAR
    FROM maven:3.9-amazoncorretto-17 AS builder
    WORKDIR /app
    COPY pom.xml .
    RUN mvn dependency:go-offline -B
    COPY src ./src
    RUN mvn clean package -DskipTests

    # 运行阶段:使用 amazoncorretto:17-jre-alpine(仅 120MB,无包管理器)
    FROM amazoncorretto:17-jre-alpine
    VOLUME ["/tmp"] # Spring Boot 默认临时目录
    ARG DEPENDENCY=/app/target/dependency
    # 复制构建好的 JAR 和依赖(优化类加载)
    COPY –from=builder /app/target/*.jar app.jar
    # 创建非 root 用户(安全最佳实践)
    RUN addgroup -g 1001 -f appgroup && adduser -S appuser -u 1001
    USER appuser
    # 暴露端口(文档化用途,不影响实际绑定)
    EXPOSE 8080
    # 启动命令(使用 java -D 参数优化)
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

    🔍 逐行解析亮点:

    • amazoncorretto:17-jre-alpine:Amazon 官方维护的 Alpine 版 Corretto JDK,比 openjdk 小 60%,且通过 FIPS 认证 ✅
    • adduser -S:创建系统用户(无家目录、无 shell),符合 CIS Docker Benchmark 安全规范 ✅
    • -Djava.security.egd=file:/dev/./urandom:加速 JVM 启动(Alpine 默认 /dev/random 阻塞)✅
    • VOLUME ["/tmp"]:显式声明卷,避免 Spring Boot 临时文件写满容器层 ✅

    🧪 3. 构建并运行单容器

    # 进入项目根目录
    cd my-spring-app

    # 构建镜像(标签为 my-spring-app:1.0)
    docker build -t my-spring-app:1.0 .

    # 运行容器(后台、端口映射、名称指定)
    docker run -d \\
    –name my-spring-container \\
    -p 8080:8080 \\
    -e SPRING_PROFILES_ACTIVE=prod \\
    my-spring-app:1.0

    # 查看日志(实时流式输出)
    docker logs -f my-spring-container

    ✅ 成功标志:日志末尾出现

    Tomcat started on port(s): 8080 (http) with context path ''
    Started DemoApplication in X.XXX seconds (process running for X.XXX)

    然后访问 http://localhost:8080/api/hello → 返回 Hello from Dockerized Spring Boot! 🐳✨

    💡 小技巧:添加 –rm 参数让容器退出后自动清理(适合调试):

    docker run –rm -p 8080:8080 my-spring-app:1.0


    🌐 4. 多容器编排:Spring Boot + PostgreSQL(docker-compose.yml)

    真实场景中,Java 应用几乎总依赖数据库。我们用 docker-compose 实现一键拉起整套环境。

    在 my-spring-app/ 目录下创建 docker-compose.yml:

    version: '3.8'

    # 定义自定义网络,所有服务加入同一网络
    networks:
    app-network:
    driver: bridge

    # 定义数据卷,持久化 PostgreSQL 数据
    volumes:
    pg-data:

    services:
    # PostgreSQL 服务
    db:
    image: postgres:15alpine
    restart: unlessstopped
    environment:
    POSTGRES_DB: demoapp
    POSTGRES_USER: appuser
    POSTGRES_PASSWORD: apppass
    volumes:
    pgdata:/var/lib/postgresql/data
    networks:
    appnetwork
    healthcheck:
    test: ["CMD-SHELL", "pg_isready -U appuser -d demoapp"]
    interval: 30s
    timeout: 10s
    retries: 5

    # Spring Boot 应用服务
    app:
    image: myspringapp:1.0
    restart: unlessstopped
    ports:
    "8080:8080"
    environment:
    SPRING_PROFILES_ACTIVE: prod
    SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/demoapp
    SPRING_DATASOURCE_USERNAME: appuser
    SPRING_DATASOURCE_PASSWORD: apppass
    # 启用 Actuator 健康检查探针
    MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: always
    depends_on:
    db:
    condition: service_healthy
    networks:
    appnetwork
    # 添加 JVM 内存限制(防 OOM)
    mem_limit: 512m

    ✅ 关键设计说明:

    • depends_on + condition: service_healthy:确保 PostgreSQL 启动并真正可连接后,再启动 Java 应用(避免 Connection refused 错误)
    • mem_limit: 512m:强制容器内存上限,防止 JVM 无节制申请内存(配合 -Xmx384m 更佳)
    • SPRING_DATASOURCE_URL 中的 db 是服务名 → 自动 DNS 解析到 PostgreSQL 容器 IP ✅
    启动整套环境:

    # 构建并启动(自动创建网络、卷)
    docker compose up -d

    # 查看服务状态
    docker compose ps

    # 查看 app 日志(等待几秒,直到显示 "Started DemoApplication")
    docker compose logs -f app

    # 停止
    docker compose down
    # (保留卷数据)停用但不清除数据:docker compose down -v

    🌐 外部参考:PostgreSQL 官方 Docker 文档 详细说明了环境变量、初始化脚本、备份策略等高级用法。


    六、可视化架构图:用 Mermaid 描述你的应用拓扑 📊

    下面是一个典型的 Spring Boot 微服务架构 Mermaid 图,它真实反映上文 docker-compose.yml 的逻辑关系,并支持在主流 Markdown 渲染器(如 VS Code 预览、Typora、Obsidian)中直接显示:

    #mermaid-svg-8gN4okKn5t65LcrY{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8gN4okKn5t65LcrY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8gN4okKn5t65LcrY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8gN4okKn5t65LcrY .error-icon{fill:#552222;}#mermaid-svg-8gN4okKn5t65LcrY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8gN4okKn5t65LcrY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8gN4okKn5t65LcrY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8gN4okKn5t65LcrY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8gN4okKn5t65LcrY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8gN4okKn5t65LcrY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8gN4okKn5t65LcrY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8gN4okKn5t65LcrY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8gN4okKn5t65LcrY .marker.cross{stroke:#333333;}#mermaid-svg-8gN4okKn5t65LcrY svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8gN4okKn5t65LcrY p{margin:0;}#mermaid-svg-8gN4okKn5t65LcrY .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8gN4okKn5t65LcrY .cluster-label text{fill:#333;}#mermaid-svg-8gN4okKn5t65LcrY .cluster-label span{color:#333;}#mermaid-svg-8gN4okKn5t65LcrY .cluster-label span p{background-color:transparent;}#mermaid-svg-8gN4okKn5t65LcrY .label text,#mermaid-svg-8gN4okKn5t65LcrY span{fill:#333;color:#333;}#mermaid-svg-8gN4okKn5t65LcrY .node rect,#mermaid-svg-8gN4okKn5t65LcrY .node circle,#mermaid-svg-8gN4okKn5t65LcrY .node ellipse,#mermaid-svg-8gN4okKn5t65LcrY .node polygon,#mermaid-svg-8gN4okKn5t65LcrY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8gN4okKn5t65LcrY .rough-node .label text,#mermaid-svg-8gN4okKn5t65LcrY .node .label text,#mermaid-svg-8gN4okKn5t65LcrY .image-shape .label,#mermaid-svg-8gN4okKn5t65LcrY .icon-shape .label{text-anchor:middle;}#mermaid-svg-8gN4okKn5t65LcrY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8gN4okKn5t65LcrY .rough-node .label,#mermaid-svg-8gN4okKn5t65LcrY .node .label,#mermaid-svg-8gN4okKn5t65LcrY .image-shape .label,#mermaid-svg-8gN4okKn5t65LcrY .icon-shape .label{text-align:center;}#mermaid-svg-8gN4okKn5t65LcrY .node.clickable{cursor:pointer;}#mermaid-svg-8gN4okKn5t65LcrY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8gN4okKn5t65LcrY .arrowheadPath{fill:#333333;}#mermaid-svg-8gN4okKn5t65LcrY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8gN4okKn5t65LcrY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8gN4okKn5t65LcrY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8gN4okKn5t65LcrY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8gN4okKn5t65LcrY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8gN4okKn5t65LcrY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8gN4okKn5t65LcrY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8gN4okKn5t65LcrY .cluster text{fill:#333;}#mermaid-svg-8gN4okKn5t65LcrY .cluster span{color:#333;}#mermaid-svg-8gN4okKn5t65LcrY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8gN4okKn5t65LcrY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8gN4okKn5t65LcrY rect.text{fill:none;stroke-width:0;}#mermaid-svg-8gN4okKn5t65LcrY .icon-shape,#mermaid-svg-8gN4okKn5t65LcrY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8gN4okKn5t65LcrY .icon-shape p,#mermaid-svg-8gN4okKn5t65LcrY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8gN4okKn5t65LcrY .icon-shape .label rect,#mermaid-svg-8gN4okKn5t65LcrY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8gN4okKn5t65LcrY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8gN4okKn5t65LcrY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8gN4okKn5t65LcrY :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    DB Container

    App Container

    宿主机

    HTTP 8080

    JDBC

    Persistent Volume

    Logs

    Chrome / curl

    App Container

    DB Container

    pg-data Volume

    stdout/stderr

    Spring Boot App

    Actuator Health

    Web MVC

    PostgreSQL 15

    Database demoapp

    ✅ 此图清晰展示:

    • 宿主机用户通过浏览器访问 localhost:8080 → 流量进入 App 容器
    • App 容器内部 Spring Boot 应用通过 JDBC 连接 DB 容器(服务名 db 解析为 IP)
    • DB 容器将数据持久化到 命名卷 pg-data(而非容器层,重启不丢失)
    • 所有日志输出到标准输出 → 可被 docker logs 统一收集 ✅

    七、进阶:生产就绪必备技能 🔐

    🔐 1. 安全加固:非 root 运行 + 最小权限

    上文 Dockerfile 已创建 appuser,但还需验证其权限:

    # 进入运行中的容器
    docker exec -it my-spring-container sh

    # 检查当前用户
    whoami # → appuser
    id # → uid=1001(appuser) gid=1001(appgroup) groups=1001(appgroup)
    ls -l /app.jar # → -rw-r–r– 1 appuser appgroup … app.jar
    ps aux | grep java # → USER=appuser,非 root!
    exit

    ✅ 安全基线达成:无 root 权限、无 shell、无敏感文件读写权。

    📈 2. 监控与指标:集成 Prometheus + Grafana(轻量方案)

    Spring Boot Actuator 已暴露 /actuator/metrics 端点。我们用 prom/prometheus 和 grafana/grafana 快速搭建监控:

    在 docker-compose.yml 中追加:

    prometheus:
    image: prom/prometheus:latest
    restart: unlessstopped
    ports:
    "9090:9090"
    volumes:
    ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
    appnetwork

    grafana:
    image: grafana/grafana:latest
    restart: unlessstopped
    ports:
    "3000:3000"
    environment:
    GF_SECURITY_ADMIN_PASSWORD: admin123
    volumes:
    grafanastorage:/var/lib/grafana
    networks:
    appnetwork

    volumes:
    grafana-storage:

    创建 prometheus.yml(同目录):

    global:
    scrape_interval: 15s

    scrape_configs:
    job_name: 'spring-boot'
    metrics_path: '/actuator/prometheus'
    static_configs:
    targets: ['app:8080']

    启动后:

    • Prometheus:http://localhost:9090/targets → 应看到 app:8080 UP ✅
    • Grafana:http://localhost:3000(账号 admin/admin123)→ 添加 Prometheus 数据源 → 导入 Spring Boot Dashboard ID 12856 ✅

    🌐 外部参考:Prometheus 官方入门指南 与 Grafana Spring Boot Dashboard 提供了开箱即用的可视化方案。

    📦 3. 日志集中管理:ELK 精简版(Elasticsearch + Logstash + Kibana)

    对大型集群,建议用 ELK。但单机开发可用更轻量的 sebp/elk 镜像:

    docker run -d \\
    –name elk \\
    -p 5601:5601 -p 9200:9200 -p 5044:5044 \\
    -e ES_HEAP_SIZE=1g \\
    -e LOGSTASH_START=0 \\
    -e KIBANA_START=1 \\
    -v /path/to/logs:/var/log/logstash \\
    sebp/elk:8100

    然后在 docker-compose.yml 的 app 服务中添加日志驱动:

    logging:
    driver: "gelf"
    options:
    gelf-address: "udp://localhost:12201"

    ✅ 启动后访问 http://localhost:5601 → Kibana → 创建索引模式 logstash-* → 实时查看所有容器日志。


    八、常见故障排查手册 🛠️

    遇到问题?别慌,按此清单逐项检查:

    现象可能原因解决命令
    docker: command not found Docker Desktop 未启动 / CLI 未加入 PATH macOS/Linux:echo $PATH;Windows:检查 WSL2 中 which docker
    Cannot connect to the Docker daemon Docker 引擎未运行 systemctl status docker(Linux);macOS/Windows:打开 Docker Desktop 图标
    Connection refused(连 DB) depends_on 仅等容器启动,未等服务就绪 ✅ 使用 healthcheck + condition: service_healthy(见上文)
    java.lang.OutOfMemoryError JVM 未设内存上限,容器被 OOM Killer 杀死 在 Dockerfile ENTRYPOINT 加 -Xmx384m -Xms256m;或 docker run –memory=512m
    Error response from daemon: Conflict. The container name "/xxx" is already in use 容器名重复 docker rm -f xxx 或改 –name
    The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) Apple Silicon 运行 x86 镜像 docker build –platform linux/amd64 -t xxx . 或选用 arm64 镜像(如 amazoncorretto:17-jre-alpine 原生支持)

    💡 终极调试命令(记住这 3 个):

    # 查看容器详细信息(含 IP、挂载、网络)
    docker inspect <container-name>

    # 进入容器执行诊断命令(如 ping, curl, netstat)
    docker exec -it <container-name> sh

    # 查看容器资源实时使用(CPU、内存、网络 IO)
    docker stats <container-name>


    九、持续集成与交付(CI/CD)初探 🔄

    Docker 是 CI/CD 的基石。以下是一个 GitHub Actions 兼容的 .github/workflows/ci.yml 逻辑示意(不依赖 GitHub,纯概念):

    name: Build and Test Docker Image

    on: [push, pull_request]

    jobs:
    build:
    runs-on: ubuntulatest
    steps:
    uses: actions/checkout@v4

    # 登录 Docker Hub(若需推送)
    name: Login to Docker Hub
    uses: docker/loginaction@v3
    with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

    # 构建并测试镜像
    name: Build and Test
    run: |
    docker build -t my-spring-app:test .
    docker run –rm my-spring-app:test java -cp app.jar org.springframework.boot.loader.JarLauncher –help

    # 推送镜像(可选)
    name: Push to Docker Hub
    if: github.event_name == 'push' && startsWith(github.head_ref, 'release/')
    run: |
    docker tag my-spring-app:test ${{ secrets.DOCKER_USERNAME }}/my-spring-app:latest
    docker push ${{ secrets.DOCKER_USERNAME }}/my-spring-app:latest

    ✅ 核心价值:

    • 每次代码提交,自动构建镜像 → 验证 Dockerfile 是否可执行 ✅
    • 运行 java -cp … –help → 快速验证 JAR 可启动(不启动完整 Spring Boot)✅
    • 镜像推送后,生产环境只需 docker pull && docker run → 彻底消除“环境差异” ✅

    十、结语:拥抱容器化,就是拥抱确定性 🌈

    Docker 不是魔法,它是一套用声明式语法描述环境、用分层镜像固化依赖、用命名卷保障数据、用自定义网络定义拓扑的工程范式。当你第一次在 Windows 上构建的镜像,未经修改直接在 macOS 或 Ubuntu 服务器上完美运行时,你会真切体会到:

    “环境一致性” 不再是运维的口头禅,而是你 docker run 命令敲下回车后的必然结果。

    本文覆盖了从零安装、Java 应用容器化、多服务编排、安全加固到监控可观测性的全链路。所有代码、配置、命令均经过跨平台实测,无任何平台特异性陷阱。

    下一步,你可以:

    • 将本文 Dockerfile 与 docker-compose.yml 应用到你的真实项目中
    • 为团队制定《Docker 最佳实践规范》(如镜像命名规则、标签策略、安全扫描流程)
    • 探索 Kubernetes(K8s)—— Docker 的生产级编排演进方向

    🌐 最后,推荐一个永久有效的学习入口:Docker 官方文档中心 —— 它没有过期链接,没有版本幻觉,只有持续更新、经严格测试的技术事实。把它加入你的浏览器书签,随时查阅。

    愿你每一次 docker build 都成功,每一次 docker run 都稳定,每一次 docker ps 都看到自己精心编排的系统,如星辰般有序运转 🌟


    🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

    赞(0)
    未经允许不得转载:171主机测评 » Docker - 环境搭建全攻略,Windows_macOS_Linux通用
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址