question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Simplify usage in different Linux environments

See original GitHub issue

I’m going to write down issue, working-but-terrible solution and would like to ask more experienced people around here for better solution.

Issue

Linux binaries shipped with NuGet package are mostly unusable unless user have exactly the same environment as the one package was built in. Even if you install all the dependencies, you are most likely to end up with slightly different versions of your libraries and OpenCVSharpExtern won’t work. So, unless you are using exactly the same Ubuntu with exactly the same versions of packages as on CI server, it won’t work out of the box.

Working but problematic solution

Local environment

  1. Build OpenCV or install version 4.3.0 (if your package repos have newer versions).
  2. Follow build instructions from README.md and build OpenCvSharpExtern.
  3. Rename it to libOpenCvSharp (without .so) and put file into /usr/lib or make sure ld finds it some other way.

Debug with ldd or just read exception (it will mention what dependency is missing) if you encounter problems.

Docker

Things become even more fun here. If you are hosting ASP .NET Core app inside docker linux container, the only way I found is to build OpenCvSharpExtern in the container similar to production and then extract compilation result along with all dependencies.

  1. Dockerize your app as usual, use mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic as runtime image base.
  2. Run your container with something that won’t constantly break because of OpenCV exceptions (so container doesn’t stop).
  3. docker exec container_name bash to get into the container.
  4. Run all the neccessary apt-get install ..., build OpenCV 4.3.0, build OpenCvSharp and make sure both are installed into the container system (present somewhere in /usr/local/share/opencvsharp4/ or elsewhere). There are CI scripts in this repo that should help with apt-get part.
  5. Copy all these dependencies into the host system (using mounted volume, for example). I had to copy /usr/local, /usr/lib and /lib/x86_64-linux-gnu which turned out to be 1.2GiB.
  6. Remove this experimental container (optional, probably done by docker-compose automatically).
  7. Setup your Dockerfile to copy these files from host onto runtime container after build.
  8. Also something like ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/share/opencv4/lib/:/usr/local/lib/:/lib/x86_64-linux-gnu/" will probably be required.
  9. Enjoy this process again when upgrade of OpenCV needed (or runtime upgraded, etc).

Questions

  1. Is it possible to build statically linked libOpenCvSharpExtern.so to embed all the dependent libs into it? It looks like it was successfully done for Windows, so I wonder if it is possible on Linux.
  2. Is there a better solution for docker problem? Would you just automate compiling OpenCV in production environment steps on your CI server or there is better approach?

I’m fairly noob in either docker and magic of C++ compilation, sorry if I’m missing something obvious. Hope this helps someone or attracts answers with better solutions 😃

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:6

github_iconTop GitHub Comments

1reaction
ArXen42commented, Jul 15, 2020

A bit better solution

@shimat Thanks for the dockerfile you mentioned in #953. I modified this file to create base image that builds environment for running apps that use OpenCVSharp with all necessary dependencies. Modified dockerfile uses Ubuntu 20 dotnet SDK as base image.

It can be added to docker-compose.yml and then used as FROM opencvsharp_base in dockerfiles, or pushed to custom docker registry, etc.

Dockerized .NET project does not need any dependency aside from OpenCVSharp4, native binaries will be built inside docker.

However, I’m yet to separate build environment from runtime here. To do so, one will need to copy OpenCV build output and libOpenCvSharp.so (these are currently installed directly into the container system using make install) and install all the necessary packages (runtime should have same versions of dependencies ad build environment).

Guess that will be the next step but for now I don’t mind a bit bloated container 😃

Dockerfile itself:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-focal

ENV OPENCV_VERSION=4.3.0

RUN apt-get update && apt-get install -y \
    apt-transport-https \
    software-properties-common \
    wget \
    unzip \
    curl \
    ca-certificates
    #bzip2 \
    #grep sed dpkg 

# Install opencv dependencies
RUN cd ~
RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    gfortran \
    libjpeg8-dev \
    libpng-dev \
    software-properties-common
RUN add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main" && apt-get update && apt-get install -y \
    libjasper1 \
    libtiff-dev \
    libavcodec-dev \
    libavformat-dev \
    libswscale-dev \
    libdc1394-22-dev \
    libxine2-dev \
    libv4l-dev

