Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building a compiled application with Docker

I am building a server, written in C++ and want to deploy it using Docker with docker-compose. What is the "right way" to do it? Should I invoke make from Dockerfile or build manually, upload to some server and then COPY binaries from Dockerfile?

like image 888
Alexander Shishenko Avatar asked Dec 29 '15 19:12

Alexander Shishenko


People also ask

Can any application run in Docker?

You can run any application in Docker as long as it can be installed and executed unattended, and the base operating system supports the app. Windows Server Core runs in Docker which means you can run pretty much any server or console application in Docker.

Is Docker still relevant 2021?

Docker support will be removed in version 1.22, which is planned for the second half of 2021. That's why I think that the year 2021 is the beginning of Docker's end.


1 Answers

I had difficulties automating our build with docker-compose, and I ended up using docker build for everything:

Three layers for building

Run → develop → build

Then I copy the build outputs into the 'deploy' image:

Run → deploy

Four layers to play with:

Run
  • Contains any packages required for the application to run - e.g. libsqlite3-0
Develop
  • FROM <projname>:run
  • Contains packages required for the build
    • e.g. g++, cmake, libsqlite3-dev
  • Dockerfile executes any external builds
    • e.g. steps to build boost-python3 (not in package manager repositories)
Build
  • FROM <projname>:develop
  • Contains source
  • Dockerfile executes internal build (code that changes often)
  • Built binaries are copied out of this image for use in deploy
Deploy
  • FROM <projname>:run
  • Output of build copied into image and installed
  • RUN or ENTRYPOINT used to launch the application

The folder structure looks like this:

.
├── run
│   └── Dockerfile
├── develop
│   └── Dockerfile
├── build
│   ├── Dockerfile
│   └── removeOldImages.sh
└── deploy
    ├── Dockerfile
    └── pushImage.sh

Setting up the build server means executing:

docker build -f run -t <projName>:run
docker build -f develop -t <projName>:develop

Each time we make a build, this happens:

# Execute the build
docker build -f build -t <projName>:build

# Install build outputs
docker build -f deploy -t <projName>:version

# If successful, push deploy image to dockerhub
docker tag <projName>:<version> <projName>:latest
docker push <projName>:<version>
docker push <projName>:latest

I refer people to the Dockerfiles as documentation about how to build/run/install the project.

If a build fails and the output is insufficient for investigation, I can run /bin/bash in <projname>:build and poke around to see what went wrong.


I put together a GitHub repository around this idea. It works well for C++, but you could probably use it for anything.


I haven't explored the feature, but @TaylorEdmiston pointed out that my pattern here is quite similar to multi-stage builds, which I didn't know about when I came up with this. It looks like a more elegant (and better documented) way to achieve the same thing.

like image 183
MatrixManAtYrService Avatar answered Oct 05 '22 23:10

MatrixManAtYrService