入门:手动构建镜像

news2024/11/16 18:08:36

前面我们已经了解了Docker镜像的结构,实际上所有常用的应用程序都有对应的镜像,我们只需要下载这些镜像然后就可以使用了,而不需要自己去手动安装,顶多需要进行一些特别的配置。当然要是遇到某些冷门的应用,可能没有提供镜像,这时就要我们手动去安装,接着我们就来看看如何构建我们自己的Docker镜像。构建镜像有两种方式,一种是使用commit命令来完成,还有一种是使用Dockerfile来完成,我们先来看第一种。

这里我们就做一个简单的例子,比如我们现在想要在Ubuntu的base镜像中安装Java环境,并将其打包为新的镜像(这个新的镜像就是一个包含Java环境的Ubuntu系统镜像)

咱们先启动Ubuntu镜像,然后使用yum命令(跟apt比较类似)来安装Java环境,首先是run命令:

docker pull ubuntu

接着启动:

直接使用apt命令来安装Java环境,在这之前先更新一下,因为是最小安装所以本地没有任何软件包:

 

接着输入:

apt install openjdk-8-jdk

等待安装完成:

 

这样,我们就完成了对Java环境的安装了,接着我们就可以退出这个镜像然后将其构建为新的镜像:

使用commit命令可以将容器保存为新的镜像:

docker commit 容器名称/ID 新的镜像名称

 

可以看到安装了软件之后的镜像大小比我们原有的大小大得多,这样我们就可以通过这个镜像来直接启动一个带Java环境的Ubuntu操作系统容器了。不过这种方式虽然自定义度很高,但是Docker官方并不推荐,这样的话使用者并不知道镜像是如何构建出来的,是否里面带了后门都不知道,并且这样去构建效率太低了,如果要同时构建多种操作系统的镜像岂不是要一个一个去敲?我们作为普通用户实际上采用Dokcerfile的方式会更好一些。

我们来看看如何使用Dockerfile的形式创建一个带Java环境的Ubuntu系统镜像。首先直接新建一个名为Dockerfile的文件:

touch Dockerfile

接着我们来进行编辑,Dockerfile内部需要我们编写多种指令来告诉Docker我们的镜像的相关信息:

FROM <基础镜像>

首先我们需要使用FROM指令来选择当前镜像的基础镜像(必须以这个指令开始),这里我们直接使用ubuntu作为基础镜像即可,当然如果不需要任何基础镜像的话,直接使用scratch表示从零开始构建,这里就不演示了。

基础镜像设定完成之后,我们就需要在容器中运行命令来安装Java环境了,这里需要使用RUN指令:

RUN apt update
RUN apt install -y openjdk-8-jdk

每条指令执行之后,都会生成一个新的镜像层。

OK,现在我们的Dockerfile就编写完成了,只需要完成一次构建即可:

docker build -t <镜像名称> <构建目录>

执行后,Docker会在构建目录中寻找Dockerfile文件,然后开始依次执行Dockerfile中的指令:

 

构建过程的每一步都非常清晰地列出来了,一共三条指令对应三步依次进行,我们稍微等待一段时间进行安装,安装过程中所以的日志信息会直接打印到控制台(注意Docker镜像构建有缓存机制,就算你现在中途退出了,然后重新进行构建,也会直接将之前已经构建好的每一层镜像,直接拿来用,除非修改了Dockerfile文件重新构建,只要某一层发生变化其上层的构建缓存都会失效,当然包括pull时也会有类似的机制)

 

最后成功安装,会出现在本地:

可以看到安装出来的大小跟我们之前的是一样的,因为做的事情是一模一样的。我们可以使用history命令来查看构建历史:

 

可以看到最上面两层是我们通过使用apt命令生成的内容,就直接作为当前镜像中的两层镜像,每层镜像都有一个自己的ID,不同的镜像大小也不一样。而我们手动通过commit命令来生成的镜像没有这个记录:

 

如果遇到镜像ID为missing的一般是从Docker Hub中下载的镜像会有这个问题,但是问题不大。用我们自己构建的镜像来创建容器就可以直接体验带Java环境的容器了:

