Search code examples
c++dockercmakecrow

C++ with Crow, CMake, and Docker


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 :)


Solution

  • 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.