在CSDN学Golang云原生(Docker镜像)
一,镜像分层机制
在 Docker 中,一个镜像可以由多个分层(Layer)组成。每个分层都表示一些修改或添加到上一个分层的文件系统差异。
Golang 在构建 Docker 镜像时也支持类似的机制,通过 docker build
命令来创建一个包含多个分层的镜像。
具体实现方式是在 Dockerfile 中使用 RUN
、ADD
、COPY
等指令来安装软件包、下载文件等操作,并且使用 -o
选项设置编译输出目录:
FROM golang:1.16WORKDIR /go/src/appCOPY . .RUN go get -d -v ./...
RUN go install -v ./...CMD ["app"]
上面的例子中,我们从 Golang 官方镜像开始构建一个新镜像,并设置工作目录为 /go/src/app
。然后复制当前目录下所有文件到容器中,并执行 go get
和 go install
命令安装和编译 Go 代码。最后设置容器启动命令为 app
。
在执行这个 Dockerfile 的过程中,Docker 会将每个指令生成的结果保存为一个新的分层,并将它们合并成最终的镜像。这种机制有助于减小镜像大小,避免重复数据存储。
如果你想查看某个 Docker 镜像的所有分层信息,可以使用 docker history
命令:
$ docker history my-image
IMAGE CREATED CREATED BY SIZE COMMENT
d34e5b1a58b3 5 days ago /bin/sh -c #(nop) CMD ["app"] 0B
<missing> 5 days ago /bin/sh -c go install -v ./... 4.57MB
<missing> 5 days ago /bin/sh -c go get -d -v ./... 43.9MB
<missing> 5 days ago /bin/sh -c #(nop) COPY dir:86fd420f94bef8f09... 2.61kB
<missing> 6 weeks ago /bin/sh -c #(nop) WORKDIR /go/src/app 0B
<missing> 6 weeks ago /bin/sh -c #(nop) COPY file:d75a3e0d6401fcdb7... 116B
<missing> 6 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 6 weeks ago /bin/sh -c #(nop) ADD file:e0da07f59373bac823... 811MB
上面的结果显示了该镜像中每个分层所包含的文件、大小以及生成方式。
需要注意的是,由于 Docker 镜像的设计原理,某些操作(例如 apt-get update
)可能会导致多次创建分层,从而增加镜像大小。因此在编写 Dockerfile 的时候要尽量避免重复或无效的操作,以减小镜像大小。
二,容器写时复制机制
Golang 容器写时复制(Copy-on-write) 的实现细节,以下是一个简单的代码示例:
func CopyContainer(rootfs string) (string, error) {// 创建容器镜像的只读层runcmd := exec.Command("docker", "create", rootfs)output, err := runcmd.Output()if err != nil {return "", fmt.Errorf("failed to create container: %v", err)}containerID := strings.TrimSpace(string(output))// 挂载容器镜像到一个临时目录tmpdir, err := ioutil.TempDir("", "container")if err != nil {return "", fmt.Errorf("failed to create temporary directory: %v", err)}defer os.RemoveAll(tmpdir)mountcmd := exec.Command("mount", "-o", "bind", "/proc/self/mounts", filepath.Join(tmpdir, "mounts"))if err := mountcmd.Run(); err != nil {return "", fmt.Errorf("failed to mount /proc/self/mounts: %v", err)}// 以只读方式挂载容器层到临时目录rootfsPath := filepath.Join(tmpdir, "rootfs")if err := os.MkdirAll(rootfsPath, 0755); err != nil {return "", fmt.Errorf("failed to create rootfs path: %v", err)}mountcmd = exec.Command("mount", "-o", "ro,noatime,nodiratime,noexec,nodev,nosuid", "--bind", rootfs, rootfsPath)if err := mountcmd.Run(); err != nil {return "", fmt.Errorf("failed to bind mount rootfs: %v", err)}// 创建容器镜像的读写层layerPath := filepath.Join(tmpdir, "layer")if err := os.MkdirAll(layerPath, 0755); err != nil {return "", fmt.Errorf("failed to create layer path: %v", err)}// 挂载读写层到容器镜像只读层上mountcmd = exec.Command("mount", "-o", "rw,noatime,nodiratime,noexec,nodev,nosuid,lowerdir="+rootfsPath+",upperdir="+layerPath+",workdir="+filepath.Join(tmpdir, "work"), "none", filepath.Join(tmpdir, "overlay"))if err := mountcmd.Run(); err != nil {return "", fmt.Errorf("failed to create overlay mount: %v", err)}// 卸载临时目录下挂载的文件系统defer func() {exec.Command("umount", "-l", filepath.Join(tmpdir, "overlay")).Run()exec.Command("umount", "-l", rootfsPath).Run()exec.Command("umount", "-l", filepath.Join(tmpdir, "mounts")).Run()}()containerRoot := filepath.Join(layerPath, "root")return containerRoot, nil
}
此函数使用 Golang 的 os/exec
包来执行操作系统级别的命令(如挂载和卸载文件系统)。它首先创建一个只读的容器镜像,并将其挂载到一个临时目录。然后,它将容器镜像根文件系统以只读方式挂载到该临时目录中,然后再将读写层作为 OverlayFS 挂载到只读层上。最后,它返回容器的根路径。
需要注意的是,此示例仅适用于 Linux 系统,并且使用了一些操作系统特定的命令和选项。在不同的操作系统和环境中可能需要进行修改以实现类似的功能。
三,容器联合挂载机制
在Golang中,可以通过使用os/exec包和容器运行时接口(CRI)来实现容器的联合挂载机制。
具体步骤如下:
- 使用os/exec包创建一个新的进程,并设置其命令参数为需要执行的容器程序。
- 在命令参数中指定需要挂载的文件系统类型及其路径,例如:--mount type=bind,source=/host/path,target=/container/path
- 使用CRI将该进程作为容器启动起来。
- 容器内部可以访问到宿主机上已经挂载好的目录,即实现了联合挂载。
示例代码如下:
package mainimport ("os""os/exec"
)func main() {cmd := exec.Command("docker", "run", "--rm","-v", "/etc:/host/etc:ro","alpine", "cat", "/host/etc/hostname")cmd.Stdout = os.Stdoutcmd.Stderr = os.Stderrerr := cmd.Run()if err != nil {panic(err)}
}
以上代码会启动一个Alpine Linux容器,并且将宿主机上的/etc目录以只读方式挂载到容器内部。然后在容器内部执行cat /host/etc/hostname命令,输出宿主机上的主机名信息
四,镜像内容寻址机制
在golang中,镜像内容寻址机制指的是程序在运行时如何查找和访问已经编译好的包文件。golang使用了一种基于包名的寻址机制。
当我们在代码中引用一个外部包时,例如import "fmt"
,编译器会首先查找系统上的标准库路径,如果找到了就直接使用系统自带的fmt包;如果没有找到,则会继续在$GOPATH环境变量所指向的目录下查找,并将其编译成二进制文件进行链接。若还未找到,则会报错提示无法找到对应包。
Golang对于不同操作系统采用了不同的命名规范和后缀名。例如,在Windows平台下生成的可执行文件为.exe格式,在Linux或Unix平台下则是二进制可执行文件。
golang通过基于包名和路径来确定应该从哪个位置加载相应的包,这种方式使得依赖管理更加简单易懂,同时也方便了跨平台开发。
五,镜像构建
Golang 镜像构建通常可以分为以下几个步骤:
- 编写Dockerfile文件:Dockerfile是构建镜像的配置文件,其中包含了一系列命令和指令,用于指定如何将代码打包进镜像中。例如,可以通过
FROM
指令指定基础镜像(例如golang:latest
);通过WORKDIR
指令设置工作目录;通过COPY
或者ADD
指令将代码拷贝到镜像中等。 - 构建Docker镜像:在终端窗口中使用docker build命令来执行构建过程。例如:
docker build -t my-golang-app .
这条命令会在当前目录下寻找名为“Dockerfile”的文件,并以此为依据构建新的my-golang-app镜像。
- 运行容器:在终端窗口中使用docker run命令运行容器。例如:
docker run -p 8080:8080 my-golang-app
这样就成功运行了一个 Golang 应用程序的 Docker 容器,并且可以通过浏览器访问 http://localhost:8080 来查看应用程序的输出。
需要注意的是,在编写 Dockerfile 文件时,应该尽量遵循最佳实践,避免一些常见问题,如不必要的安装软件包、不规范的文件权限等。
六,镜像共享
Golang 镜像共享一般有两种方式:
- 通过 Docker Hub 共享:Docker Hub 是官方的 Docker 镜像仓库,开发者可以在其中创建自己的镜像并分享给其他人。要实现这种方式,需要在 Docker Hub 上注册账号,并将自己的 Golang 镜像 push 到 Docker Hub 上去,然后其他用户就可以 pull 下来使用。
- 通过私有镜像仓库共享:如果不想将自己的 Golang 镜像公开分享到 Docker Hub 上,也可以搭建自己的私有镜像仓库(如 Harbor、Nexus等),将其作为公司或团队内部的镜像管理中心,以便于内部协同开发和部署应用程序。在私有镜像仓库中上传和下载 Golang 镜像与在 Docker Hub 中类似。
无论是哪种方式,都需要遵循最佳实践制作好 Golang 镜像,并确保该镜像具有较高的可重复性和稳定性,在生产环境中能够正常运行。
七,私有注册中心构建
在 Golang 中,可以使用 Docker 镜像仓库或者自己搭建私有注册中心来进行镜像的管理和共享。下面介绍一种基于 Harbor 的私有注册中心构建方式。
- 下载安装并启动 Harbor
在官网下载 Harbor 并解压缩到任意目录,然后运行./install.sh
脚本安装。安装完毕后执行docker-compose up -d
启动 Harbor。默认情况下 Harbor 运行在 80 和 443 端口上,并使用自签名证书加密通信。 - 创建项目并添加用户
登录到 Harbor 控制台,在左侧导航栏选择“项目”,点击“新建项目”按钮创建一个新的项目。然后在该项目中创建用户并分配权限,以便于其他人上传、下载和管理镜像。 - 构建 Golang 镜像并 push 到 Harbor
编写一个简单的 Golang 应用程序,并编译成可执行文件(例如 hello-world),然后写好 Dockerfile 文件并将其与可执行文件放在同一目录下。接着在该目录下执行以下命令:
# 使用 Dockerfile 构建镜像
docker build -t harbor.example.com/myproject/hello-world:v1 .# 将镜像推送到 Harbor 私有注册中心
docker push harbor.example.com/myproject/hello-world:v1
其中 harbor.example.com
是你的私有注册中心地址,myproject
是你创建的项目名称,hello-world:v1
是镜像的名称和版本号。
- 下载并使用 Golang 镜像
在其他机器上登录到 Harbor 控制台或者运行以下命令下载镜像:
docker login harbor.example.com
docker pull harbor.example.com/myproject/hello-world:v1
然后就可以使用该镜像了。
注意:为了保证安全性和可靠性,在实际生产环境中,需要对私有注册中心进行更多的配置和管理,例如设置访问控制、加密通信、备份恢复等。
相关文章:
在CSDN学Golang云原生(Docker镜像)
一,镜像分层机制 在 Docker 中,一个镜像可以由多个分层(Layer)组成。每个分层都表示一些修改或添加到上一个分层的文件系统差异。 Golang 在构建 Docker 镜像时也支持类似的机制,通过 docker build 命令来创建一个包…...
Hive窗口函数大全
Hive窗口函数 一、偏移量函数laglead 二、窗口分析函数first_valuelast_value 三、排序函数rankdense_rankrow_number 一、偏移量函数 lag 语法:lag(col,n,default_val) 返回值:字段类型 说明:往前第n行数据。 lag(column字段,第…...

达闼面试(部分)(未完全解析)
grpc怎么解决负载均衡问题? Answer by newBing : gRPC提供了多种负载均衡策略,包括轮询、随机、最少连接数等。gRPC客户端可以使用这些策略来选择要连接的服务器。 k8s环境下部署grpc的几种方案 : 在k8s环境中,可以选择headless service,或者…...

Makefile常用函数
目录 字符串替换函数:subst 模式字符串替换函数:patsubst 去空格函数 strip 查找字符串函数 findstring 过滤函数 filter 反过滤函数 filter-out 排序函数 sort 取目录函数 dir 取文件函数 notdir 取后缀函数 suffix 取前缀函数 basename 加…...

mysql的一些知识整理
这里整理一些mysql相关的知识点,是自己不太熟悉的内容 varchar(n) 中 n 最大取值为多少 MySQL 规定除了 TEXT、BLOBs 这种大对象类型之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过 65535 个字节。 …...

修改密码和再次确认密码的js和element-ui的使用
<template><div><!-- plan的插槽 --><plan title"修改密码"><!-- 插槽的名字 --><span slot"header">修改密码</span><el-form:model"ruleForm2"status-icon:rules"rules2"ref"rul…...

蓝桥杯专题-真题版含答案-【垒骰子_动态规划】【抽签】【平方怪圈】【凑算式】
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…...
kubernetes调试利器——kubectl debug工具
通常情况下,业务容器所使用的镜像是非常精简的,而一旦业务容器出现问题,通过kubectl exec进入到容器时,我们会发现自己需要使用的工具都没有,也无法通过apt, apt-get, yum等包管理工具下载需要的工具。 想要解决这个尴…...

浅谈es5如何保证并发请求的返回顺序
最近在公司实习写的是es5,在和回调地狱经过一番拉扯之后写下这篇文章,也算是体验了一把没有promise的时代 假设我们的div有一个日历列表,但是由于大小关系只能每次显示2天的信息,项目限制只能使用es5,不能使用es6的pro…...
深入浅出Pytorch函数——torch.squeeze
分类目录:《深入浅出Pytorch函数》总目录 相关文章: 深入浅出Pytorch函数——torch.squeeze 深入浅出Pytorch函数——torch.unsqueeze 将输入张量形状为1的维度去除并返回。比如输入向量的形状为 A 1 B 1 C 1 D A\times1\times B\times1\times C…...
【LeetCode】121.买卖股票的最佳时机
题目 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大…...
【力扣】74. 搜索二维矩阵 <二分法>
【力扣】74. 搜索二维矩阵 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非递减顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则&am…...
Spring Task+Cron表达式
不需要导入坐标spring-context(包含在了spring-boot-starter) 在启动类添加EnableScheduleing开启任务调度 单独建个定时任务包task,创建定时任务类MyTask 在定时任务类添加Component 在类的方法上添加Scheduled(cron “cron表达…...

你们公司的【前端项目】是如何做测试的?字节10年测试经验的我这样做的...
前端项目也叫web端项目(通俗讲就是网页上的功能)是我们能够在屏幕上看到并产生交互的体验。 前端项目如何做测试? 要讲清楚这个问题,先需要你对测试流程现有一个全局的了解,先上一张测试流程图: 测试流程…...

华为战略方法论:BLM模型之关键任务与依赖关系
内容简介 在 BLM 模型中,执行部分包括四个模块,分别是: 关键任务与依赖关系;组织与绩效;人才;氛围与文化。 详细内容,大家可以参看下面这张图。 这四个模块其实是可以进一步划分成两个关键点…...
django的ORM模板的fake更新
django存量数据表的migraions记录丢失,若要更新表结构,则需用到fake,否则报错: 解决步骤如下: 1)同步存量表结构,生成伪表 --fake sudo python3 manage.py makemigrations appname sudo pyt…...

239.滑动窗口最大值
leetcode原题链接 题目描述: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例1: 输入:nums [1,…...
Redis基础原理
1 概念 1.1 关系型数据库与非关系型数据库对比 关系型数据库Mysql、Oralce特点数据之间有关联;数据存储在硬盘上效率操作关系型数据库非常耗时 非关系型数据库redis、hbase存储key:value特点数据之间没有关联关系;数据存储在内存中缓存思想从缓存中获…...
.NET 5 Web API 中JWT详细教程:保护你的Web应用
第一部分: 理解JWT JSON Web Token(JWT)是一种在不同系统之间传递信息的安全方式。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部包…...

MyBatis-Plus自动填充
文章目录 一、前言二、MyBatis-Plus自动填充功能实现2.1、实体类上增加注解2.2、自定义填充类编写 一、前言 我们在建表的时候,所有的表都会有create_id(创建人id)、create_time(创建时间)、update_id(更新…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...