首页 > 编程语言 >让 Java 再次伟大 - 你不知道的 Java 之集成 Docker 的那些密事(一章节)

让 Java 再次伟大 - 你不知道的 Java 之集成 Docker 的那些密事(一章节)

时间:2025-01-02 13:25:25浏览次数:7  
标签:... Layer 缓存 Java COPY 指令 RUN Docker 密事

学会这款 全新设计的 Java 脚手架 ,从此面试不再怕!

在这里插入图片描述

Docker 的底层实现原理

Docker 是一种容器服务,为了方便理解你可以认为他是一个轻量级的虚拟机。通过 Docker 创建的容器,在宿主机上共享硬件资源和底层系统与接口,同时又能提供互相隔离的应用程序环境。
这是怎么做到的?由于 Linux 一切资源皆文件,所以只要简单的使用命名空间即可实现进程之间的隔离。

就像下面这个树形菜单,每个进程在自己的「文件夹/命名空间」中运作,互不干扰。

├── proc/
│   ├── 1/              # 系统初始化进程(主机)
│   │   ├── cmdline
│   │   └── status
│   ├── 2/              # 内核线程(主机)
│   │   ├── cmdline
│   │   └── status
│   ├── 100/            # 用户进程 A(主机 PID 100,用户 A 的 PID 1)
│   │   ├── cmdline
│   │   └── status
│   └── 200/            # 用户进程 B(主机 PID 200,用户 B 的 PID 1)
│       ├── cmdline
│       └── status
├── sys/
│   └── class/net/
│       ├── eth0/       # 以太网接口(主机)
│       ├── wlan0/      # 无线网络接口(主机)
│       ├── veth0/      # 用户 A 的虚拟网络接口(用户 A 的命名空间)
│       └── veth1/      # 用户 B 的虚拟网络接口(用户 B 的命名空间)
└── etc/
    ├── hostname        # 主机的主机名文件(主机)
    ├── hostname_a      # 用户 A 的主机名文件(用户 A 的命名空间)
    └── hostname_b      # 用户 B 的主机名文件(用户 B 的命名空间)

Layer 与缓存

容器本身也是一个进程,未运行的容器称为容器镜像。容器镜像由指令构成,这些指令的集合成为 Dockerfile

FROM ubuntu:latest

RUN apt-get update && apt-get install -y build-essentials
COPY main.c Makefile /src/
WORKDIR /src/
RUN make build

上面这个最典型的 Dockerfile 中的每一个指令的执行结果都会形成一个 Layer(层),而镜像是层的集合。
在这里插入图片描述

层是可复用的,通过指令创建的层会被缓存起来。如果下一次有同样的指令就会优先使用这个被缓存起来的层。这就是为什么第一次下载镜像时会很慢,而后面再下载有关联的镜像时就很快的原因。

Step 1/2 : FROM ubuntu:20.04
 ---> abc123...
Step 2/2 : RUN apt-get update && apt-get install -y curl
 ---> Running in def456...
Removing intermediate container def456...
 ---> ghi789...
Successfully built ghi789...
Successfully tagged my-image:latest

---------------------------------------------------------

Step 1/2 : FROM ubuntu:20.04
 ---> abc123...
Step 2/2 : RUN apt-get update && apt-get install -y curl
 ---> Using cache
 ---> ghi789...
Successfully built ghi789...
Successfully tagged my-image:latest

缓存失效

在上例中,如果你修改了 main.c 的内容,那这个指令对应的 Layer 就失效了,这个层就会被重新构建。这是期望的行为,你当然希望层能够反应最新的内容。但要注意一旦某个 layer 过期,该层以下的所有层会全部失效,这会大大增加你的构建时间。
在这里插入图片描述

缓存复用

指令的分割与排序

所以为了减少构建所需时间,我们常常会想办法复用缓存,尽可能把缓存失效的影响范围缩减到最小。下面这个 dockerfile 中包含了一个 COPY 指令,这个指令会拷贝当前目录的所有内容到镜像的工作目录中

FROM node
WORKDIR /app
COPY . .          
RUN npm install  
RUN npm build    

很显然,当前目录的内容肯定包含你的代码文件,而代码文件又是非常容易发生变动的。如果我们将项目的依赖定义文件和代码文件分开定义,就能创建更加内聚的 Layer ,增加了复用缓存的可能性。

FROM node
WORKDIR /app
COPY package.json yarn.lock .    # 先拷贝依赖定义文件
RUN npm install                  # 安装依赖文件
COPY . .                         # 再拷贝项目文件
RUN npm build                    # 构建镜像

当重新构建时,如果你的依赖没有发生变化,那上一次 RUN npm install 形成的 Layer 就可以得到复用。因为 COPY package.json yarn.lock . 的内容没有发生变化。这样就节省了每次构建都重新下载依赖的时间。最后再将 COPY . . 这样容易发生变化的指令放到 dockerfile 的最后来执行,也能减小缓存的失效范围。
你看,软件工程的思想都是相通的,复用代码的思路在 dockerfile 中依然适用。所以良好的编码习惯的养成并不仅仅只是让你的代码看起来更漂亮一点。