RUN cd /usr/include/linux
RUN ln -s -f ../libv4l1-videodev.h videodev.h
RUN cd ~
RUN apt-get install -y \
    libgtk2.0-dev libtbb-dev qt5-default \
    libatlas-base-dev \
    libfaac-dev \
    libmp3lame-dev \
    libtheora-dev \
    libvorbis-dev \
    libxvidcore-dev \
    libopencore-amrnb-dev \
    libopencore-amrwb-dev \
    libavresample-dev \
    x264 \
    v4l-utils

# Setup OpenCV source
RUN wget https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip && \
    unzip ${OPENCV_VERSION}.zip && \
    rm ${OPENCV_VERSION}.zip && \
    mv opencv-${OPENCV_VERSION} opencv

# Setup opencv-contrib Source
RUN wget https://github.com/opencv/opencv_contrib/archive/${OPENCV_VERSION}.zip && \
    unzip ${OPENCV_VERSION}.zip && \
    rm ${OPENCV_VERSION}.zip && \
    mv opencv_contrib-${OPENCV_VERSION} opencv_contrib

# Build OpenCV
RUN cd opencv && mkdir build && cd build && \
    cmake \
    -D OPENCV_EXTRA_MODULES_PATH=/opencv_contrib/modules \
    -D CMAKE_BUILD_TYPE=RELEASE \
    -D BUILD_SHARED_LIBS=OFF \
    -D ENABLE_CXX11=ON \
    -D BUILD_EXAMPLES=OFF \
    -D BUILD_DOCS=OFF \
    -D BUILD_PERF_TESTS=OFF \
    -D BUILD_TESTS=OFF \
    -D BUILD_JAVA=OFF \
    -D BUILD_opencv_app=OFF \
    -D BUILD_opencv_java=OFF \
    -D BUILD_opencv_python=OFF \
    -D BUILD_opencv_ts=OFF \
    -D BUILD_opencv_js=OFF \
    -D WITH_GSTREAMER=OFF \ 
    -D OPENCV_ENABLE_NONFREE=ON \
    .. && make -j12 && make install && ldconfig

WORKDIR /

# Download OpenCvSharp
RUN git clone https://github.com/shimat/opencvsharp.git
RUN cd opencvsharp && git fetch --all --tags --prune

# Install the Extern lib.
WORKDIR /opencvsharp/src
RUN mkdir /opencvsharp/make
RUN cd /opencvsharp/make && cmake /opencvsharp/src && make -j12 && make install

ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/share/opencv4/lib/:/usr/local/lib/:/lib/x86_64-linux-gnu/"

Example docker-compose.yml:

version: '3.4'

services:
    opencvsharp_base:
        image: opencvsharp_base
        build:
            context: OpenCVSharpEnvironment

    some_image_processing_api:
        restart: unless-stopped
        build:
            context: .
            dockerfile: src/SomeImageProcessingApi/Dockerfile
            args:
                configuration: Debug
        depends_on:
            - opencvsharp_base

Example Dockerfile:

FROM opencvsharp_base
WORKDIR /app

COPY /src/SomeImageProcessingApi/SomeImageProcessingApi.csproj ./src/SomeImageProcessingApi/
WORKDIR /app/src/SomeImageProcessingApi
RUN dotnet restore

WORKDIR /app
COPY /src/SomeImageProcessingApi/. ./src/SomeImageProcessingApi/

WORKDIR /app/src/SomeImageProcessingApi
ARG configuration
RUN dotnet publish -c $configuration -o out

# TODO: separate runtime container
WORKDIR /app/src/SomeImageProcessingApi/out
ENTRYPOINT ["dotnet", "SomeImageProcessingApi.dll"]
0reactions
stale[bot]commented, Jul 24, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Simplifying the Crazy World of Linux Distros
This article simply explains the crazy, vast universe of Linux distributions.
Read more >
Can one Linux OS based environment application run in ...
One application can be used in different Linux based environments if that that environment provides the necessary preconditions to do so.
Read more >
Simplified Remote Management of Linux Servers
In this session we will show how a system administrator can use the new tools to function more effectively, focusing on how they...
Read more >
Simplify your cloud journey with Red Hat Enterprise Linux
Learn how to use Red Hat Enterprise Linux as a consistent, high-performance operating system foundation for hybrid and multicloud ...
Read more >
How To Make Linux More Secure (With Less Work)
Streamlining Linux Security: Simplified Approaches to Enhance Security with Less Effort · Develop a secure approach to SSH authentication.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found