在CSDN学Golang云原生(Docker镜像)

一,镜像分层机制

在 Docker 中,一个镜像可以由多个分层(Layer)组成。每个分层都表示一些修改或添加到上一个分层的文件系统差异。

Golang 在构建 Docker 镜像时也支持类似的机制,通过 docker build 命令来创建一个包含多个分层的镜像。

具体实现方式是在 Dockerfile 中使用 RUNADDCOPY 等指令来安装软件包、下载文件等操作,并且使用 -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)来实现容器的联合挂载机制。

具体步骤如下:

  1. 使用os/exec包创建一个新的进程,并设置其命令参数为需要执行的容器程序。
  2. 在命令参数中指定需要挂载的文件系统类型及其路径,例如:--mount type=bind,source=/host/path,target=/container/path
  3. 使用CRI将该进程作为容器启动起来。
  4. 容器内部可以访问到宿主机上已经挂载好的目录,即实现了联合挂载。

示例代码如下:

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 镜像构建通常可以分为以下几个步骤:

  1. 编写Dockerfile文件:Dockerfile是构建镜像的配置文件,其中包含了一系列命令和指令,用于指定如何将代码打包进镜像中。例如,可以通过FROM指令指定基础镜像(例如golang:latest);通过WORKDIR指令设置工作目录;通过COPY或者 ADD 指令将代码拷贝到镜像中等。
  2. 构建Docker镜像:在终端窗口中使用docker build命令来执行构建过程。例如:
docker build -t my-golang-app .

这条命令会在当前目录下寻找名为“Dockerfile”的文件,并以此为依据构建新的my-golang-app镜像。

  1. 运行容器:在终端窗口中使用docker run命令运行容器。例如:
docker run -p 8080:8080 my-golang-app

这样就成功运行了一个 Golang 应用程序的 Docker 容器,并且可以通过浏览器访问 http://localhost:8080 来查看应用程序的输出。

需要注意的是,在编写 Dockerfile 文件时,应该尽量遵循最佳实践,避免一些常见问题,如不必要的安装软件包、不规范的文件权限等。

六,镜像共享

Golang 镜像共享一般有两种方式:

  1. 通过 Docker Hub 共享:Docker Hub 是官方的 Docker 镜像仓库,开发者可以在其中创建自己的镜像并分享给其他人。要实现这种方式,需要在 Docker Hub 上注册账号,并将自己的 Golang 镜像 push 到 Docker Hub 上去,然后其他用户就可以 pull 下来使用。
  2. 通过私有镜像仓库共享:如果不想将自己的 Golang 镜像公开分享到 Docker Hub 上,也可以搭建自己的私有镜像仓库(如 Harbor、Nexus等),将其作为公司或团队内部的镜像管理中心,以便于内部协同开发和部署应用程序。在私有镜像仓库中上传和下载 Golang 镜像与在 Docker Hub 中类似。

无论是哪种方式,都需要遵循最佳实践制作好 Golang 镜像,并确保该镜像具有较高的可重复性和稳定性,在生产环境中能够正常运行。

七,私有注册中心构建

在 Golang 中,可以使用 Docker 镜像仓库或者自己搭建私有注册中心来进行镜像的管理和共享。下面介绍一种基于 Harbor 的私有注册中心构建方式。

  1. 下载安装并启动 Harbor
    在官网下载 Harbor 并解压缩到任意目录,然后运行 ./install.sh 脚本安装。安装完毕后执行 docker-compose up -d 启动 Harbor。默认情况下 Harbor 运行在 80 和 443 端口上,并使用自签名证书加密通信。
  2. 创建项目并添加用户
    登录到 Harbor 控制台,在左侧导航栏选择“项目”,点击“新建项目”按钮创建一个新的项目。然后在该项目中创建用户并分配权限,以便于其他人上传、下载和管理镜像。
  3. 构建 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 是镜像的名称和版本号。

  1. 下载并使用 Golang 镜像
    在其他机器上登录到 Harbor 控制台或者运行以下命令下载镜像:
docker login harbor.example.com
docker pull harbor.example.com/myproject/hello-world:v1

然后就可以使用该镜像了。

注意:为了保证安全性和可靠性,在实际生产环境中,需要对私有注册中心进行更多的配置和管理,例如设置访问控制、加密通信、备份恢复等。

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

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

