学习open62541 --- [79] 在docker中运行open62541工程

docker是非常流行的容器技术,解决了部署环境不一致的问题,open62541的工程也可以在docker容器中运行,本文讲述如何把open62541工程放到docker容器中运行。

本文使用WSL ubuntu 22.04作为宿主环境,其它linux也是一样。


一 拉取debian镜像

执行docker命令拉取debian镜像

docker pull debian:bookworm

这个debian镜像创建的容器非常干净,啥都没有,都需要自己安装,如果我想创建多个容器,那就要安装多次,所以这里基于debian:bookworm来制作自定义镜像。


二 编写Dockerfile

通过Dockerfile来制作自定义镜像,

# 使用 debian:bookworm 作为基础镜像
FROM debian:bookworm# 设置环境变量以避免交互式配置提示
ENV DEBIAN_FRONTEND=noninteractive# 确保 /etc/apt/sources.list 文件存在,并使用国内镜像源(以阿里云为例)
RUN if [ ! -f "/etc/apt/sources.list" ]; then echo "deb http://mirrors.aliyun.com/debian/ bookworm main non-free contrib" > /etc/apt/sources.list && \echo "deb-src http://mirrors.aliyun.com/debian/ bookworm main non-free contrib" >> /etc/apt/sources.list && \echo "deb http://mirrors.aliyun.com/debian/ bookworm-updates main non-free contrib" >> /etc/apt/sources.list && \echo "deb-src http://mirrors.aliyun.com/debian/ bookworm-updates main non-free contrib" >> /etc/apt/sources.list; fi# 更新包列表并安装常用开发工具
RUN apt-get update && \apt-get install -y \git \curl \wget \cmake \vim \sudo \build-essential \python3 \python-is-python3 \python3-pip \python3.11-venv \openssh-client \net-tools \iproute2 \iputils-ping \dnsutils \ca-certificates \gnupg \lsb-release \&& apt-get clean \&& rm -rf /var/lib/apt/lists/*# 创建虚拟环境目录
RUN python3 -m venv /opt/venv# 设置虚拟环境为当前环境
ENV PATH="/opt/venv/bin:$PATH"# 设置容器启动时默认执行的命令
CMD ["bash"]

然后运行docker命令来制作镜像,

docker build -t myimage:0.0.1 .

执行完毕后,运行docker images来查看当前的本地镜像,
![[Pasted image 20250707215627.png]]

这个镜像可以推送到docker hub或者其他仓库里,然后分享给别人使用,这样就保证开发环境是一样的了。


三 创建open62541工程

在WSL ubuntu下创建一个简单的open62541工程,工程结构如下,包含server和client
![[Pasted image 20250708210916.png]]

open62541使用的版本是v1.4.12,
client.c内容如下,

// client.c,功能主要是从server那里获取时间
#include <stdlib.h>
#include "open62541.h"int main(void) 
{UA_Client *client = UA_Client_new();UA_ClientConfig_setDefault(UA_Client_getConfig(client));UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");if(retval != UA_STATUSCODE_GOOD) {UA_Client_delete(client);return (int)retval;}/* Read the value attribute of the node. UA_Client_readValueAttribute is a* wrapper for the raw read service available as UA_Client_Service_read. */UA_Variant value; /* Variants can hold scalar values and arrays of any type */UA_Variant_init(&value);/* NodeId of the variable holding the current time */const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);retval = UA_Client_readValueAttribute(client, nodeId, &value);if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) {UA_DateTime raw_date = *(UA_DateTime *) value.data;UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);}/* Clean up */UA_Variant_clear(&value);UA_Client_delete(client); /* Disconnects the client internally */return EXIT_SUCCESS;
}

server.c内容如下,