有关Dockerfile的其他命令,我们还会在后续的学习中逐步认识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/98249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【细胞分割】中值滤波+分水岭法细胞计数【含Matlab源码 640期】

⛄一、图像分割简介 理论知识参考&#xff1a;【基础教程】基于matlab图像处理图像分割【含Matlab源码 191期】 ⛄二、部分源代码 clear; close all; %------------------ %程序中定义图像变量说明 %Image->原图变量; %Image_BW->二值化图象; %Image_BW_medfilt->中…

【实时数仓】DWM层跳出明细计算之需求分析、读取数据、通过Flink的CEP完成跳出判断、写回kafka、测试

文章目录一 DWM层-跳出明细计算1 需求分析与思路&#xff08;1&#xff09;什么是跳出&#xff08;2&#xff09;计算跳出行为的思路&#xff08;3&#xff09;实现思路2 读取数据&#xff08;1&#xff09;代码编写&#xff08;2&#xff09;测试3 通过Flink的CEP完成跳出判断…

【MATLAB100个实用小技巧】——数值分析(85-100)

文章目录前言系列文章85.86. 三次样条插值法87. NEWTON 插值88. hermite 插值89. newton 形式的 hermite 插值90. 平方根法91. gauss 消去法92. 三角分解法93. jacobi 迭代法94. gauss 迭代法95. sor 迭代法96. 最速下降法97. 共额梯度法98. newton 迭代法99. broyden 迭代法10…

前端媒体查询@media示例详解和calc()函数的使用

媒体查询media media 可以针对不同的屏幕尺寸设置不同的样式&#xff0c;特别是如果需要设置设计响应式的页面&#xff0c;media 是非常有用的。当重置浏览器大小的过程中&#xff0c;页面也会根据浏览器的宽度和高度重新渲染页面。 eg&#xff1a;如果文档宽度小于 500 像素…

pytorch 自编码器实现图像的降噪

自编码器 自动编码器是一种无监督的深度学习算法&#xff0c;它学习输入数据的编码表示&#xff0c;然后重新构造与输出相同的输入。它由编码器和解码器两个网络组成。编码器将高维输入压缩成低维潜在(也称为潜在代码或编码空间) &#xff0c;以从中提取最相关的信息&#xff…

SpringCloud之Hystrix

复杂分布式体系结构中的应用程序有数十个依赖关系&#xff0c;每个依赖关系在某些时候将不可避免失败&#xff01; 服务雪崩 多个微服务之间调用的时候&#xff0c;假设微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其他的微服务&#xff0c;这就是所谓的“…

HttpRunner3.x 安装与使用

HttpRunner3.x 安装与使用HttpRunner3.x 安装与使用安装使用运行脚手架项目方式一&#xff1a;录制生成用例步骤1&#xff1a;导出har文件步骤2&#xff1a;转化成测试用例文件har2casehmake步骤3&#xff1a;执行测试用例方式二&#xff1a;手工编写测试用例HttpRunner3.x 安装…

Jenkins自动部署springboot的Docker镜像,解决Status [1]问题

Jenkins凡是要指定路径的命令&#xff0c;一定要写绝对路径&#xff0c;不能写相对路径&#xff01;不要以为配置了Remote directory&#xff0c;那么命令就会在Remote directory下执行&#xff01;这种想法是错误的&#xff01;&#xff01;&#xff01; 《jenkins自动化发布到…

机器学习实战教程(五):朴素贝叶斯实战篇

一、前言 上篇文章机器学习实战教程&#xff08;四&#xff09;&#xff1a;朴素贝叶斯基础篇_M_Q_T的博客-CSDN博客讲解了朴素贝叶斯的基础知识。本篇文章将在此基础上进行扩展&#xff0c;你将看到以下内容&#xff1a; 拉普拉斯平滑垃圾邮件过滤(Python3)新浪新闻分类(skle…

毕业设计 - 基于Java的敬老院管理系统设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计系统的主要功能性需求2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java web项目: 基于Java的敬老院管理系统设计与实现 一、项目设计 1. 模块设计 站在护工角度来看&#xff0c;他们迫切希望&#xff0c;在运用该系统…