相关文章

Python - OpenCV实现摄像头人脸识别(亲测版)

要使用Python 3和OpenCV进行摄像头人脸识别&#xff0c;您可以按照以下步骤进行操作&#xff1a; 1.安装OpenCV库 在命令行中输入以下命令&#xff1a; pip install opencv-python2.准备人脸检测器 使用OpenCV的人脸检测器可以检测出图像中的人脸。在Python中&#xff0c;您…

【Terraform学习】TerraformCloud入门介绍(快速入门)

TerraformCloud入门介绍 什么是 TerraformCloud&#xff1f; Terraform Cloud是Hashicorp Terraform的SaaS版本。 免费版功能 免费版功能包括版本控制集成、远程计划和实施远程计划和实施、通知及webhook、全http API驱动、状态管理、模拟计划、私有化模块注册器以及全HTTP界…

LabVIEW开发谐振器陀螺仪仿真系统

LabVIEW开发谐振器陀螺仪仿真系统 陀螺仪是INS系统中最重要的传感器。它们的性能&#xff08;如精度和偏置稳定性&#xff09;决定了INS系统的水平。陀螺仪按原理分为三类&#xff1a;角动量守恒、萨格纳克效应和科里奥利效应。旋转坐标系中的移动物体受到的力与旋转坐标系的角…

7-22练习

题目1 链接5071 不难发现通过A的范围可以缩小B的范围进而减少循环次数 通过B可以消除A的循环 这个是一个很巧妙的地方。这个题还有一个比较容易引起歧义的地方就是i:n每一次循环都要符合条件 这样我们不难构造出一个函数 f(B+x) = 1000*A+x 试验1 运行超时-- 需要减少复杂度…

从SEU到ZJU——研究生新手村冒险随记

博主终于想起账号密码了&#xff08;bushi 上一次发文还是去年的六月份&#xff0c;一篇PAT甲级的AK留恋&#xff08;之后就发现自己的算法非正解&#xff09; 那时正在准备保研复试&#xff0c;总想着等一切结束了就更新blog&#xff0c;但是一拖再拖就是一年 现在的我&#…

Hive视图

hive的视图 简介 hive的视图简单理解为逻辑上的表hive只支持逻辑视图&#xff0c;不支持物化视图视图存在的意义 对数据进行局部暴露&#xff08;涉及隐私的数据不暴露&#xff09;简化复杂查询 创建视图&#xff1a; create view if not exists v_1 as select uid,movie f…

windows 安装 mongodb 数据库

软件下载 访问官方的下载地址&#xff1a; https://www.mongodb.com/try/download/community &#xff0c;然后选择对应的版本进行下载 下载好了之后双击进行安装 软件安装 1、点击 next 点击下一步 2、勾选接受协议&#xff0c;点击 next 3、第三页有两个选项&#x…

QEMU源码全解析14 —— QOM介绍(3)

接前一篇文章&#xff1a;QEMU源码全解析13 —— QOM介绍&#xff08;2&#xff09; 本文内容参考&#xff1a; 《趣谈Linux操作系统》 —— 刘超&#xff0c;极客时间 《QEMU/KVM》源码解析与应用 —— 李强&#xff0c;机械工业出版社 特此致谢&#xff01; 上回书讲到了Q…

大学生活题解

样例输入&#xff1a; 3 .xA ... Bx.样例输出&#xff1a; 6思路分析&#xff1a; 这道题只需要在正常的广搜模板上多维护一个— —方向&#xff0c;如果当前改变方向&#xff0c;就坐标不变&#xff0c;方向变&#xff0c;步数加一&#xff1b;否则坐标变&#xff0c;方向不…

视频讲解Codeforces Round 887 (Div. 2)(A--C)

文章目录 A. Desorting1、板书2、代码 B. Fibonaccharsis1、板书2、代码 C. Ntarsis Set1、板书2、代码 视频讲解Codeforces Round 887 (Div. 2)&#xff08;A–C&#xff09; A. Desorting 1、板书 2、代码 #include<bits/stdc.h> #define endl \n #define INF 0x3f…

Amazon Linux上使用ec2-user来设置开机自启动的shell脚本