减少构建体积

COPY 指令会对指定目录下的所有文件就行拷贝。而很多东西是你不需要拷贝到镜像中的,比如 .history .git node_modules 等等和代码无关的产物。使用 .dockerignore 就可以配置想要忽略的文件或目录。

node_modules
tmp*
.history
.git
...

这就结束了吗?

本篇文章主要对 Docker 及其 Layer 缓存做一些初步介绍。文中的思路用来解决一些基本问题是可行的;但是 docker 的 Layer 设计并不能在所有问题中都发挥良好,有些问题需要更加高级的手段才能够得以解决。关注我的账号,我将在后续的章节中更新更多内容。

标签:...,Layer,缓存,Java,COPY,指令,RUN,Docker,密事
From: https://blog.csdn.net/ccmjga/article/details/144853855

相关文章

  • 【Java项目】基于SpringBoot+Vue的CSGO赛事管理系统
    源码获取:https://download.csdn.net/download/u011832806/89461573基于SpringBoot+Vue的CSGO赛事管理系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/109zhbBkTfpLZJx0Twg2afg?pw......
  • 【Java项目】基于SpringBoot+Vue的洪涝灾害应急信息管理系统的设计与实现(源码+LW+包运
    源码获取:https://download.csdn.net/download/u011832806/90001545基于SpringBoot+Vue的洪涝灾害应急信息管理系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven洪涝灾害应急信息管理系统是一个综合性的信息平台,旨在提供实时......
  • Cause: java.sql.SQLDataException: ORA-01841: (完整) 年份值必须介于 -4713 和 +999
    报错信息:###Theerrormayexistinfile[E:\IdeaProjects\FeiShuEHR\target\classes\mapper\ZzzHrOaQingJiaMapper.xml]###TheerrormayinvolvedefaultParameterMap###Theerroroccurredwhilesettingparameters###SQL:SELECTDANHAO,A0190,LEAVE_TYPEI......
  • docker安装fastdfs
    使用Docker安装FastDFS1.获取镜像可以利用已有的FastDFSDocker镜像来运行FastDFS。获取镜像可以通过下载dockerimagepulldelron/fastdfs加载好镜像后,就可以开启运行FastDFS的tracker和storage了。2.运行tracker执行如下命令开启tracker服务dockerrun-dti--netwo......
  • linux更新软件源 安装docker
    vim/etc/aptsources.list学习参考https://blog.csdn.net/bskfnvjtlyzmv867/article/details/81044217 #默认注释了源码镜像以提高aptupdate速度,如有需要可自行取消注释debhttps://mirrors.tuna.tsinghua.edu.cn/ubuntu/xenialmainrestricteduniversemultiverse#......
  • 【转型大模型必看】Java开发者能否转型大模型?程序员的逆袭秘籍,转行不再是梦
    随着技术的不断进步,人工智能(AI)大模型已经成为当今科技领域最热门的话题之一。许多开发者开始考虑从传统的软件开发领域,如Java,转向人工智能领域,今天小编和大家一起来探讨Java开发者是否可以转型到人工智能大模型,转型的优势,薪资对比,以及转型所需的知识和学习路线等。01Java......
  • JavaScript 的核心特性和TypeScript 的高级概念
    JavaScript核心特性JavaScript是一种动态的、弱类型的编程语言,广泛应用于Web开发中。它是Web页面上的脚本语言,也是Node.js生态系统的重要语言。JavaScript的核心特性包括:1. 动态类型弱类型语言:变量的类型在运行时确定,可以存储任何类型的数据,类型转换在运行时进行。......
  • 已拿offer|西安华为 Java 面经
    西安华为Java面经​ 写在前面,推荐这个ai面试产品,多面鹅ai,真的很好用。在面试前已经模拟面试准备过很多次,多亏了多面鹅帮我模拟面试还复盘,给了我很大的帮助!还有线上面试同步ai辅助提醒的功能,但是我没用,有用过的小伙伴可以分享一下经验!OfferGoose多面鹅官网- AI面试模......
  • Java接入阿里云日志服务
    要将系统的日志输出到阿里云的日志服务(SLS),需要进行以下几个步骤:创建阿里云日志服务项目和日志库:登录阿里云控制台。进入日志服务(SLS)控制台。创建一个新的项目(Project)。在项目中创建一个新的日志库(Logstore)。配置日志采集:在日志服务控制台中,选择你创建的日志库。进入“......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
    摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,网上书城管理系统当然也不能排除在外。网上书城管理系统是以实际运用为开发背景,运用软件工程原理和开发方法,采用SSM框架构建的一个管理系统。整个开发过程首......