构建 HTTP 服务端与 Docker 镜像:从开发到测试

embedded/2024/11/13 10:14:09/

在现代应用开发中,Docker 是一种非常流行的技术,用于打包、分发和运行应用程序。这篇博文将介绍如何使用 Docker 创建一个 HTTP 服务端,打包成 Docker 镜像,并在本地进行测试,包括如何模拟客户端发送 POST 请求。

1. 介绍

本篇博客的目标是:

  • 创建一个简单的 HTTP 服务端应用。

  • 将应用打包成 Docker 镜像。

  • 启动并测试 HTTP 服务端。

  • 使用 curl 模拟客户端向服务端发送 POST 请求。

  • 管理 Docker 容器和镜像,包括停止、删除容器和镜像。

2. 创建 HTTP 服务端

如果你用的是C++11,那么就可以用httplib库来完成window和linux下的HTTP相关操作。在这个库中,作者已给出服务器端和客户端的示例代码,可以直接运行。路径是"cpp-httplib-master\example\example.sln"

https://i-blog.csdnimg.cn/direct/bc02eb41f1b94c17a5b787be03846774.png" />

相当于已经有一个现成的 HTTP 服务端应用,只需要往里面添加请求。此处我假设服务端处理 POST 请求,通过指定路径 /get_route 来接收 JSON 数据,并返回一个 JSON 响应。

json库指路:GitHub - nlohmann/json: JSON for Modern C++

示例代码(C++ HTTP 服务端)

#include <httplib.h>
#include <nlohmann/json.hpp>
​
int main() {httplib::Server svr;
​svr.Post("/get_route", [&](const httplib::Request& req, httplib::Response& res) {try {// 解析请求体中的 JSON 数据nlohmann::json request_data = nlohmann::json::parse(req.body);// 进行逻辑处理(例如,执行某种数据处理算法)// 假设我们有一个处理函数 `process_route`,会根据请求的内容计算路径nlohmann::json response_data = process_route(request_data);// 返回 JSON 响应res.set_content(response_data.dump(), "application/json");} catch (const std::exception& e) {res.status = 400;res.set_content("{\"error\": \"Invalid JSON data\"}", "application/json");}});
​// 启动服务端,监听 8080 端口svr.listen("0.0.0.0", 8080);return 0;
}

3. 打包 Docker 镜像

在linux环境下通过 Docker 将客户端打包成镜像,方便在任何支持 Docker 的环境中运行。以下是将应用打包为 Docker 镜像的步骤。

3.1. 创建 Dockerfile

首先,我们需要一个 Dockerfile 来描述如何构建镜像。 Dockerfile文件需要在当前工程目录下

https://i-blog.csdnimg.cn/direct/65d5a35d6e324fb094a47eef6afa6d08.png" />

下面是一个我的 Dockerfile 示例:

# 使用官方 Ubuntu 20.04 镜像作为基础镜像
FROM ubuntu:20.04
​
# 设置时区
ENV TZ=Asia/Shanghai
RUN apt-get update && apt-get install -y \tzdata \&& dpkg-reconfigure --frontend noninteractive tzdata
​
# 安装必要的系统依赖(根据项目需要添加)
RUN apt-get install -y \build-essential \libboost-all-dev \libstdc++6 \libssl-dev \libcurl4-openssl-dev \wget \curl \ca-certificates \&& apt-get clean
​
# 创建工作目录
WORKDIR /app
​
# 复制 .dockerignore 文件中未忽略的项目文件(可以通过 .dockerignore 排除不需要的文件)
COPY . .
​
# 复制编译后的可执行文件到容器中的 /usr/local/bin 路径
COPY ./bin/AvoidObs_Search /usr/local/bin/AvoidObs_Search
​
# 设置容器内的默认命令
ENTRYPOINT ["/usr/local/bin/AvoidObs_Search"]
​
# 可选:如果需要将配置文件挂载到容器中,可以在运行容器时使用 -v 选项来挂载
# EXPOSE 8080
​
# 默认的运行参数可以根据实际需求修改
CMD ["--help"]

3.2. 构建 Docker 镜像

使用 docker build 命令来构建镜像。该命令要求在项目的根目录下,输入pwd查看当前路径,并且确认包含 Dockerfile

docker build -t avoidobs-search:1.0 .

此命令会根据 Dockerfile 的定义,打包出一个名为 avoidobs-search:1.0 的镜像。

3.3. 运行 Docker 容器

一旦镜像构建完成,就可以使用以下命令来启动容器:

docker run -it -p 8080:8080 avoidobs-search:1.0

这个命令将容器的 8080 端口映射到主机的 8080 端口,允许从外部访问服务。

4. 测试 HTTP 服务

在 Docker 容器启动后,服务已经在 8080 端口监听请求。接下来,我们使用 curl 来模拟客户端发送一个 POST 请求。

4.1. 使用 curl 发送 POST 请求

curl 是一个强大的命令行工具,用于向 URL 发送请求。在本例中,我们发送一个包含多个字段的 JSON 数据:

curl -X POST http://localhost:8080/get_route -H "Content-Type: application/json" -d "{\"num_uavs\": 5, \"flag_use_avoid_obs\": 1, \"grid_size\": 250, \"rally_point\": {\"lat\": 300986462, \"lng\": 1079954736}, \"strike_point\": {\"lat\": 300727124, \"lng\": 1085859475}, \"avoidance_area\": [{ \"lat\": 323933074, \"lng\": 1047571967 }, { \"lat\": 324415592, \"lng\": 1083385845 }, { \"lat\": 297743777, \"lng\": 1083237961 }, { \"lat\": 297827300, \"lng\": 1046171234 }], \"search_area\": [{ \"lat\": 301008931, \"lng\": 1081017137 }, { \"lat\": 303906132, \"lng\": 1083715730 }, { \"lat\": 303176929, \"lng\": 1089347623 }, { \"lat\": 298410734, \"lng\": 1086922078 }, { \"lat\": 299130795, \"lng\": 1081810098 }], \"obstacles\": [{ \"obs_type\": 1, \"circle\": { \"radius\": 2000000, \"lat\": 314529743, \"lng\": 1061959970 } }, { \"obs_type\": 1, \"circle\": { \"radius\": 2000000, \"lat\": 305723418, \"lng\": 1059969981 } }, { \"obs_type\": 0, \"polygon\": [{ \"lat\": 318753658, \"lng\": 1073292651 }, { \"lat\": 318312837, \"lng\": 1075420574 }, { \"lat\": 317308720, \"lng\": 1074607380 }] }]}"

4.2. 解释 curl 命令:

  • -X POST:指定 HTTP 请求方法为 POST。

  • -H "Content-Type: application/json":指定请求头,告诉服务端请求体是 JSON 格式。

  • -d:指定请求体数据,传递给服务端的 JSON 数据。

5. Docker 容器与镜像管理

在整个过程中,不停调整代码逻辑,因此要管理 Docker 容器和镜像。以下是一些常用命令:

5.1. 查看 Docker 容器

docker ps -a

https://i-blog.csdnimg.cn/direct/3e85bf9a4efb40198ea68e2a62b3f3c3.png" />

5.2. 停止 Docker 容器

这里要用的是容器ID,即docker ps -a得到的

docker stop <CONTAINER ID>

5.3. 删除 Docker 容器

这里要用的是容器ID,即docker ps -a得到的

docker rm <CONTAINER ID>

5.4. 查看 Docker 镜像信息

docker images

5.5. 删除 Docker 镜像

这里要用的是镜像ID,即docker images得到的

docker rmi <IMAGE ID>

6. 遇到的问题

6.1. 读取文件

关于可执行程序需要读取文件和输出文件的问题

从Docker打包的镜像中运行AvoidObs_Search可执行程序和直接运行linux环境下的AvoidObs_Search可执行程序时在读取文件时,容器内运行的程序提示无法读取文件。

原因:docker内部镜像的路径和实际运行路径不一样,所以初始化文件的路径对于在docker里的可执行程序来说是无效的,故无法读取数据。

更改为接收POST请求后解决,可以完成通信。

6.2. docker pull失败

docker pull 失败的最常见原因之一是网络连接问题。如果你的网络连接到 Docker Hub 或私有镜像仓库不稳定,可能会导致拉取镜像失败。

1. 找到 Docker 配置文件

Docker 的配置文件 daemon.json 用于配置 Docker 的各种设置。你需要修改这个配置文件,以指定镜像加速器。

  • Linux 系统:配置文件通常位于 /etc/docker/daemon.json

  • Windows 系统:配置文件通常位于 C:\ProgramData\Docker\config\daemon.json

  • MacOS 系统:配置文件通常位于 /Applications/Docker.app/Contents/Resources/etc/docker/daemon.json

如果该文件不存在,可以直接vim /etc/docker/daemon.json,创建一个新的文件,再进行修改。

2. 配置 Docker 镜像加速器

以下给出我的配置。

{"registry-mirrors": ["https://docker.m.daocloud.io","https://dockerproxy.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://hub-mirror.c.163.com","https://hub.uuuadc.top","https://docker.anyhub.us.kg","https://dockerhub.jobcher.com","https://dockerhub.icu","https://docker.ckyl.me","https://docker.awsl9527.cn","https://mirror.baidubce.com"]
}

修改完成后,键盘上按esc退出,英文状态输入:,再输入wq保存退出。


http://www.ppmy.cn/embedded/136904.html

相关文章

每天5分钟玩转C#/.NET之C#线性查找算法

前言 线性查找算法是一种简单的查找算法&#xff0c;用于在一个数组或列表中查找一个特定的元素。它从数组的第一个元素开始&#xff0c;逐个检查每个元素&#xff0c;直到找到所需的元素或搜索完整个数组。线性查找的时间复杂度为O(n)&#xff0c;其中n是数组中的元素数量。 …

如何保证Redis与MySQL双写一致性

什么是双写一致性问题&#xff1f; 双写一致性主要指在一个数据同时存在于缓存&#xff08;如Redis&#xff09;和持久化存储&#xff08;如MySQL&#xff09;的情况下&#xff0c;任何一方的数据更新都必须确保另一方数据的同步更新&#xff0c;以保持双方数据的一致状态。这一…

【大数据学习 | kafka高级部分】kafka的kraft集群

首先我们分析一下zookeeper在kafka中的作用 zookeeper可以实现controller的选举&#xff0c;并且记录topic和partition的元数据信息&#xff0c;帮助多个broker同步数据信息。 在新版本中的kraft模式中可以这个管理和选举可以用kafka自己完成&#xff0c;而不再依赖zookeeper。…

项目管理和研发管理中的痛点及其解决方案

在现代企业中&#xff0c;研发管理和项目管理面临着多重挑战&#xff0c;包括资源配置不当、沟通不畅、目标不明确、进度控制困难等。这些痛点不仅影响项目的顺利推进&#xff0c;还可能导致企业在市场竞争中处于劣势。尤其是在资源配置不当方面&#xff0c;企业往往难以合理分…

图像处理自动渲染代码

图像处理自动渲染通常涉及一系列步骤&#xff0c;包括图像读取、预处理、渲染参数设置、渲染执行以及结果保存等。以下是一个简化的Python示例代码&#xff0c;使用了OpenCV库进行图像处理&#xff0c;以及一个假设的render_function来模拟渲染过程&#xff08;实际上&#xff…

AI 心目中的我

这两天网上有个很流行的游戏&#xff0c;就是向 ChatGPT 提问&#xff1a; 根据你对我的所知&#xff0c;请绘制一张图&#xff0c;画一下你心目中我现在生活的样子。 然后 ChatGPT 就画出了下面这张图&#xff1a; 当然&#xff0c;第一次问这个问题的回复是&#xff1a; 然后…

Unet++改进7:添加SimAM注意力机制||无参数的卷积神经网络注意模块

本文内容:添加SimAM注意力机制 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 在本文中,我们为卷积神经网络(ConvNets)提出了一个概念简单但非常有效的注意力模块。与现有的通道智能和空间智能注意力模块相比,我们的模块在不向原始网络添加参数的情况下…

【Linux探索学习】第十二弹——初识进程:进程的定义、描述和一些简单的相关操作

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在前面经过那么多篇的铺垫后&#xff0c;今天我们正式进入Linux学习的第一个重难点——进程&#xff0c;理解进程对于我们学习操作系统的其…