diff --git a/LICENSE b/LICENSE index e0f9599..aa9aac2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 frontmark GmbH +Copyright (c) 2024 frontmark GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 526358f..fe16dbb 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,16 @@ Dockerfiles and Makefiles to build and run (web) apps and services. ## nodejs-express-web-service -A stripped-down example of a dockerized [Express](https://expressjs.com) (4.x) web service [[...]](nodejs-express-web-service) +A stripped-down example of a dockerized [Express](https://expressjs.com) (4.x) web service [[more...]](nodejs-express-web-service) ## python-gunicorn-flask-app -A stripped-down example of a dockerized [Flask](https://flask.palletsprojects.com/en/2.2.x/) web application [[...]](python-gunicorn-flask-app) +A stripped-down example of a dockerized [Flask](https://flask.palletsprojects.com/en/2.2.x/) web application [[more...]](python-gunicorn-flask-app) + +## ubuntu-20-04-compile-cxx-with-vcpkg + +A multi-stage build process for a C++ program that *does* use `vcpkg` to manage dependencies [[more...]](ubuntu-20-04-compile-cxx-with-vcpkg) + +## ubuntu-20-04-compile-cxx-without-vcpkg + +A multi-stage build process for a C++ program that does **not** use `vcpkg` to manage dependencies [[more...]](ubuntu-20-04-compile-cxx-without-vcpkg) diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/Dockerfile b/ubuntu-20-04-compile-cxx-with-vcpkg/Dockerfile new file mode 100644 index 0000000..ebc7848 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/Dockerfile @@ -0,0 +1,41 @@ +FROM ubuntu:20.04 as build +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates git \ + curl zip unzip tar \ + wget gpg \ + ninja-build \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /root +# install - latest - cmake: +RUN \ + wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null \ + && echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null \ + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + cmake \ + && rm -rf /var/lib/apt/lists/* +# needed on arm, s390x, ppc64le and riscv platforms: +ENV VCPKG_FORCE_SYSTEM_BINARIES=1 +# bootstrap vcpkg: +RUN \ + git clone https://github.com/microsoft/vcpkg \ + && ./vcpkg/bootstrap-vcpkg.sh +# install boost: +RUN \ + vcpkg/vcpkg install \ + boost-iostreams \ + boost-program-options +COPY src/ ./src +RUN cmake -DCMAKE_BUILD_TYPE=Release -S src -B src/build \ + -DCMAKE_TOOLCHAIN_FILE=/root/vcpkg/scripts/buildsystems/vcpkg.cmake \ + && make -C src/build/main + +FROM ubuntu:20.04 +RUN groupadd -r otto && useradd -r -g otto otto +WORKDIR /home/otto +COPY --from=build /root/src/build/ ./build +USER otto diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/Makefile b/ubuntu-20-04-compile-cxx-with-vcpkg/Makefile new file mode 100644 index 0000000..8bab5f3 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/Makefile @@ -0,0 +1,32 @@ +name = built-with-vcpkg +img = $(name):latest + +caps = --cap-drop ALL +sopt = --security-opt no-new-privileges +mem = +cpu = +pids = +rofs = --read-only --tmpfs /tmp +args = $(caps) $(sopt) $(mem) $(cpu) $(pids) $(rofs) + +.PHONY: all clean build run stop rm up down init reinit rerun +.DEFAULT_GOAL := all +all: build + +clean: ; +build: clean + docker build -t $(img) . +run: + @docker run --rm $(args) --name $(name) --hostname $(name) $(img) ./build/main/progname --name Jane +stop rm: + -docker container $@ $(name) + +up: build run + +down: stop rm + +init: up + +reinit: down init + +rerun: down run diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/README.md b/ubuntu-20-04-compile-cxx-with-vcpkg/README.md new file mode 100644 index 0000000..9866629 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/README.md @@ -0,0 +1,67 @@ +# ubuntu-20-04-compile-cxx-with-vcpkg + +Basic example of a dockerized multi-stage build process for a C++ program that *does* use `vcpkg` to manage dependencies. + +For an example that does **not** use `vcpkg` to manage dependencies, please see [../ubuntu-20-04-compile-cxx-without-vcpkg](../ubuntu-20-04-compile-cxx-without-vcpkg). + +**Table of Contents** + +- [Makefile](#makefile) + - [Build and run the code](#build-and-run-the-code) + +## Makefile + +The [Makefile](Makefile) can be used to easily manage the build process using [GNU Make](https://www.gnu.org/software/make/) (on Linux, macOS and Windows ([Cygwin](https://www.cygwin.com/))). + +### Build and run the code + +```sh +make reinit +``` + +will build the code and run the built program. + +It's a handy shortcut that you can use to redo everything after the code has changed. + +For more fine-grained control, please have a look at the included [Makefile](Makefile). + +You should see the following output: + +```sh +docker build -t built-with-vcpkg:latest . +[+] Building 202.6s (16/16) FINISHED docker:desktop-linux + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 1.53kB 0.0s + => [internal] load metadata for docker.io/library/ubuntu:20.04 1.6s + => [internal] load .dockerignore 0.1s + => => transferring context: 2B 0.0s + => [internal] load build context 0.0s + => => transferring context: 1.31kB 0.0s + => [stage-1 1/4] FROM docker.io/library/ubuntu:20.04@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae9 0.0s + => => resolve docker.io/library/ubuntu:20.04@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9 0.0s + => => sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9c35d 1.13kB / 1.13kB 0.0s + => => sha256:4aa61d4985265be6d872cc214016f2f91a77b1c925dab5ce502db2edc4a7e5af 424B / 424B 0.0s + => => sha256:3048ba0785953b689215053519eb1c34853e2e3af512eed001be59fec1f32e42 2.31kB / 2.31kB 0.0s + => [build 2/8] RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommend 16.2s + => [stage-1 2/4] RUN groupadd -r otto && useradd -r -g otto otto 0.3s + => [stage-1 3/4] WORKDIR /home/otto 0.0s + => [build 3/8] WORKDIR /root 0.0s + => [build 4/8] RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/d 26.4s + => [build 5/8] RUN git clone https://github.com/microsoft/vcpkg && ./vcpkg/bootstrap-vcpkg.sh 65.2s + => [build 6/8] RUN vcpkg/vcpkg install boost-iostreams boost-program-options 91.5s + => [build 7/8] COPY src/ ./src 0.0s + => [build 8/8] RUN cmake -DCMAKE_BUILD_TYPE=Release -S src -B src/build -DCMAKE_TOOLCHAIN_FILE=/root/vcpkg/scr 1.4s + => [stage-1 4/4] COPY --from=build /root/src/build/ ./build 0.0s + => exporting to image 0.0s + => => exporting layers 0.0s + => => writing image sha256:950072b6eb7802f8f30d3fdf09897376b3d6001d972a2471c935cd21ca56eef3 0.0s + => => naming to docker.io/library/built-with-vcpkg:latest 0.0s + +Hello, Jane! +``` + +202.6 seconds. Compare that to the 21.7 seconds of the build process **without** `vcpkg` (see [../ubuntu-20-04-compile-cxx-without-vcpkg](../ubuntu-20-04-compile-cxx-without-vcpkg)). + +The difference is due to the time it takes to download and build the dependencies. + +The actual build time of the program is similar in both cases. diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/src/CMakeLists.txt b/ubuntu-20-04-compile-cxx-with-vcpkg/src/CMakeLists.txt new file mode 100644 index 0000000..5065e8f --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/src/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) +project(progname) +set(CMAKE_CXX_STANDARD 20) +add_subdirectory(main) diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/CMakeLists.txt b/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/CMakeLists.txt new file mode 100644 index 0000000..712938d --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/CMakeLists.txt @@ -0,0 +1,6 @@ +set(Boost_USE_STATIC_LIBS ON) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +add_executable(progname "main.cpp") +find_package(Boost REQUIRED COMPONENTS program_options) +target_link_libraries(progname PRIVATE ${Boost_LIBRARIES}) +include_directories(${Boost_INCLUDE_DIRS}) diff --git a/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/main.cpp b/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/main.cpp new file mode 100644 index 0000000..8d82c5a --- /dev/null +++ b/ubuntu-20-04-compile-cxx-with-vcpkg/src/main/main.cpp @@ -0,0 +1,29 @@ +#include +#include + +using namespace boost::program_options; + +int main(int argc, char **argv) { + try { + options_description desc("Allowed options"); + desc.add_options()("help", "produce help message")( + "name", value(), "say hello to this name"); + + variables_map vm; + store(parse_command_line(argc, argv, desc), vm); + notify(vm); + + if (vm.count("help")) { + std::cout << desc << "\n"; + return 1; + } + + if (vm.count("name")) { + std::cout << "Hello, " << vm["name"].as() << "!\n"; + } else { + std::cout << "Hello, World!\n"; + } + } catch (const error &ex) { + std::cerr << ex.what() << '\n'; + } +} diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/Dockerfile b/ubuntu-20-04-compile-cxx-without-vcpkg/Dockerfile new file mode 100644 index 0000000..036fdf1 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/Dockerfile @@ -0,0 +1,18 @@ +FROM ubuntu:20.04 as build +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + libboost-dev \ + libboost-program-options-dev \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /root +COPY src/ ./src +RUN cmake -DCMAKE_BUILD_TYPE=Release -S src -B src/build \ + && cmake --build src/build + +FROM ubuntu:20.04 +RUN groupadd -r otto && useradd -r -g otto otto +WORKDIR /home/otto +COPY --from=build /root/src/build/ ./build +USER otto diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/Makefile b/ubuntu-20-04-compile-cxx-without-vcpkg/Makefile new file mode 100644 index 0000000..0bf6375 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/Makefile @@ -0,0 +1,32 @@ +name = built-without-vcpkg +img = $(name):latest + +caps = --cap-drop ALL +sopt = --security-opt no-new-privileges +mem = +cpu = +pids = +rofs = --read-only --tmpfs /tmp +args = $(caps) $(sopt) $(mem) $(cpu) $(pids) $(rofs) + +.PHONY: all clean build run stop rm up down init reinit rerun +.DEFAULT_GOAL := all +all: build + +clean: ; +build: clean + docker build -t $(img) . +run: + @docker run --rm $(args) --name $(name) --hostname $(name) $(img) ./build/main/progname --name John +stop rm: + -docker container $@ $(name) + +up: build run + +down: stop rm + +init: up + +reinit: down init + +rerun: down run diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/README.md b/ubuntu-20-04-compile-cxx-without-vcpkg/README.md new file mode 100644 index 0000000..3cf4570 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/README.md @@ -0,0 +1,64 @@ +# ubuntu-20-04-compile-cxx-without-vcpkg + +Basic example of a dockerized multi-stage build process for a C++ program that does **not** use `vcpkg` to manage dependencies. + +For an example that *does* use `vcpkg` to manage dependencies, please see [../ubuntu-20-04-compile-cxx-with-vcpkg](../ubuntu-20-04-compile-cxx-with-vcpkg). + +**Table of Contents** + +- [Makefile](#makefile) + - [Build and run the code](#build-and-run-the-code) + +## Makefile + +The [Makefile](Makefile) can be used to easily manage the build process using [GNU Make](https://www.gnu.org/software/make/) (on Linux, macOS and Windows ([Cygwin](https://www.cygwin.com/))). + +### Build and run the code + +```sh +make reinit +``` + +will build the code and run the built program. + +It's a handy shortcut that you can use to redo everything after the code has changed. + +For more fine-grained control, please have a look at the included [Makefile](Makefile). + +You should see the following output: + +```sh +docker build -t built-without-vcpkg:latest . +[+] Building 21.7s (13/13) FINISHED docker:desktop-linux + => [internal] load build definition from Dockerfile 0.0s + => => transferring dockerfile: 546B 0.0s + => [internal] load metadata for docker.io/library/ubuntu:20.04 1.3s + => [internal] load .dockerignore 0.0s + => => transferring context: 2B 0.0s + => [build 1/5] FROM docker.io/library/ubuntu:20.04@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91e 0.0s + => => resolve docker.io/library/ubuntu:20.04@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9 0.0s + => => sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9c35d 1.13kB / 1.13kB 0.0s + => => sha256:4aa61d4985265be6d872cc214016f2f91a77b1c925dab5ce502db2edc4a7e5af 424B / 424B 0.0s + => => sha256:3048ba0785953b689215053519eb1c34853e2e3af512eed001be59fec1f32e42 2.31kB / 2.31kB 0.0s + => [internal] load build context 0.0s + => => transferring context: 1.26kB 0.0s + => [build 2/5] RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommend 18.7s + => [stage-1 2/4] RUN groupadd -r otto && useradd -r -g otto otto 0.3s + => [stage-1 3/4] WORKDIR /home/otto 0.0s + => [build 3/5] WORKDIR /root 0.0s + => [build 4/5] COPY src/ ./src 0.0s + => [build 5/5] RUN cmake -DCMAKE_BUILD_TYPE=Release -S src -B src/build && cmake --build src/build 1.5s + => [stage-1 4/4] COPY --from=build /root/src/build/ ./build 0.1s + => exporting to image 0.0s + => => exporting layers 0.0s + => => writing image sha256:2f0a4d8c966239cc521ff559847c9db3c98769f39e9dbe02aeeb6d9098a01118 0.0s + => => naming to docker.io/library/built-without-vcpkg:latest 0.0s + +Hello, John! +``` + +21.7 seconds. Compare that to the 202.6 seconds of the build process **with** `vcpkg` (see [../ubuntu-20-04-compile-cxx-with-vcpkg](../ubuntu-20-04-compile-cxx-with-vcpkg)). + +The difference is due to the time it takes to download and build the dependencies. + +The actual build time of the program is similar in both cases. diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/src/CMakeLists.txt b/ubuntu-20-04-compile-cxx-without-vcpkg/src/CMakeLists.txt new file mode 100644 index 0000000..5065e8f --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/src/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) +project(progname) +set(CMAKE_CXX_STANDARD 20) +add_subdirectory(main) diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/CMakeLists.txt b/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/CMakeLists.txt new file mode 100644 index 0000000..a9b2223 --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/CMakeLists.txt @@ -0,0 +1,5 @@ +set(Boost_USE_STATIC_LIBS ON) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +add_executable(progname "main.cpp") +find_package(Boost REQUIRED COMPONENTS program_options) +target_link_libraries(progname PRIVATE ${Boost_LIBRARIES}) diff --git a/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/main.cpp b/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/main.cpp new file mode 100644 index 0000000..8d82c5a --- /dev/null +++ b/ubuntu-20-04-compile-cxx-without-vcpkg/src/main/main.cpp @@ -0,0 +1,29 @@ +#include +#include + +using namespace boost::program_options; + +int main(int argc, char **argv) { + try { + options_description desc("Allowed options"); + desc.add_options()("help", "produce help message")( + "name", value(), "say hello to this name"); + + variables_map vm; + store(parse_command_line(argc, argv, desc), vm); + notify(vm); + + if (vm.count("help")) { + std::cout << desc << "\n"; + return 1; + } + + if (vm.count("name")) { + std::cout << "Hello, " << vm["name"].as() << "!\n"; + } else { + std::cout << "Hello, World!\n"; + } + } catch (const error &ex) { + std::cerr << ex.what() << '\n'; + } +}