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

这篇具有很好参考价值的文章主要介绍了在CSDN学Golang云原生(Docker镜像)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一,镜像分层机制

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

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

具体实现方式是在 Dockerfile 中使用 RUNADDCOPY 等指令来安装软件包、下载文件等操作,并且使用 -o 选项设置编译输出目录:

FROM golang:1.16

WORKDIR /go/src/app

COPY . .

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 main

import (
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("docker", "run", "--rm",
		"-v", "/etc:/host/etc:ro",
		"alpine", "cat", "/host/etc/hostname")

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err := 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

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

注意:为了保证安全性和可靠性,在实际生产环境中,需要对私有注册中心进行更多的配置和管理,例如设置访问控制、加密通信、备份恢复等。文章来源地址https://www.toymoban.com/news/detail-609723.html

到了这里,关于在CSDN学Golang云原生(Docker镜像)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在CSDN学Golang云原生(Kubernetes二开)

    Kubernetes提供了client-go库,该库可以让开发人员使用Golang编写的应用程序与Kubernetes API进行交互。通过client-go,你可以创建、更新和删除Kubernetes资源,并查询集群状态等信息。 以下是一个示例代码片段,演示如何使用client-go列出当前运行的Pod:

    2024年02月15日
    浏览(42)
  • 【云原生 | 37】Docker快速部署编程语言Golang

    🍁 博主简介 :         🏅云计算领域优质创作者         🏅新星计划第三季python赛道第一名         🏅阿里云ACE认证高级工程师         🏅阿里云开发者社区专家博主 ✒️ 博主微信 :15575411187 💊 交流社区 :小鹏linux(个人社区)欢迎您的加入! 目录

    2024年02月01日
    浏览(60)
  • 在CSDN学Golang云原生(Kubernetes Pod)

    在 Kubernetes 中,Pod 是最小的可部署单元,它包含一个或多个容器。使用 Golang 来定义和操作 Pod 时,需要使用 kubernetes/client-go 包提供的 API。 以下是 Golang 定义和基本用法 Pod 的示例: 安装 kubernetes/client-go 包 在 Golang 环境中安装 kubernetes/client-go 包,该包提供了访问 Kubernetes

    2024年02月15日
    浏览(39)
  • 在CSDN学Golang云原生(Kubernetes Volume)

    Kubernetes 中的 Volume 和 ConfigMap 都是 Kubernetes 中常用的资源对象。它们可以为容器提供持久化存储和配置文件等。 Volume 可以将容器内部的文件系统挂载到宿主机上,也可以将多个容器间共享一个 Volume,并且 Volume 与 Pod 的生命周期相同。 ConfigMap 则是一种用于保存应用程序配置

    2024年02月15日
    浏览(31)
  • 在CSDN学Golang云原生(Kubernetes Service)

    在 Kubernetes 中,Service 是一种抽象概念,用于定义一组 Pod 并为它们提供访问入口。通过 Service,您可以将多个 Pod 组合成一个逻辑单元,并使用标签选择器来确定哪些 Pod 属于该 Service。 下面是一个简单的 Service 定义示例: 在上面的示例中,我们创建了一个名为  my-service  的

    2024年02月15日
    浏览(40)
  • 在CSDN学Golang云原生(持续交付Argo)

    Argo是一个基于Kubernetes的容器本地工作流引擎,可以帮助用户在Kubernetes上创建、运行和维护容器化应用程序。下面是Argo安装配置的步骤: 首先确保你已经安装了kubectl和helm 添加chart仓库 创建namespace 安装 Argo CD 其中, server.extraArgs={--insecure}  表示允许不受信任的证书。 rbac.

    2024年02月15日
    浏览(34)
  • 在CSDN学Golang云原生(服务网格istio)

    在Kubernetes上部署istio,可以按照以下步骤进行: 安装Istio 使用以下命令从Istio官网下载最新版本的Istio: 其中, VERSION 是要安装的Istio版本号。 将下载的文件解压到本地目录: 进入解压后的目录: 然后,安装Istio CRDs(Custom Resource Definitions): 最后,安装Istio组件和示例应用

    2024年02月15日
    浏览(40)
  • 在CSDN学Golang云原生(Kubernetes集群管理)

    在 Kubernetes 集群中,Node 的隔离与恢复通常可以通过以下方式实现: 使用 Taints 和 Tolerations 实现隔离 Taints 和 Tolerations 是 Kubernetes 中用于节点调度的机制。通过给节点添加 taints(污点),可以让节点拒绝某些特定的 Pod 调度。而对于需要运行在这些节点上的 Pod,我们需要在

    2024年02月15日
    浏览(40)
  • 在CSDN学Golang云原生(Kubernetes集群安全)

    Kubernetes ABAC(Attribute-Based Access Control)授权模式是一种基于属性的访问控制模型,它可以根据用户或组的属性决定是否允许他们访问 Kubernetes 集群中的资源。 在使用 ABAC 授权模式时,管理员需要定义一些规则来限制哪些用户或组有权访问集群中的不同资源。这些规则通常包括

    2024年02月14日
    浏览(34)
  • 在CSDN学Golang云原生(Kubernetes Pod调度)

    在 Kubernetes 中,可以使用 NodeSelector 字段来指定 Pod 调度到哪些节点上运行。NodeSelector 是一个键值对的 map,其中键是节点的标签名,值是标签值。具体步骤如下: 在节点上添加标签 首先需要在节点上添加相应的标签,例如: 编写 Pod 的 YAML 文件 在编写 Pod 的 YAML 文件时,需

    2024年02月15日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包