Home > Back-end >  C with Crow, CMake, and Docker
C with Crow, CMake, and Docker

Time:08-15

Goal

I would like to compile an Crow Project with CMake and deploy it in a docker container.

Code

So far, I compiled in Visual Studio and installed Crow via VCPKG similar to this Tutorial. example main.cpp from Crow website:

#include "crow.h"
//#include "crow_all.h"

int main()
{
    crow::SimpleApp app; //define your crow application

    //define your endpoint at the root directory
    CROW_ROUTE(app, "/")([](){
        return "Hello world";
    });

    //set the port, set the app to run on multiple threads, and run the app
    app.port(18080).multithreaded().run();
}

I want to build my docker image with docker build -t main_app:1 . and then run a container with docker run -d -it -p 443:18080 --name app main_app:1. Therefore, I considered something similar like this:

Dockerfile:

FROM ubuntu:latest

RUN apt-get update -y
RUN apt-get upgrade -y

# is it necessary to install all of them?
RUN apt-get install -y g   gcc cmake make git gdb pkg-config

RUN git clone --depth 1 https://github.com/microsoft/vcpkg
RUN ./vcpkg/bootstrap-vcpkg.sh

RUN /vcpkg/vcpkg install crow

CMakeLists.txt:

cmake_minimum_required(VERSION 3.8)

project(project_name)

include(/vcpkg/scripts/buildsystems/vcpkg.cmake)

find_package(Crow CONFIG REQUIRED)

add_executable(exe_name "main.cpp")

target_link_libraries(exe_name PUBLIC Crow::Crow)

Questions

  1. However, obviously this is not complete and thus will not work. Hence, I would like to know how a proper (and simple) Dockerfile and CMakeLists.txt would look like for this main.cpp?
  2. Is it possible to create my image without VCPKG? I am a little bit concerned about my image and container size, here.
  3. How would it work with the crow_all.h header only file?
  4. Is it possible to build an image from an already compiled name.exe, as well - so I won't have to compile anything while building the image?
  5. Since this ought to be a minimal example, would there be any conflicts with a file structure like this:
docker_project
  |__Dockerfile
  |__CMakeLists.txt
  |__header.hpp
  |__class.cpp
  |__main.cpp

Thanks for your help :)

CodePudding user response:

After further research and testing I could solve this issue on two ways:

Crow.h Project compiled with CMake in Docker container

Dockerfile

# get baseimage
FROM ubuntu:latest

RUN apt-get update -y
RUN apt-get upgrade -y
# reinstall certificates, otherwise git clone command might result in an error
RUN apt-get install --reinstall ca-certificates -y

# install developer dependencies
RUN apt-get install -y git build-essential cmake --no-install-recommends

# install vcpkg package manager
RUN git clone https://github.com/microsoft/vcpkg
RUN apt-get install -y curl zip
RUN vcpkg/bootstrap-vcpkg.sh

# install crow package
RUN /vcpkg/vcpkg install crow

# copy files from local directory to container
COPY . /project

# define working directory from container
WORKDIR /build

# compile with CMake 
RUN bash -c "cmake ../project && cmake --build ."

# run executable (name has to match with CMakeLists.txt file)
CMD [ "./app" ]

Docker directory would look like this:

Docker
  |__vcpkg
    |__ ...
  |__project
    |__CMakeLists.txt
    |__main.cpp
  |__build
    |__app
    |__ ...

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)

project(project)

# full path from root directory
include(/vcpkg/scripts/buildsystems/vcpkg.cmake)

find_package(Crow CONFIG REQUIRED)

add_executable(
    app
    main.cpp
)

target_link_libraries(app PUBLIC Crow::Crow)

build Docker image in local directory

project
  |__Dockerfile
  |__CMakeLists.txt
  |__main.cpp

Navigate to project folder in shell and run docker build -t image_name:1 . to build the Docker image and run Docker container with docker run -d -it --rm --name container_name -p 443:18080 image_name:1.

Crow Project compiled with g command and header only library in Docker container

I created the crow_all.h header only file from Crow Github repository and downloaded the asio package via VCPKG on my PC and copied the header files (C:\vcpkg\packages\asio_x64-windows\include) to my project folder into a subdirectory called asio. Hence, my project directory look like this:

project
  |__asio
    |__asio.hpp
    |__asio
      |__ ...
  |__crow_all.h
  |__Dockerfile
  |__main.cpp

I build and run the Docker image/container with the same commands as above. Dockerfile (entire content from project directory gets copied into /usr/src/ directory in Docker container)

# get baseimage
FROM gcc:12

# copy files from local folder to destination
COPY . /usr/src

# define working directory in container
WORKDIR /usr/src

# compile main.cpp (-I/usr/src/asio/ link path starting from root)
RUN g   -I/usr/src/asio/ main.cpp -lpthread -o app

# run executable
CMD [ "./app" ]

To the other questions

  1. I still do not know, whether that is possible.
  2. With such a (still) simple file structure no serious conflicts appeared.
  • Related