Skip to content

Run a C++ Boost app

In this guide we create and deploy a C++-based HTTP web server using the Boost libraries. To run this example, follow these steps:

  1. Install the kraft CLI tool and a container runtime engine, e.g. Docker.

  2. Clone the example repository and cd into the examples/http-cpp-boost/ directory:

Terminal window
git clone https://github.com/kraftcloud/examples
cd examples/http-cpp-boost/

Make sure to log into KraftCloud by setting your token and a metro close to you. We use fra0 (Frankfurt, 🇩🇪) in this guide:

Terminal window
# Set KraftCloud access token
export KRAFTCLOUD_TOKEN=token
# Set metro to Frankfurt, DE
export KRAFTCLOUD_METRO=fra0

When done, invoke the following command to deploy this application on KraftCloud:

Terminal window
kraft cloud deploy -p 443:8080 .

The output shows the instance URL and other details:

Terminal window
[] Deployed successfully!
────────── name: http-cpp-boost-rae7s
────────── uuid: 5a9886fa-f8a3-4860-afcf-d5eb13fdc38d
───────── state: running
─────────── url: https://red-snow-3bn7bzc8.fra0.kraft.host
───────── image: http-cpp-boost@sha256:61cf86b89fed46351af53689e27189315e466576475f61c7240bf17644613489
───── boot time: 15.00 ms
──────── memory: 128 MiB
service group: red-snow-3bn7bzc8
── private fqdn: http-cpp-boost-rae7s.internal
──── private ip: 172.16.6.4
────────── args: /http_server

In this case, the instance name is http-cpp-boost-rae7s and the URL is https://red-snow-3bn7bzc8.fra0.kraft.host. They are different for each run.

Use curl to query the KraftCloud instance of the C++ Boost HTTP web server:

Terminal window
curl https://red-snow-3bn7bzc8.fra0.kraft.host
Hello, World!

At any point in time, you can list information about the instance:

Terminal window
kraft cloud instance list
NAME FQDN STATE CREATED AT IMAGE MEMORY ARGS BOOT TIME
http-cpp-boost-rae7s red-snow-3bn7bzc8.fra0.kraft.host running 1 minute ago http-cpp-boost@sha256:61cf86b89fed46351af53689e27189315e... 128 MiB /http_server 15000us

When done, you can remove the instance:

Terminal window
kraft cloud instance remove http-cpp-boost-rae7s

Customize your Application

To customize the application, update the files in the repository, listed below:

  • http_server.cpp: the C++ HTTP server
  • Kraftfile: the KraftCloud specification
  • Dockerfile: the Docker-specified application filesystem
/**
* Compile with: g++ async_http_server.cpp -o async_http_server -lboost_system -lboost_thread -lpthread
*
* https://gist.github.com/danilogr/990efa4ab3b5bce29b883b931ac55507
*/
#include <iostream>
#include <ostream>
#include <istream>
#include <ctime>
#include <string>
#include <functional>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread.hpp>
using boost::asio::ip::tcp;
class HttpServer; // forward declaration
class Request : public boost::enable_shared_from_this<Request>
{
// member variables
HttpServer& server;
boost::asio::streambuf request;
boost::asio::streambuf response;
void afterRead(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
// done reading, writes answer (yes, we ignore the request);
std::ostream res_stream(&response);
boost::system::error_code err;
res_stream << "HTTP/1.0 200 OK\r\n"
<< "Content-Type: text/html; charset=UTF-8\r\n"
<< "Content-Length: 14\r\n"
<< "\r\n"
<< "Hello, World!\n" << "\r\n";
boost::asio::async_write(*socket, response, boost::bind(&Request::afterWrite, shared_from_this(), err, bytes_transferred));
}
void afterWrite(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
// done writing, closing connection
socket->close();
}
public:
boost::shared_ptr<tcp::socket> socket;
Request(HttpServer& server);
void answer()
{
if (!socket) return;
// reads request till the end
boost::system::error_code err;
boost::asio::async_read_until(*socket, request, "\r\n\r\n",
boost::bind(&Request::afterRead, shared_from_this(), err, 0));
}
};
class HttpServer
{
public:
HttpServer(unsigned int port) : acceptor(io_service, tcp::endpoint(tcp::v4(), port)) {}
~HttpServer() { if (sThread) sThread->join(); }
void Run()
{
sThread.reset(new boost::thread(boost::bind(&HttpServer::thread_main, this)));
}
boost::asio::io_service io_service;
private:
tcp::acceptor acceptor;
boost::shared_ptr<boost::thread> sThread;
void thread_main()
{
// adds some work to the io_service
start_accept();
io_service.run();
}
void start_accept()
{
boost::system::error_code err;
boost::shared_ptr<Request> req (new Request(*this));
acceptor.async_accept(*req->socket,
boost::bind(&HttpServer::handle_accept, this, req, err));
}
void handle_accept(boost::shared_ptr<Request> req, const boost::system::error_code& error)
{
if (!error) { req->answer(); }
start_accept();
}
};
Request::Request(HttpServer& server): server(server)
{
socket.reset(new tcp::socket(server.io_service));
}
int main()
{
HttpServer server(8080);
server.Run();
}
}

Lines in the Kraftfile have the following roles:

  • spec: v0.6: The current Kraftfile specification version is 0.6.

  • runtime: base: The Unikraft runtime kernel to use is its base one.

  • rootfs: ./Dockerfile: Build the application root filesystem using the Dockerfile.

  • cmd: ["/http_server"]: Use /http_server as the starting command of the instance.

Lines in the Dockerfile have the following roles:

  • COPY ./http_server.cpp /src/http_server.cpp: Copy the server implementation file (http_server.cpp) in the Docker filesystem (in /src/http_server.cpp).

The following options are available for customizing the application:

  • If only updating the implementation in the http_server.cpp source file, no other change is required.

  • If new files are added, these have to be copied in the application filesystem, using the COPY command in the Dockerfile.

  • If a new C++ source files is added, update the cmd line in the Kraftfile and replace http_server.cpp to run that file when creating the instance.

  • More extensive changes may require expanding the Dockerfile with additional Dockerfile commands.

Learn More

Use the --help option for detailed information on using KraftCloud:

Terminal window
kraft cloud --help

Or visit the CLI Reference.