要在Amazon Linux上使用ec2-user来设置开机自启动的shell脚本&#xff0c;可以按照以下步骤操作&#xff1a; 1. 确保您拥有要设置自启动的shell脚本。假设脚本的路径是/home/ec2-user/myscript.sh。 2. 使用以下命令打开/etc/rc.d/rc.local文件&#xff1a; shell sudo nano /…

2023年的深度学习入门指南(20) - LLaMA 2模型解析

2023年的深度学习入门指南(20) - LLaMA 2模型解析 上一节我们把LLaMA 2的生成过程以及封装的过程的代码简单介绍了下。还差LLaMA 2的模型部分没有介绍。这一节我们就来介绍下LLaMA 2的模型部分。 这一部分需要一些深度神经网络的基础知识&#xff0c;不懂的话不用着急&#xf…

notepad++ 正则表达式查找特定字符串

批量文本的处理方法 在报文中有很多指标和值都具有固定的格式&#xff0c;比如是 a"1" 这类格式&#xff0c;那么我们只取前面的指标a&#xff0c;就会比较复杂&#xff0c;而使用正则表达式就会快乐许多&#xff01; 采用以下第二种方法 查找目标 (.?)\" …

Python电商爬虫保姆级入门教程(纯新手向)

图灵Python课堂 长沙图灵教育于2001年开始进入教育行业&#xff0c;立足泛IT类职业教育&#xff0c;以打造高新技术人才为宗旨&#xff0c;专注于提供多层次、个性化的职业技能培训课程&#xff0c;为各行业培养技术开发、应用和管理等岗位的中高端人才&#xff0c;致力于成为…

【无标题】自定义类型:位段,枚举,联合

自定义类型&#xff1a;位段&#xff0c;枚举&#xff0c;联合 1. 位段1.1 什么是位段1.2 位段的内存分配1.3 位段的跨平台问题 2. 枚举2.1 枚举类型的定义2.2 枚举类型的优点2.3 枚举的使用 3. 联合&#xff08;共用体&#xff09;3.1 联合类型的定义3.2联合的特点3.2.1 相关面…

LUMEN技术要点总结

LUMEN总结 主题是动态全局光照和Lumen Lumen更像是一个各种GI算法的集大成者。 1. 如何理解lumen及全局光照的实现机制 渲染方程 至今为止所有的实时光照都是按照Render Equation来进行渲染的&#xff0c;我们做得到只是在无限的逼近它。 我们把只进行一次反弹叫做SingleBou…

CentOS实现html转pdf

CentOS使用实现html转PDF&#xff0c;需安装以下软件&#xff1a; yum install wkhtmltopdf # 转换工具&#xff0c;将HTML文件或网页转换为PDFyum install xorg-x11-server-Xvfb # 虚拟的X服务器&#xff0c;在无图形界面环境下运行图形应用程yum install wqy-zenhei-fonts #…

centos制作openssh 9.3p2 rpm包

标题使用源码制作openssh 9.3p2 的rpm包 准备&#xff1a; 操作系统&#xff1a;CentOS Linux release 7.4.1708 (Core) #测试发现rpm包要在什么系统安装需要就需要在什么系统上制作 工具软件&#xff1a;rpm-build 源码文件&#xff1a;openssh-9.3p2.tar.gz x11-ssh-askpas…

[AT_cf_2015_relay_g]题解

洛谷链接&ATcoder链接 题目翻译&#xff1a; 您将从 n n n 种主菜和 m m m 种副菜中选择菜品来创建一道套餐。您只能选择一种主菜&#xff0c;但可以选择任意数量的副菜。此外&#xff0c;也可以选择不选任何副菜。无论是主菜还是副菜&#xff0c;每种菜品只能选择一道…

【UniApp开发小程序】悬浮按钮+出售闲置商品+商品分类选择【基于若依管理系统开发】

文章目录 界面效果界面实现悬浮按钮实现商品分类选择界面使元素均匀分布 闲置商品描述信息填写界面价格校验 界面效果 【悬浮按钮】 【闲置商品描述信息填写界面】 【商品分类选择界面】 【分类选择完成】 界面实现 悬浮按钮实现 悬浮按钮漂浮于页面之上&#xff0c;等页面…