// server.c
#include "open62541.h"#include <signal.h>
#include <stdlib.h>UA_Boolean running = true;static void stopHandler(int sign) {UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");running = false;
}int main(void) 
{signal(SIGINT, stopHandler);signal(SIGTERM, stopHandler);UA_Server *server = UA_Server_new();UA_ServerConfig_setDefault(UA_Server_getConfig(server));UA_StatusCode retval = UA_Server_run(server, &running);UA_Server_delete(server);return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

CMakeLists.txt内容如下,

cmake_minimum_required(VERSION 3.10)project(demo)add_definitions(-std=c99)add_library(open62541 open62541/open62541.copen62541/open62541.h
)add_executable(client src/client.c)
target_include_directories(client PRIVATE open62541)
target_link_libraries(client open62541 pthread)add_executable(server src/server.c)
target_include_directories(server PRIVATE open62541)
target_link_libraries(server open62541 pthread)

最后,在工程根目录下添加.devcontainer.json,内容如下,

{"image":"myimage:0.0.1"
}

这个用于指导使用哪个镜像来生成容器。


四 在容器中运行工程

使用VSCode打开工程,然后Ctrl+Shift+p打开命令界面,执行“Dev Containers: Reopen in Container”
![[Pasted image 20250708221118.png]]

这个执行后会通过镜像创建容器,然后在容器里打开本工程,最后VScode左下角会变成下面这样,
![[Pasted image 20250709210120.png]]

表示已经在容器里打开了,默认是root用户。

工程在容器中的目录是/workspaces/prj_001/

在工程根目录下创建build目录,然后cd进入后执行下面命令进行编译,

cmake .. && make

这里需要创建终端执行命令,有2种方式,

  1. 使用VSCode的终端,因为VSCode已经和容器连接成功了
  2. 在WSL linux下打开终端,然后输入docker ps来查看容器id,最后执行docker exec -it 容器id bash,就可以进入容器里了

编译成功后运行server,默认端口是4840,VSCode里会自动转发,
![[Pasted image 20250709210954.png]]

这样我们在容器外面使用UaExpert也可以访问,非常方便,
![[Pasted image 20250709211035.png]]

这里解释一下为什么使用Reopen in container:因为可以把工程放在宿主机里,如果容器挂了,那么重新开个容器就可以了,如果把工程放到容器里,那么就存在一定的风险了。

还有一点,工程在容器里打开后,里面的文件权限都变成root的了,因为容器默认的用户就是root,当我们在宿主机里想修改工程文件时,就会提示权限不够,解决办法是在工程根目录下,执行下面的命令,把文件的owner再变回来,

sudo chown -R user_name .

user_name就是宿主机的登录用户名。

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

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

相关文章

Spring Boot微服务中集成gRPC实践经验分享

Spring Boot微服务中集成gRPC实践经验分享 一、业务场景描述 在某电商系统中&#xff0c;推荐服务、库存服务、订单服务等微服务需要高效、双向流式通信&#xff0c;RESTHTTP已无法满足低延迟、高并发和严格类型安全的需求。为此&#xff0c;我们选择在Spring Boot微服务中集成…

springboot项目编写测试类,乱码问题解决

​MockMvc 的默认行为​ MockMvc ​默认使用 ISO-8859-1 解码响应&#xff0c;而服务端实际返回 UTF-8 编码数据 。 Postman 无乱码是因浏览器自动识别编码&#xff0c;但 MockMvc 需显式配置。 ​过滤器失效场景​ Spring 的 CharacterEncodingFilter ​默认只对 POST 请求生效…

打破传统,开启 AR 智慧课堂​

在教育领域&#xff0c;AR 智慧课堂宛如一场及时雨&#xff0c;为传统教育模式带来了革命性的变革&#xff0c;让学习变得更加生动有趣、高效互动。通过 AR 技术&#xff0c;抽象的知识瞬间变得鲜活起来&#xff0c;学生们可以在虚拟与现实交织的世界中&#xff0c;探索历史的长…

热烈祝贺 Flink 2.0 存算分离入选 VLDB 2025

VLDB 2025 论文热烈祝贺 Apache Flink 2.0 的重磅研究成果《Disaggregated State Management in Apache Flink 2.0 》被数据库领域顶级会议 VLDB 2025 正式接收&#xff01;这项工作由 Apache Flink 社区 联合 阿里巴巴实时计算 Flink 团队 以及多位学术界研究人员共同完成&…

蓄电池能量管理matlab的simulink仿真

蓄电池能量管理matlab的simulink仿真模型 AlternatorTableData.mat , 7395 Battery_Management_Lib.mdl , 577258 Readme.txt , 1293 license.txt , 1551 ssc_battery_management.mdl , 221248 ssc_lead_acid_battery_50Ah_ini.m , 1760 ssc_lead_acid_battery_80Ah_ini.m , 1…

MyBatisPlus-03-扩展功能

文章目录【README】【1】基于MyBatisPlus的代码生成器【2】MyBatisPlus-DB静态工具【2.1】使用MyBatisPlus的DB静态工具查询单个及多个用户地址【查询单个用户的访问效果】【查询多个用户的访问效果】【3】逻辑删除【3.1】代码实现【4】枚举处理器【4.1】代码实现【5】JSON处理…

初识Neo4j之Cypher(三)

目录 一、介绍 二、语法 1、节点 2、关系 3、属性 4、模式 一、介绍 Cypher 是 Neo4j 的声明式查询语言&#xff0c;兼容 GQL 标准。通过 openCypher 项目&#xff0c;Cypher 以开源方式提供。它类似于 SQL&#xff0c;但专为图数据优化。 Cypher 直观且接近自然语言&…

19-C#静态方法与静态类

C#静态方法与静态类 1.static-静态方法animal.eat&#xff08;&#xff09;;//直接调用 public class animal {public static void eat()//定义静态方法{messagebox.show("animal eat");} }2.static-静态类animal.eat&#xff08;&#xff09;;//直接调用public stat…

基于YOLO的足球检测Web应用:从训练到部署的完整实战

用Python和深度学习技术打造一个完整的足球检测系统&#xff0c;支持图片检测、视频分析和实时监控。本文带你从零开始构建一个专业的Web应用。&#x1f3af; 项目背景 在体育赛事分析和足球训练中&#xff0c;准确识别和定位足球是一个重要需求。本项目利用YOLO深度学习算法&a…

npm 切换 node 版本 和npm的源

在开发过程中&#xff0c;不同项目可能需要不同版本的 Node.js&#xff0c;同时 于由XX原因&#xff0c;我们需要切换npm的源。这时如果需要切换node版本或者npm的源&#xff0c;我们可以使用以下方法。 使用 nvm 切换 Node 版本 1、安装 npm install nvm -g2、使用 # 列出所有…

Java学习第二十部分——EasyMock

目录 一.概述 二.作用 三.工作原理 四.使用示例 五.主要特点 六.适用场景 七.其他模拟框架比较 八.idea简单项目实战 1.打开idea创建Java项目&#xff0c;注意构建系统选“Maven” 2.为pom.xml文件添加如下依赖&#xff0c;并重新加载Maven依赖&#xff0c;直至不报错…

机器学习模型在C++平台的部署

一、概述机器学习模型的训练通常在Python环境下完成&#xff0c;而现实生产环境的复杂性和多样性使得模型的部署成为一个值得关注的重点。不同应用场景下有不同适应的实现方式&#xff0c;这里主要介绍通过一种通用中间格式——ONNX&#xff08;Open Neural Network Exchange&a…

保姆级安装 Ruby 环境下载及安装教程, RubyInstaller下载及安装教程

一、下载安装 RubyInstaller 1.打开 RubyInstaller 官网&#xff1a;https://rubyinstaller.org/ 点击跳转, 官网界面如下图&#xff1a; 点击下载最新的 RubyDevkit 版本&#xff08;如 RubyDevkit 3.4.X (x64) &#xff09;。如下图所示&#xff1a; 注意点&#xff1a;如果…

SQL 一键生成 Go Struct!支持字段注释、类型映射、结构体命名规范

SQL 一键生成 Go Struct&#xff01;支持字段注释、类型映射、结构体命名规范 在 Golang 开发中&#xff0c;尤其是操作数据库时&#xff0c;我们经常会遇到这种场景&#xff1a; ✅ 拿到数据库建表 SQL&#xff0c;却要手动写 Go struct✅ 字段几十个、类型复杂&#xff0c;…

Web 前端框架选型:React、Vue 和 Angular 的对比与实践

Web 前端框架选型&#xff1a;React、Vue 和 Angular 的对比与实践 选择前端框架就像选择一个长期合作伙伴。错误的选择可能会让你的项目在未来几年内背负沉重的技术债务&#xff0c;而正确的选择则能让开发效率飞速提升。 经过多年的项目实践&#xff0c;我发现很多新人在框架…

C# 值拷贝、引用拷贝、浅拷贝、深拷贝

值拷贝定义&#xff1a;直接复制变量的值&#xff0c;适用于基本数据类型&#xff08;如int, float, char等&#xff09;。在 C# 中&#xff0c;值类型&#xff08;基本数据类型和结构体&#xff09;默认使用值拷贝。特点&#xff1a;创建原始值的完全独立副本&#xff0c;修改…

深度学习图像分类数据集—百种鸟类识别分类

该数据集为图像分类数据集&#xff0c;适用于ResNet、VGG等卷积神经网络&#xff0c;SENet、CBAM等注意力机制相关算法&#xff0c;Vision Transformer等Transformer相关算法。 数据集信息介绍&#xff1a;525种鸟类识别分类 训练数据集总共有84635张图片&#xff0c;每个文件夹…

零基础 “入坑” Java--- 八、类和对象(一)

文章目录一、初识面向对象二、类的定义和使用1.认识类2.类的定义格式三、类的实例化四、this引用五、对象的构造及初始化1.有关初始化2.构造方法3.就地初始化一、初识面向对象 Java是一门纯面向对象的语言&#xff08;OOP&#xff09;&#xff0c;在面向对象的世界里&#xff…

数字孪生技术引领UI前端设计新篇章:智能物联网的深度集成

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;数字孪生与物联网的共生革命在智能设备爆发式增长的今天&#xff0c;传统…

代码审计-shiro漏洞分析

一、关于shiro介绍 简单讲&#xff0c;shiro是apache旗下的一个Java安全框架&#xff0c;轻量级简单易上手&#xff0c;框架提供很多功能接口&#xff0c;常见的身份认证 、权限认证、会话管理、Remember 记住功能、加密等等。 二、漏洞分析 1.CVE-2019-12422-shiro550 漏洞原理…