【Flink】Flink Starting Offset 启动消费位置 指定时间消费

文章目录 1.概述2.测试3.源码1.概述 首先参考文章:【Flink】Flink 1.14.0 全新的 Kafka Connector Kafka Source 能够通过指定 OffsetsInitializer来消费从不同偏移量开始的消息。内置的初始值设定项包括: KafkaSource.builder()// Start from committed offset of the co…

【YOLOv7-环境搭建③】PyCharm安装和环境、解释器配置

下载链接&#xff1a; 来源&#xff1a;&#xff08;博主&#xff09;唐三. 链接:https://pan.baidu.com/s/1y6s_EScOqvraFcx7iPSy1g 提取码:m1oa 安装&#xff1a; 以管理员身份打开安装完成后&#xff0c;打开软件到达以下界面&#xff0c;框框全选到达以下界面&#xf…

【指纹识别】指纹识别匹配门禁系统【含GUI Matlab源码 587期】

⛄一、指纹识别简介 1 指纹识别的引入和原理 1.1 指纹的基本知识 指纹&#xff0c;由于其具有终身不变性、唯一性和方便性&#xff0c;已几乎成为生物特征识别的代名词。指纹是指人的手指末端正面皮肤上凸凹不平产生的纹线。纹线有规律的排列形成不同的纹型。纹线的起点、终点…

kotlin基础学习笔记第九章——泛型

实化类型参数允许你在运行时的内联函数中引用作为类型实参的具体类型&#xff08;对普通的类和函数来说&#xff0c;这样行不通&#xff0c;因为类型实参在运行时会被擦除&#xff09;。 声明点变型可以说明一个带类型参数的泛型类型&#xff0c;是否是另一个泛型类型的子类型或…

什么是MySQL插入意向锁?

Insert Intention Lock&#xff0c;中文我们也称之为插入意向锁。 这个可以算是对我们之前所讲的 Gap Lock 的一个补充&#xff0c;关于 Gap Lock&#xff0c;如果还有小伙伴不懂&#xff0c;可以参考&#xff1a;记录锁、间隙锁与 Next-Key Locks。 1. 为什么需要插入意向锁…

吃透Chisel语言.40.Chisel实战之单周期RISC-V处理器实现(下)——具体实现和最终测试

Chisel实战之单周期RISC-V处理器实现&#xff08;下&#xff09;——具体实现和最终测试 上一篇文章中我们对本项目的需求进行了分析&#xff0c;并得到了初步的设计&#xff0c;这一篇文章我们就可以基于该设计来实现我们的单周期RISC-V处理器了。实现之后也必须用实际代码来…

[ 数据结构 -- 手撕排序算法第三篇 ] 希尔排序

文章目录前言一、常见的排序算法二、希尔排序2.1 希尔排序(缩小增量排序)2.1.1 预排序阶段2.1.2 插入排序阶段2.2 单趟希尔排序2.2.1 思路分析三、希尔排序实现代码四、希尔排序的时间复杂度五、希尔排序和直接插入排序效率测试5.1 测试5.2 结论5.2.1 随机数比较5.2.2 有序数组…

【二维码识别】灰度+二值化+校正二维码生成与识别【含GUI Matlab源码 635期】

⛄一、二维码生成与识别简介 如今,移动互联网技术日新月异,随着5G时代的来临,广泛应用于数据处理过程中的二维码信息安全日益成为人们越来越关注的问题。以QR码为代表的二维码,以其在信息存储、传输和识别技术领域优异的表现,成为信息共享、移动支付等领域的宠儿。不可避免地,…

利用深度学习生成数据的时间序列预测(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 数据分析研究目前仍是行业热点,相关学者从数据分析关键技术中的异常检测、入侵检测、时间序列预测等角度展开研究。然而,现有研…

Go环境搭建与IDE开发工具配置

安装Go语言编译器 Go语言编译器》编译器将源代码编译为可执行程序》源代码程序员使用高级语言所书写的代码文件》高级语言c/c/go…》机器语言0和1构成&#xff0c;机器能直接识别》汇编语言比机器语言稍微可读一点点的指令集 编译器下载地址 根据系统下载对应的go编译器版本…