自己动手写Docker系列 -- 5.8实现容器制定环境变量运行

Docker容器化部署悟空CRM:从环境配置到生产级实践 在实际企业级 CRM 系统选型与部署中,悟空 CRM(WukongCRM)因其开源、功能全面和 Java 技术栈而受到许多团队的关注。然而,从源码编译、依赖配置到服务启动,传统部署方式步骤繁琐,环境问题频发,极易消耗开发运维人员大量精力。Docker 容器化技术为这类复杂应用的标准化部署提供了理想方案,它通过将应用及其所有依赖打包成一个可移植的镜像,实现了“一次构建,处处运行”。本文将聚焦于如何利用 Docker 和 Docker Compose,从零开始完成悟空 AICRM 的完整生产级部署。整个过程不仅 阅读详情

简介

在上篇中我们实现了将不同的容器独立进行隔离,并进行独立打包,本篇中将实现启动容器时指定环境变量,让容器内运行的程序可以使用外部传递的环境变量

源码说明

同时放到了Gitee和Github上,都可进行获取

本章节对应的版本标签是:5.8,防止后面代码过多,不好查看,可切换到标签版本进行查看

代码实现

实现该功能的主要思路如下:

直接使用系统函数即可:os.Environ(),在容器启动的时候进行传入,后面就可以在系统中进行获取

但exec命令存在问题,进入后不能得到环境变量

exec命令其实是mydocker发起的另外一个进程,这个进程的父进程其实是宿主机的,并不是容器内的。
因为在Cgo里面使用了setns系统调用,才使得这个进程进入到了容器内的命名空间,但是由于环境变量是继承自父进程的,因此这个exec进程的环境变量其实是继承自宿主机的,所以在exec进程内看到的环境变量其实是宿主机的环境变量。
但是,只要是容器内PID为1的进程,创建出来的进程都会继承它的环境变量

系统启动时环境变量传入

增加-e相关的命令

var RunCommand = cli.Command{
	Name:  "run",
	Usage: `Create a container with namespace and cgroups limit mydocker run -ti [command]`,
	Flags: []cli.Flag{
		......
		cli.StringSliceFlag{
			Name:  "e",
			Usage: "set environment",
		},
	},
	/*
		这里是run命令执行的真正函数
		1.判断参数是否包含command
		2.获取用户指定的command
		3.调用Run function 去准备启动容器
	*/
	Action: func(context *cli.Context) error {
		......
		// 获取并传入
		envSlice := context.StringSlice("e")
		run.Run(tty, detach, cmdArray, resConfig, volume, containerName, envSlice)
		return nil
	},
}

继续传入初始化函数

func Run(tty, detach bool, cmdArray []string, config *subsystem.ResourceConfig, volume, containerName string, envSlice []string) {
	......
	parent, writePipe := container.NewParentProcess(tty, containerName, rootUrl, mntUrl, volume, envSlice)
	if err := parent.Start(); err != nil {
		log.Error(err)
		// 如果fork进程出现异常,但有相关的文件已经进行了挂载,需要进行清理,避免后面运行报错时,需要手工清理
		deleteWorkSpace(rootUrl, mntUrl, volume, containerName)
		return
	}
	......
}

调用系统函数,直接注入进去

func NewParentProcess(tty bool, containerName, rootUrl, mntUrl, volume string, envSlice []string) (*exec.Cmd, *os.File) {
	......
	
	// 将管道的一端传入fork的进程中
	cmd.ExtraFiles = []*os.File{readPipe}
	if err := newWorkSpace(rootUrl, mntUrl, volume, containerName); err != nil {
		log.Errorf("new work space err: %v", err)
		return nil, nil
	}
	cmd.Dir = mntUrl
	// 直接添加环境变量到系统中
	cmd.Env = append(os.Environ(), envSlice...)
	return cmd, writePipe
}

exec改造

exec改造适配,在run的时候重新注入下环境变量

func ExecContainer(containerName string, commandArray []string) error {
	......

	// 获取环境变量,重新注入
	envs, err := getEnvsByPid(pid)
	if err != nil {
		return err
	}
	cmd.Env = append(os.Environ(), envs...)

	if err := cmd.Run(); err != nil {
		return fmt.Errorf("exec container %s err: %v", containerName, err)
	}
	return nil
}

环境变量的获取就是读取正在运行的容器进行,得到其对应的环境变量

func getEnvsByPid(pid string) ([]string, error) {
	path := fmt.Sprintf("/proc/%s/environ", pid)
	contentBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read file %s err: %v", path, err)
	}
	return strings.Split(string(contentBytes), "\u0000"), nil
}

测试运行

我们启动一个前台和一个后台的容器,分开查看下:

root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ↑1  go build mydocker/main.go                                                                               SIG(127) ↵  ⚡  513  06:35:19
root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ↑1  ./main run -ti -e bird=123 sh                                                                                    ✔  ⚡  514  06:35:21
{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"all command is : sh","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"parent process run","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"init come on","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"current location: /home/lw/code/go/dockerDemo/mnt","time":"2022-04-14T06:35:28+08:00"}
{"level":"info","msg":"find path: /bin/sh","time":"2022-04-14T06:35:28+08:00"}
/ # env |grep bird
bird=123
/ # exit

 root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ↑1  ./main run -d -e bird=123 -name bird top                                                                SIG(127) ↵  ⚡  515  06:35:58
{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-14T06:36:14+08:00"}
{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-04-14T06:36:14+08:00"}
{"level":"info","msg":"all command is : top","time":"2022-04-14T06:36:14+08:00"}
{"level":"info","msg":"parent process run","time":"2022-04-14T06:36:14+08:00"}
root@lw-Code-01-Series-PF5NU1G  ~/code/go/dockerDemo   main ● ↑1  ./main exec bird env |grep bird                                                                         SIG(127) ↵  ⚡  516  06:36:15
bird=123
Linux运维全栈实战:从零搭建Zabbix监控+Docker容器+MySQL+Nginx技能体系 很多想转行或刚入行的运维新人,都有过这样的困惑:面对Linux、Zabbix、Docker、MySQL、Nginx这些名词,感觉每个都要学,但不知道从哪里开始,更不知道学到什么程度才算“会了”。网上教程要么太零散,要么太理论,看完还是不知道如何把它们串联起来解决一个真实的企业问题。 这篇文章要解决的,正是这个核心痛点。它不是一个简单的命令合集,而是一张为你绘制的“技能地图”。我们将以 Linux操作系统为基石 ,串联起 Zabbix监控、Docker容器、MySQL数据库和Nginx服务 这四大企业级核心技 阅读详情

相关推荐

Llama-Swap安全部署指南:API密钥管理与容器安全实践

在AI应用开发中,API密钥管理与容器安全是保障服务稳定与数据机密性的核心环节。API密钥作为访问大模型服务的凭证,其泄露可能导致资源滥用或数据安全风险,因此需要遵循最小权限原则进行全生命周期管理。容器化部署通过环境隔离提升了应用的可移植性,但配置不当会引入攻击面,需从镜像构建、运行时限制到网络策略进行纵深防御。这些安全实践对于Llama-Swap这类模型服务中间件尤为重要,它能有效集成多模型API,其安全部署涉及密钥的安全存储注入、非root用户运行、资源限制及网络隔离等关键技术,确保服务在复杂环境下的机

weixin_34226706的博客 417

在docker上调用宿主机硬件_关于Docker的随手一记

写在前面的话 Docker是一种运行与Linux和Windows上的软件,用于创建、管理和编排容器。随着互联网的发展,往日的大型单体应用正被逐渐分解成小的、可以独立运行的组件,也就是我们一直在讲的微服务。微服务彼此之间解耦,可以独立的开发、部署、升级、伸缩。这使得我们可以依据业务需要对每一个模块的服务实现快速迭代。微服务在给我们带来很多的便捷,但在系统包含较多微服务...

weixin_39941620的博客 927

Docker部署Wukong AICRM:从环境配置到长期运维的完整实践指南

容器化技术通过将应用及其依赖打包成标准化的镜像,实现了环境隔离与一致性,从根本上解决了传统部署中常见的依赖冲突和环境差异问题。其核心原理在于利用操作系统级的虚拟化,为每个应用提供独立的运行空间。这一技术价值在于极大地简化了应用的开发、测试、部署和扩展流程,提升了软件交付的效率和可靠性。在工程实践中,Docker已成为AI应用、微服务架构和持续集成/持续部署(CI/CD)流水线的关键技术组件。特别是在部署像Wukong AICRM这类结合了AI能力的客户关系管理系统时,合理的Docker部署策略不仅涉及镜像拉

cong84596496的博客 292

Duix.Avatar完整指南:8G显存如何搭建专业级离线AI数字人

录一条口播视频要返工半小时?把数字人外包给商业平台,又被报价和人脸数据出海的隐私风险劝退?看到"开源数字人"四个字,第一反应却是:我家电脑跑得动吗? Duix.Avatar 是一个真开源、全离线的 AI 数字人项目:上传一段 10 秒左右的视频,克隆你的形象和声音,之后输入文案或上传音频即可驱动口型,自动生成口播播报视频。全程在自己的机器上完成,不联网、不按条计费。这篇指南按"硬件自查 → 一键

gitblog_01097的博客 337

Kali Linux中利用Docker部署ARL资产侦察平台实战指南

在网络安全领域,信息收集是渗透测试和攻防演练的关键前置环节,其核心原理是通过自动化技术对目标资产进行系统化发现与识别。容器化技术通过环境隔离和标准化部署,解决了传统部署中依赖冲突和版本管理的难题,为安全工具提供了可移植、可复现的运行环境。Docker作为主流的容器引擎,能够将复杂应用及其依赖打包成独立单元,实现一键部署与快速迁移,极大提升了安全研究与实践的效率。结合Kali Linux这一渗透测试标准平台,利用Docker部署ARL资产侦察灯塔,可以快速构建自动化资产发现流水线,广泛应用于攻防演练、漏洞挖掘

weixin_33701564的博客 382

DeepSeek-Harness Docker 部署指南:一键搭建 AI 模型 API 服务

Docker 容器化技术通过将应用及其依赖打包成标准镜像,实现了环境隔离与部署一致性,解决了传统部署中环境配置复杂、依赖冲突等痛点。其核心原理是利用操作系统级虚拟化,为应用提供独立的运行环境,确保在不同系统上行为一致。这一技术在 AI 模型部署领域价值显著,能大幅简化从开发到生产的流程。特别是在大语言模型(LLU)服务化场景中,Docker 化部署使得 GPU 资源管理、多实例扩展和持续集成变得高效可靠。本文聚焦于如何利用 Docker 容器快速部署 DeepSeek-Harness 工具链,将复杂的模型推

weixin_30781433的博客 403

Docker为容器设置环境变量(在docker run命令中设置容器的环境变量、在Dockerfile文件中设置容器的环境变量、在docker-compose.yaml中设置容器的环境变量)

Docker为容器设置环境变量(在docker run命令中设置容器的环境变量、在Dockerfile文件中设置容器的环境变量、在docker-compose.yaml中设置容器的环境变量)

聂可以的博客 1万+

Wukong AICRM Docker部署实战:从环境搭建到避坑指南

Docker作为容器化技术的代表,通过将应用及其依赖打包成标准化的容器单元,实现了开发、测试、生产环境的一致性,解决了传统部署中环境差异导致的运行问题。其核心原理基于操作系统级虚拟化,利用命名空间和控制组实现资源隔离,通过镜像分层机制提升部署效率。在工程实践中,Docker Compose进一步简化了多容器应用的编排管理,使得复杂应用的部署变得可重复和自动化。这种技术组合特别适用于需要快速搭建测试环境或进行持续集成的场景,例如部署像Wukong AICRM这样集成了AI能力的开源CRM系统。通过容器化部署,

weixin_34321753的博客 345

为容器设置环境变量

为容器设置环境变量 文章目录为容器设置环境变量在容器中指定环境变量使用configMap传递环境变量一次性传递configMap所有条目作为环境变量 在容器中指定环境变量 假如现在有demo.sh和Dockerfile demo.sh: #!/bin/bash while [[ true ]]; do echo time $INTERVAL sleep $INTERVAL done Dockerfile: FROM centos ADD demo.sh /root/demo.sh ENTRYPOIN

Just so-so 2892

从零构建:基于Docker与FRR的OSPF虚拟网络实验室

本文详细介绍了如何利用Docker与FRR构建OSPF虚拟网络实验室,从环境设计到高级网络拓扑配置,再到实验验证与排错。通过容器化技术实现高效资源利用和快速部署,特别适合网络协议教学、企业网络架构验证等场景。

plum99的博客 220

STM32串口调试踩坑记:HAL_UART_ErrorCallback里不先解锁,你的中断接收就废了

本文深入分析了STM32串口调试中HAL_UART_ErrorCallback的锁机制陷阱,指出在错误回调中不先解锁会导致中断接收失效的问题。通过解析HAL库源码,提出了正确的错误处理实现方法,并分享了预防措施与最佳实践,帮助开发者提升串口通信的可靠性。

weixin_33733810的博客 512

Docker 启动容器后修改容器中的环境变量env

原文链接:https://blog.csdn.net/shujujiegou_lixin/article/details/121521332。2.dokcer ps ,找到容器名,再docker inspect [容器名], 获取容器的长id:container-id。或者,vim /apps/docker/containers/[container-id]/config.json。1.docker info,查看Docker Root Dir: /apps/docker。

LJWWD的博客 5070

RISC-V— 架构基础知识学习

蜂鸟 E200 系列是一个开源的RISC-V 处理器。蜂鸟 E200 系列由中国大陆研发团队开发,用户能够轻松与开发人员取得交流和支持。RI蜂鸟 E200 处理器研发团队拥有在国际一流公司多年开发处理器的经验,使用稳健的Verilog 2001 语法编写的可综合 RTL 代码,以工业级标准进行开发。蜂鸟 E200 的代码为人工编写,添加丰富的注释且可读性强,非常易于理解。

deilt 1万+

自己动手写 Docker 系列文章总览

本文章系列起源于:《自己动手写 Docker》,编程实践方得真知,虽然大部分代码书中都有,但还是遇到了不少困难,下面是对于自己写的 Docker Demo 的总览

github_35735591的博客 2268

拆解一个800G光模块:手把手带你认识里面的MT插芯和光纤阵列(FA)

本文详细拆解了800G光模块中的关键组件MT插芯和光纤阵列(FA),揭示了并行光学技术如何实现高速数据传输。通过显微镜下的精密观察,展示了MT插芯的高精度构造和光纤阵列的连接奥秘,同时解析了高精度研磨工艺对光信号传输的重要性。这些微型组件是高速收发模块实现800Gbps带宽的核心技术。

weixin_30839881的博客 1540

408 | 408常用计算公式与方法 —— 计组篇 汇总

408常用计算公式与方法 —— 计算机组成原理篇 汇总

"You are worthy! You can do it!" 4649

Java开发者Docker实战指南:从容器化原理到微服务部署

容器化技术通过将应用及其依赖打包成轻量级、可移植的容器,解决了环境差异和依赖冲突问题。其核心原理基于Linux命名空间和控制组实现资源隔离与限制,相比传统虚拟机更轻量高效。这项技术为现代化软件交付和微服务架构提供了基石,显著提升了开发、测试和部署的一致性。在Java技术栈中,Docker能确保JDK版本、应用服务器配置的一致性,实现“一次构建,处处运行”。通过Dockerfile定义镜像构建过程,配合Docker Compose进行多服务编排,Java开发者可以高效管理Spring Boot等微服务应用及其

weixin_34293141的博客 334

Python爬虫实战:爬取携程旅游平台数据,我拆解了动态反爬+Cookie续命(附完整可运行代码)

反爬类型表现形式应对思路sign参数返回403/空数据逆向JS还原加密逻辑Cookie时效登录后1小时Cookie失效定时刷新Cookie/保存登录态行为检测爬取过快触发验证码模拟真人延时/随机点击IP封禁单IP爬取超50条数据被封付费代理池/降低请求频率爬取携程旅游平台数据的核心,不是“简单的HTTP请求”,而是“理解平台的反爬逻辑并合规适配”——从sign参数破解到Cookie维护,再到行为模拟,每一步都是对HTTP协议、前端加密、用户行为的深度理解。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1713

企业级应用部署实战:从Docker容器化到CI/CD自动化

在现代软件工程中,应用部署是连接开发与运维的关键环节,其核心原理在于通过标准化和自动化确保软件交付的可靠性与一致性。容器化技术通过封装应用及其运行环境,解决了“在我机器上能运行”的经典难题,实现了环境的一致性。从技术价值看,自动化部署流水线能显著降低人为错误、提升发布效率,并支持快速回滚。在实际应用场景中,企业级部署通常涉及环境隔离、配置管理、服务编排、监控告警等多个维度。本文以Spring Boot应用为例,结合Docker和Docker Compose等热词,详细拆解了从服务器初始化、容器化部署到日志监

weixin_34348805的博客 358

使用 MATLAB/Simulink + Simscape Electrical,构建一个含光伏并网系统与SVG的联合仿真模型,实现动态无功补偿与电压支撑

摘要:本文详细介绍了基于Simulink的SVG与光伏并网逆变器联合系统建模方法。通过构建包含光伏单元、SVG主电路和控制模块的仿真模型,实现动态无功补偿与电压稳定。重点阐述了ip-iq无功检测算法、双闭环控制和SVPWM调制等关键技术。仿真结果表明,该系统能快速响应无功需求,在10ms内将功率因数提升至0.98以上,有效抑制电压波动。文章为新能源并网系统中的电能质量治理提供了实用解决方案,并提出了进一步优化方向。

xiaoheshang_123的博客 322

USLE模型(1.2):LS因子的计算

基于USLE的甘南川西北土壤侵蚀研究。准备好30米分辨率的dem。

所有专家都曾始于新手 3481

Docker容器化部署实战:从零构建企业级AI应用系统

容器化技术是现代软件开发和部署的核心实践,它通过将应用及其依赖打包成标准化的容器单元,实现了环境一致性、快速部署和资源隔离。其核心原理基于操作系统级虚拟化,相比传统虚拟机更加轻量高效。在技术价值层面,容器化显著提升了开发运维效率,简化了依赖管理,并为企业级应用的微服务架构提供了基础支撑。这一技术广泛应用于Web服务、数据库、AI模型服务等复杂系统的部署场景。本文以实战为导向,通过构建一个集成了AI能力的客户关系管理系统,详细演示了如何使用Docker Compose进行多服务编排,涵盖镜像构建、网络配置、数

weixin_30902251的博客 397

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

5个简单步骤:快速部署你的FoundryVTT虚拟桌面服务器

想要在几分钟内搭建一个稳定可靠的Foundry Virtual Tabletop服务器吗?FoundryVTT Docker项目为你提供了完整的容器化解决方案,让你轻松享受桌面角色扮演游戏的乐趣。无论是新手用户还是经验丰富的游戏主持人,这个项目都能帮助你快速搭建专业的虚拟桌面平台。让我们一起来探索如何轻松部署你的个人游戏服务器吧!🎲 ## 🚀 快速入门指南:5分钟搭建你的游戏服务器 Fou

gitblog_00371的博客 644

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

01-Docker入门与核心概念

要真正理解Docker,我们不能仅仅停留在"它是一个工具"的层面。任何一项技术的诞生都不是凭空而来的,它是对前人智慧的继承与发展,是对现实问题的回应。容器化技术同样如此——它有着超过四十年的技术积淀,经历了从chroot到LXC,再到Docker和Kubernetes的漫长演进。本章将带你穿越时光,梳理容器化技术的发展脉络,让你明白Docker为什么会出现在这个时代,以及它解决了前人没有解决好的哪些问题。软件交付方式的演进,本质上是人类对计算资源利用率和管理效率不断追求的过程。我们可以将这个过程分为三个主要

Na2SiO3Glue的博客 686

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【docker基础】0、系统学习docker之总计划

本文提供了一个系统的13周Docker学习计划,适合零基础学习者。计划分为5个阶段:基础概念与环境准备(1-2周)、基础操作(2-3周)、应用部署实践(2-3周)、高级功能与最佳实践(2-3周)以及实战项目与总结(1-2周)。

正经教主是个热衷于正经学习分享的教主。 452

从Docker Compose到生产环境:复杂应用部署全流程实战指南

在现代软件工程中,容器化技术已成为应用部署的核心范式。Docker通过提供轻量级、一致性的运行环境,解决了开发与生产环境差异的经典难题,其核心原理是基于操作系统级虚拟化实现资源隔离与打包。这项技术的工程价值在于极大提升了应用的可移植性、部署效率和资源利用率。从微服务架构到AI工作流平台,容器化部署广泛应用于需要快速迭代、弹性伸缩的复杂系统场景。本文以典型的**Docker Compose**部署为蓝本,深入拆解包含**微服务**、数据库、消息队列等组件的复杂应用从环境准备、配置管理到服务编排的全流程,涵盖网

weixin_30621711的博客 460
上一篇: 自己动手写Docker系列 -- 5.7实现通过容器制作镜像
下一篇: 自己动手写Docker系列 -- 6.1 ip分配管理
_萧_
博客等级 码龄10年 55粉丝 157原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值