Docker 入门

Docker 入门

  • [Docker 基础概念与 Java 实战指南](#Docker 基础概念与 Java 实战指南)
    • [一、Docker 基础概念](#一、Docker 基础概念)
      • [1.1 什么是 Docker](#1.1 什么是 Docker)
      • [1.2 核心概念](#1.2 核心概念)
        • [1.2.1 镜像(Image)](#1.2.1 镜像(Image))
        • [1.2.2 容器(Container)](#1.2.2 容器(Container))
        • [1.2.3 仓库(Repository)与 Registry](#1.2.3 仓库(Repository)与 Registry)
        • [1.2.4 Docker 架构](#1.2.4 Docker 架构)
        • [1.2.5 数据卷(Volume)](#1.2.5 数据卷(Volume))
        • [1.2.6 网络(Network)](#1.2.6 网络(Network))
        • [1.2.7 Dockerfile](#1.2.7 Dockerfile)
        • [1.2.8 Docker Compose](#1.2.8 Docker Compose)
    • [二、Java 下 Docker 的常用使用](#二、Java 下 Docker 的常用使用)
      • [2.1 基础镜像的选择](#2.1 基础镜像的选择)
      • [2.2 编写 Dockerfile(以 Spring Boot 为例)](#2.2 编写 Dockerfile(以 Spring Boot 为例))
        • [2.2.1 单阶段构建(简单但镜像较大)](#2.2.1 单阶段构建(简单但镜像较大))
        • [2.2.2 多阶段构建(推荐,减小最终镜像体积)](#2.2.2 多阶段构建(推荐,减小最终镜像体积))
        • [2.2.3 常用 Dockerfile 指令详解](#2.2.3 常用 Dockerfile 指令详解)
      • [2.3 构建与运行 Java 镜像](#2.3 构建与运行 Java 镜像)
        • [2.3.1 构建镜像](#2.3.1 构建镜像)
        • [2.3.2 运行容器](#2.3.2 运行容器)
      • [2.4 使用 Docker Compose 编排 Java 应用](#2.4 使用 Docker Compose 编排 Java 应用)
        • [2.4.1 示例:Spring Boot + MySQL](#2.4.1 示例:Spring Boot + MySQL)
        • [2.4.2 常用 Compose 命令](#2.4.2 常用 Compose 命令)
      • [2.5 Java 应用 Docker 最佳实践](#2.5 Java 应用 Docker 最佳实践)
        • [2.5.1 镜像层优化](#2.5.1 镜像层优化)
        • [2.5.2 安全加固](#2.5.2 安全加固)
        • [2.5.3 资源限制](#2.5.3 资源限制)
        • [2.5.4 日志管理](#2.5.4 日志管理)
        • [2.5.5 健康检查](#2.5.5 健康检查)
        • [2.5.6 .dockerignore 文件](#2.5.6 .dockerignore 文件)
        • [2.5.7 使用环境变量管理配置](#2.5.7 使用环境变量管理配置)
      • [2.6 常见问题与调试](#2.6 常见问题与调试)
        • [2.6.1 容器启动后立即退出](#2.6.1 容器启动后立即退出)
        • [2.6.2 端口映射无效](#2.6.2 端口映射无效)
        • [2.6.3 容器间通信失败](#2.6.3 容器间通信失败)
        • [2.6.4 镜像体积过大](#2.6.4 镜像体积过大)
      • [2.7 小结](#2.7 小结)

Docker 基础概念与 Java 实战指南

一、Docker 基础概念

1.1 什么是 Docker

Docker 是一个开源的容器化平台,它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中,然后在任何支持 Docker 的环境中运行。与传统的虚拟机相比,容器共享宿主机的操作系统内核,因此启动更快、资源占用更少。而虚拟机是包含完整的客户操作系统(Guest OS),模拟了整个OS系统,开销非常大。

1.2 核心概念

1.2.1 镜像(Image)
  • 定义镜像是只读的模板,包含运行应用程序所需的一切(代码、运行时、系统工具、库、环境变量等)。
  • 特点:镜像由多层文件系统(UnionFS)堆叠而成,每一层都是只读的,构建时通过层缓存加速。
  • 命名repository:tag,如 openjdk:17-jdk-slim,tag 不指定时默认为 latest
1.2.2 容器(Container)
  • 定义:容器是镜像的运行实例,在只读镜像层之上添加一个可写层。
  • 生命周期:可以创建、启动、停止、删除。容器被删除后,可写层数据丢失(除非使用卷持久化)。
  • 隔离性:利用 Linux 内核的 namespace(命名空间)和 cgroups(控制组)实现进程、网络、文件系统的隔离与资源限制。
1.2.3 仓库(Repository)与 Registry
  • 仓库:用于存储镜像的集合,通常包含同一个镜像的不同版本(tag)。
  • Registry :仓库服务端,例如 Docker Hub(公共)、阿里云镜像服务(私有/公有)。docker pulldocker push 与 Registry 交互。
1.2.4 Docker 架构
  • Client(客户端) :用户通过 docker 命令与 Docker 守护进程通信。
  • Daemon(守护进程):负责管理镜像、容器、网络、卷等,监听客户端请求。
  • Registry:存储镜像的远程服务。
1.2.5 数据卷(Volume)
  • 目的:持久化和共享容器数据,解决容器可写层数据随容器删除而丢失的问题。
  • 类型
    • 卷(Volume) :由 Docker 管理,存储在宿主机特定目录(/var/lib/docker/volumes/),推荐使用。
    • 绑定挂载(Bind Mount):将宿主机任意目录挂载到容器,便于开发时实时同步代码。
    • 临时挂载(tmpfs):仅存于宿主机内存,不持久化。
1.2.6 网络(Network)
  • 默认网络:bridge(单机桥接网络)、host(与宿主机共享网络)、none(无网络)。
  • 自定义网络 :通过 docker network create 创建,支持容器间通过容器名通信(内置 DNS)。
  • 常用驱动:bridge(默认)、overlay(跨主机)。
1.2.7 Dockerfile
  • 定义:文本文件,包含一系列指令,用于自动化构建镜像。
  • 关键指令FROMRUNCOPYADDWORKDIREXPOSECMDENTRYPOINTENVVOLUME
1.2.8 Docker Compose
  • 定义 :用于定义和运行多容器 Docker 应用的工具,通过 docker-compose.yml 配置文件一次性管理多个服务。
  • 核心概念:services(服务)、networks(网络)、volumes(卷)。

二、Java 下 Docker 的常用使用

2.1 基础镜像的选择

Java 应用的 Docker 镜像通常以官方 OpenJDK 或第三方构建的 JDK 为基础。常见选项:

镜像名称 特点 适用场景
openjdk:<version>-jdk-slim 基于 Debian slim,体积较小,包含完整 JDK 开发、构建
openjdk:<version>-jre-slim 仅包含 JRE,体积更小 运行已编译的 Java 应用
eclipse-temurin:<version>-jdk-alpine 基于 Alpine Linux,体积极小,但可能存在 glibc 兼容性问题 追求极致镜像大小
amazoncorretto:<version>-alpine Amazon 提供的免费 OpenJDK 发行版,长期支持 生产环境推荐
azul/zulu-openjdk-alpine Azul 提供的 OpenJDK 构建 备选方案

注意:Alpine 镜像使用 musl libc 而非 glibc,某些依赖本地库的 Java 应用可能需要额外安装 glibc 或选择 slim 版本。

2.2 编写 Dockerfile(以 Spring Boot 为例)

2.2.1 单阶段构建(简单但镜像较大)
shell 复制代码
# 使用官方 OpenJDK 17 基础镜像
FROM openjdk:17-jdk-slim

# 设置工作目录
WORKDIR /app

# 将本地的 jar 包复制到容器中
COPY target/myapp-1.0.0.jar /app/app.jar

# 暴露应用端口
EXPOSE 8080

# 启动命令
CMD ["java", "-jar", "app.jar"]
2.2.2 多阶段构建(推荐,减小最终镜像体积)
shell 复制代码
# 第一阶段:构建阶段(使用完整 JDK)
FROM maven:3.8.6-openjdk-17 AS builder
WORKDIR /build
# 复制 pom.xml 并下载依赖(利用层缓存)
COPY pom.xml .
RUN mvn dependency:go-offline

# 复制源代码并打包
COPY src ./src
RUN mvn clean package -DskipTests

# 第二阶段:运行阶段(使用精简 JRE)
FROM openjdk:17-jre-slim
WORKDIR /app

# 从构建阶段复制生成的 jar 包
COPY --from=builder /build/target/myapp-*.jar ./app.jar

# 创建非 root 用户运行(安全最佳实践)
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2.2.3 常用 Dockerfile 指令详解
  • FROM:指定基础镜像,尽量选择官方镜像且指定具体版本。
  • WORKDIR :设置工作目录,后续 RUN, CMD, COPY 均以此目录为相对路径。
  • COPY / ADD:将本地文件复制到镜像。ADD 支持 URL 和自动解压 tar,通常优先使用 COPY。
  • RUN :执行命令(如 mvn package),每个 RUN 会创建一层镜像层,应尽量合并(如使用 && 连接多个命令)以减少层数。
  • EXPOSE :声明容器运行时监听的端口,仅为文档说明,真正映射需在 docker run 时用 -p
  • CMD / ENTRYPOINT :指定容器启动时执行的命令。ENTRYPOINT 更适合固定命令,CMD 提供默认参数,二者常结合使用(例如 ENTRYPOINT ["java"], CMD ["-jar", "app.jar"])。
  • ENV :设置环境变量(如 ENV JAVA_OPTS="-Xmx512m")。
  • USER:切换用户,避免使用 root 运行应用。
  • HEALTHCHECK:定义健康检查命令,用于判断容器是否健康。

2.3 构建与运行 Java 镜像

2.3.1 构建镜像
bash 复制代码
# 在项目根目录(包含 Dockerfile 的位置)执行
docker build -t myapp:1.0.0 .
  • -t:指定镜像名称和标签。
  • .:构建上下文路径,Docker 会将该路径下的所有文件发送给守护进程(可通过 .dockerignore 排除不必要文件)。
2.3.2 运行容器
bash 复制代码
# 基本运行
docker run -d --name myapp -p 8080:8080 myapp:1.0.0

# 设置 JVM 参数
docker run -d --name myapp -p 8080:8080 -e JAVA_OPTS="-Xmx512m -Xms256m" myapp:1.0.0

# 挂载宿主机目录(例如日志或配置文件)
docker run -d --name myapp -p 8080:8080 -v /host/logs:/app/logs myapp:1.0.0

# 指定网络
docker run -d --name myapp --network mynetwork myapp:1.0.0
  • -d:后台运行。
  • --name:容器名称。
  • -p:宿主机端口:容器端口。
  • -e:设置环境变量。
  • -v:挂载卷或绑定挂载。
  • --network:连接到自定义网络。

2.4 使用 Docker Compose 编排 Java 应用

当应用依赖外部服务(如 MySQL、Redis)时,使用 Docker Compose 可一键启动所有服务。

2.4.1 示例:Spring Boot + MySQL

项目结构:

复制代码
myapp/
├── my_module
├─────────dockerfile
├── docker-compose.yml
└── ...(源代码等)

docker-compose.yml

yaml 复制代码
version: '3.8'

services:
  # MySQL 数据库服务
  mysql:
    image: mysql:8.0
    container_name: mysql-db
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: mydb
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Spring Boot 应用
  app:
    build: .
    container_name: spring-app
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
      SPRING_DATASOURCE_USERNAME: appuser
      SPRING_DATASOURCE_PASSWORD: apppass
    - nacos-server-addr=172.17.0.1:8848
    - nacos-namespace=UUID 格式的字符串作为 ID(e8b6f5a4-1234-4567-89ab-cdef01234567)
    - nacos-group=DEFAULT_GRTOUP
    - nacos-username=nacos
    - nacos-password=nacos
      # 其他 JVM 参数
      JAVA_OPTS: "-Xmx512m"
    depends_on:
      mysql:
        condition: service_healthy
    networks:
      - app-network
    # 如果应用需要等待数据库完全就绪,可以添加启动前的命令
    # command: sh -c "sleep 20 && java -jar app.jar"

networks:
  app-network:
    driver: bridge

volumes:
  mysql-data:
2.4.2 常用 Compose 命令
bash 复制代码
# 启动所有服务(后台)
docker-compose up -d

# 停止并删除所有服务、网络
docker-compose down

# 查看日志
docker-compose logs -f app

# 重新构建并启动
docker-compose up -d --build

# 仅构建镜像
docker-compose build

2.5 Java 应用 Docker 最佳实践

2.5.1 镜像层优化
  • 合并 RUN 命令 :例如 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*,避免产生中间层。
  • 利用构建缓存 :将变化频率低的指令(如 COPY pom.xml)放在前面,频繁变化的(如源码)放在后面。
  • 多阶段构建:如前面示例,将构建工具和源码留在最终镜像之外,仅保留运行所需的 jar 包。
2.5.2 安全加固
  • 使用非 root 用户 :在 Dockerfile 中创建专用用户并切换(如 USER appuser)。
  • 定期更新基础镜像:及时拉取包含安全补丁的镜像。
  • 避免敏感信息:不要将密码、密钥写入 Dockerfile,应通过环境变量或 secrets 注入。
2.5.3 资源限制
  • 内存限制docker run -m 512m --memory-swap 512m ... 或 Compose 中 mem_limit: 512m
  • CPU 限制docker run --cpus=1.5 或 Compose 中 cpus: 1.5
2.5.4 日志管理
  • 将 Java 应用的日志输出到标准输出(stdout)和标准错误(stderr),由 Docker 收集(通过 docker logs 查看)。
  • 如果需要持久化日志,可以使用挂载卷或 Docker 日志驱动(如 json-filesyslog)。
2.5.5 健康检查

在 Dockerfile 中添加 HEALTHCHECK,或在 Compose 中配置 healthcheck,让编排系统自动监控容器状态。

shell 复制代码
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/actuator/health || exit 1
2.5.6 .dockerignore 文件

避免将不需要的文件(如 .gittarget/*.lognode_modules)发送到构建上下文,提高构建速度并减小镜像体积。

示例 .dockerignore

复制代码
.git
target/
*.log
.idea
*.iml
2.5.7 使用环境变量管理配置

Spring Boot 支持通过环境变量覆盖配置,推荐在 Compose 中设置 SPRING_ 系列变量,而非硬编码。

2.6 常见问题与调试

2.6.1 容器启动后立即退出
  • 原因:主进程执行完毕即退出。检查 CMD/ENTRYPOINT 是否正确,或应用是否有未捕获异常。
  • 调试:docker logs <container> 查看日志;或使用 docker run -it 交互式运行查看输出。
2.6.2 端口映射无效
  • 检查 EXPOSE 是否声明(非必须但建议),-p 参数是否正确,容器内应用是否监听了对应端口。
2.6.3 容器间通信失败
  • 使用自定义网络,并通过服务名(Compose)或容器名(--link 已废弃)访问。
  • 确保数据库等服务的健康检查通过后再启动应用(使用 depends_on 配合 condition)。
2.6.4 镜像体积过大
  • 使用 docker history <image> 查看镜像层大小,定位大文件。
  • 采用多阶段构建,删除不必要的依赖和中间文件。

2.7 小结

通过 Docker 容器化 Java 应用,可以保证开发、测试、生产环境的一致性,简化部署流程。关键点在于:

  • 选择合适的基础镜像,并采用多阶段构建优化体积。
  • 编写高效、安全的 Dockerfile。
  • 利用 Docker Compose 管理多服务依赖。
  • 遵循最佳实践(非 root 用户、资源限制、健康检查等)。

掌握这些技能后,你可以将 Java 应用轻松部署到任何支持 Docker 的环境中,实现快速交付和弹性伸缩。

相关推荐
大树882 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工3 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn863 小时前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
酣大智4 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_4 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉5 小时前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造
AC赳赳老秦5 小时前
用 OpenClaw 搭建服务器故障应急响应系统,自动处理 80% 常见运维故障
android·运维·服务器·python·rxjava·deepseek·openclaw
2601_961875246 小时前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant