在现代应用开发中,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"

相当于已经有一个现成的 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文件需要在当前工程目录下

下面是一个我的 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

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保存退出。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部