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 的环境中,实现快速交付和弹性伸缩。

相关推荐
xingyuzhisuan2 小时前
4090部署DeepSeek-V3:CPU卸载层数实测指南
运维·深度学习·gpu算力
一目Leizi2 小时前
Burp Suite实战:利用不同响应进行用户名枚举与密码爆破
运维·服务器·安全
从零点3 小时前
第三节linux,编译linux源码
linux·运维·服务器
祢真伟大3 小时前
dmagent-2026监控服务器代理部署
运维·服务器
有毒的教程3 小时前
Ubuntu 清理 Docker 镜像 / 容器 / 缓存 完整教程
ubuntu·缓存·docker
阿干tkl3 小时前
openEuler 系统 Kubernetes + Harbor 学习测试环境详细部署指南
容器·kubernetes
LSL666_4 小时前
云服务上安装nginx
java·运维·nginx
Luminbox紫创测控4 小时前
氙灯太阳光模拟器如何获得AM 1.5G标准太阳光谱?
运维·人工智能·5g
运维行者_4 小时前
通过 OpManager 集成 Firewall Analyzer 插件,释放统一网络管理与安全的强大能力
大数据·运维·服务器·网络·数据库·安全