一、Docker学习
(1)Docker简介
Docker 是一个开源容器化平台,用于将应用程序及其依赖环境打包成轻量级、可移植的容器。以下是其核心特性:
核心概念
1. 容器
- 独立运行的沙箱环境,包含应用代码、运行时、系统工具等。
- 基于镜像启动,共享主机操作系统内核,比虚拟机更轻量、启动更快。2. 镜像(Image)
- 只读模板,用于创建容器(类似程序安装包)。
- 通过分层存储优化空间,支持版本管理和复用。3. Dockerfile
- 文本文件定义镜像构建步骤(如安装依赖、复制文件)。
- 通过 `docker build` 命令生成镜像。4. Docker Hub
- 公共镜像仓库,提供预构建的官方/社区镜像(如Nginx、MySQL)。优势
- 环境一致性:解决“在我机器上能跑”问题,开发、测试、生产环境一致。
- 快速部署:秒级启动容器,支持水平扩展。
- 资源高效:无需完整虚拟化,节省内存和CPU。
- 隔离性:每个容器独立运行,避免依赖冲突。
- 跨平台:支持Linux、Windows、云服务器等。典型应用场景
- 微服务架构:将单体应用拆分为独立容器。
- 持续集成/交付(CI/CD):自动化构建、测试、部署流水线。
- 本地开发:快速搭建复杂依赖环境(如数据库+Redis)。
- 混合云部署:容器可在不同云平台无缝迁移。
(2)Docker基本组成:镜像(image)、容器(container)、仓库(repository)
结合Java的学习:镜像为Java的类模版,容器为通过类模版new出来的对象,仓库存放镜像的地方。
用Java中的代码解释:
/**
* 镜像模板类(相当于Dockerfile)
* 注解说明:
* @Image 标记这是一个镜像定义
* @Layer 表示镜像分层(基础层->JDK层->应用层)
*/
@Image
public class JavaWebImage {
// 基础层:相当于 FROM openjdk:11
@Layer(order = 1)
private String baseImage = "openjdk:11-jre";
// 依赖层:相当于 RUN apt-get install...
@Layer(order = 2)
private List<String> dependencies = Arrays.asList(
"libssl1.1",
"ca-certificates"
);
// 应用层:相当于 ADD target/app.jar /app.jar
@Layer(order = 3)
private String applicationJar = "target/myapp-1.0.0.jar";
// 入口点:相当于 ENTRYPOINT ["java","-jar","/app.jar"]
@EntryPoint
public void start() {
Runtime.run("java -jar " + applicationJar);
}
}
(3)仓库(Repository)-> 包管理
public class RepositoryDemo {
public static void main(String[] args) {
// 本地仓库操作(相当于 docker pull/push)
DockerRegistry localRepo = new LocalRegistry("~/.docker/local");
// 从远程仓库拉取镜像
JavaWebImage officialImage = localRepo.pull("registry.mycorp.com/java-web:1.0");
// 打标签并推送到私有仓库
officialImage.tag("1.0", "prod-v1.2");
localRepo.push("registry.mycorp.com/java-web:prod-v1.2");
// 查询仓库列表(相当于 docker images)
System.out.println("本地镜像列表:");
localRepo.listImages().forEach(System.out::println);
}
}
(4)完整操作流程类比
Docker操作流程 vs Java代码流程
// ==== Docker实际命令 ====
// 1. 编写Dockerfile
// 2. docker build -t myapp:1.0 .
// 3. docker run -d myapp:1.0
// 4. docker push registry.example.com/myapp:1.0
// ==== Java代码模拟 ====
public class FullProcess {
public static void main(String[] args) {
// 1. 编写镜像定义(Dockerfile)
Class<JavaWebImage> imageClass = JavaWebImage.class;
// 2. 构建镜像(docker build)
ImageBuilder builder = new ImageBuilder();
JavaWebImage image = builder.build(imageClass)
.withTag("myapp:1.0")
.build();
// 3. 运行容器(docker run)
Container<JavaWebImage> container = new Container<>(image);
container.start()
.withEnv("JAVA_OPTS", "-Xmx512m")
.withPortMapping(8080, 80);
// 4. 推送镜像(docker push)
DockerRegistry registry = new RemoteRegistry("registry.example.com");
registry.login("user", "password");
registry.push(image, "myapp:1.0");
}
}
(5)高级特性类比
1、镜像分层(Layer)
/**
* 分层结构示例(通过继承实现)
*/
public abstract class BaseImage { // 基础镜像层
protected String os = "Linux 5.4.0";
protected String arch = "x86_64";
}
public class JdkImage extends BaseImage { // 中间层
protected String jdkVersion = "11.0.15";
protected List<String> jdkModules = List.of("java.base", "java.sql");
}
public class AppImage extends JdkImage { // 应用层
private String appJar = "app-v1.2.3.jar";
private String entryPoint = "java -jar " + appJar;
}
2、容器网络(Network)
public class NetworkDemo {
public static void main(String[] args) {
// 创建网络(相当于 docker network create)
DockerNetwork myNetwork = new BridgeNetwork("my-bridge");
// 容器加入网络(相当于 --network)
JavaWebImage webContainer = new JavaWebImage();
MySQLImage dbContainer = new MySQLImage();
myNetwork.connect(webContainer);
myNetwork.connect(dbContainer);
// 设置网络别名(相当于 --network-alias)
webContainer.setNetworkAlias("webapp");
dbContainer.setNetworkAlias("mysql-primary");
}
}
(6)注意事项
1、状态差异:
Java对象通常保持状态,而Docker容器推荐无状态设计
容器文件系统层是写时复制(Copy-on-Write)机制,不同于Java对象内存分配
2、生命周期管理:
// 错误示例:直接删除运行中的容器
public void wrongDemo() {
JavaWebImage container = new JavaWebImage();
container.start();
container.delete(); // 抛出ContainerRunningException
}
// 正确做法:先停止再删除
public void correctDemo() {
JavaWebImage container = new JavaWebImage();
container.start();
container.stop();
container.delete();
}
3、资源限制:
// 设置容器资源限制(相当于 -m, --cpus)
container.config()
.setMemoryLimit(1024) // 1GB内存
.setCpuShares(0.5) // 50% CPU
.apply();