docker容器化编译C/C++程序


文章目录

  • docker容器化编译C/C++程序
  • C/C++程序为什么需要再容器内编译
  • 如何制作ubuntu下C/C++编译镜像
  • 第一步,找一个基础镜像
  • 第二步,配置一下基础环境
  • 第三步:安装调试工具
  • 第四步:安装依赖库
  • 第五步: 安装编译工具
  • 如何执行编译
  • 首先: 准备容器内的编译脚本
  • 其次:启容器进行编译
  • 最后:拷贝程序
  • 总结


C/C++程序为什么需要再容器内编译

在C/C++程序中,将代码放置在容器内编译主要是出于以下几个原因:

  1. 环境隔离:将C/C++程序放置在容器内可以实现环境的隔离。容器是一种虚拟化技术,可以在容器内部创建一个独立的运行环境,包括操作系统、依赖库等。这样可以确保程序在不同的环境中具有一致的行为,减少由于环境差异导致的问题。
  2. 依赖管理:C/C++程序可能依赖于各种库和工具,而不同项目和不同版本的依赖项之间可能存在冲突。通过将程序放置在容器内,可以将依赖项与程序隔离开来,确保每个项目都使用其所需的特定依赖版本,而不会与其他项目产生冲突。
  3. 可移植性:容器可以在不同的计算机和操作系统上运行,使得程序更具可移植性。无论是在开发环境中还是在生产环境中,只需确保容器在目标机器上正确配置,程序就能在各个环境中进行部署和运行。
  4. 部署和扩展:容器提供了方便的部署和扩展机制。通过使用容器编排工具,可以轻松地在集群中部署多个容器实例,实现高可用性和横向扩展。这对于大规模的C/C++应用程序和服务架构非常有益。

总体而言,将C/C++程序放置在容器内编译和运行可以提供环境隔离、依赖管理、可移植性和部署扩展的优势,使得程序开发和部署更加简便和可靠。

如何制作ubuntu下C/C++编译镜像

第一步,找一个基础镜像

FROM ubuntu:18.04

第二步,配置一下基础环境

# 设置阿里的ubuntu18.04的aarch64架构的源
RUN echo "deb http://mirrors.aliyun.com/ubuntu-ports/ bionic main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu-ports/ bionic-security main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu-ports/ bionic-updates main restricted universe multiverse\ndeb http://mirrors.aliyun.com/ubuntu-ports/ bionic-backports main restricted universe multiverse" >/etc/apt/sources.list \
&& echo "-----------------------" \
&& cat /etc/apt/sources.list \
&& echo "-----------------------" \
&& ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo Asia/Shanghai >/etc/timezone

此处修改了国内的apt源,由于基础镜像贼干净,在没有ca-certificates,https访问可能存在问题,需要将源的https修改为http。
如果觉得不安全的,可以先通过apt在官方源上安装tzdata和ca-certificates,但是在国内环境速度太慢。

第三步:安装调试工具

# 安装命令行工具
RUN apt-get update \ 
   && apt install -y \
       ca-certificates \
       lsb-release \
       tzdata \
       net-tools \
       iputils-ping \
       netcat \
       telnet \
       vim \
       tar zip unzip \
       wget curl \
       sngrep tcpdump \
       mysql-client

这部分可以和产品镜像公用,所以单独执行,然后这个中间镜像就可以直接被产品镜像复用,产品镜像就不用重新装了。
安装的内容根据自己需求安装,也可以不装。

第四步:安装依赖库

# 安装依赖库
RUN apt update \
    && apt install -y \
        libpqxx-dev \
        libmysqlclient-dev \
        libcurl4-openssl-dev \
        libmosquitto-dev \
        libmosquittopp-dev \
        libyaml-cpp-dev \
        libmxml-dev \
        libavutil-dev \
        libswresample-dev \
        libavcodec-dev \
        libavformat-dev \
        libswscale-dev

搞C程序,这个依赖库是最烦人的

第五步: 安装编译工具

# 安装编译工具
RUN apt update \
    && apt-get install -y \
        build-essential \
        gdb \
        cmake

不同的项目编译工具也不太一样,我这里使用的是cmake编译。

  • 最后:编译镜像
    docker build -t 37.ss360.org:1443/xuean_gb28181_xenial_x86_64/gb_28181_build:latest --file ./Dockerfile .

如何执行编译

首先: 准备容器内的编译脚本

#!/bin/bash
scriptPath=$(cd $(dirname $0) && pwd)
cd ${scriptPath}

function exit_build {
    echo "[xuean_gb28181_bionic_x86_64]清理数据"
    cd ${scriptPath}
    rm -rf ./build
    exit $1
}

echo "[xuean_gb28181_bionic_x86_64]开始编译"
rm -rf ./build
rm -f ./CMakeLists.txt

echo "[xuean_gb28181_bionic_x86_64]设置编译环境"
./env/reset.bionic.sh

echo "[xuean_gb28181_bionic_x86_64]创建编译目录"
mkdir build
cd build

echo "[xuean_gb28181_bionic_x86_64]cmake开始生成Makefile"
cmake ..

if [ $? -ne 0 ]; then
    echo "[xuean_gb28181_bionic_x86_64]cmake生成Makefile失败"
    exit_build -1
else
    echo "[xuean_gb28181_bionic_x86_64]cmake生成Makefile成功"
fi

echo "[xuean_gb28181_bionic_x86_64]开始编译"
make

if [ $? -ne 0 ]; then
    echo "[xuean_gb28181_bionic_x86_64]编译失败"
    exit_build -1
else
    echo "[xuean_gb28181_bionic_x86_64]编译成功"
fi

cd ${scriptPath}
echo "[xuean_gb28181_bionic_x86_64]重命名二进制文件"
if test -f ./bin/xuean_gb28181; then
    mv -f ./bin/xuean_gb28181 ./bin/xuean_gb28181_bionic_x64
else
    echo "[xuean_gb28181_bionic_x86_64]未发现编译后的二进制文件"
    exit_build -1
fi

echo "[xuean_gb28181_bionic_x86_64]完成编译"
exit_build 0

将正常的cmake编译流程搞到脚本里。

其次:启容器进行编译

#!/bin/bash

docker run --rm --name gb_28181_bionic_build -v $(pwd):/root/gb28181 -w /root/gb28181 37.ss360.org:1443/xuean_gb28181_x86_64/gb_28181_bionic_build:latest ./docker_build_bionic_build_impl.sh

docker run --rm --name gb_28181_bionic_build -v $(pwd):/root/gb28181 -w /root/gb28181 37.ss360.org:1443/xuean_gb28181_x86_64/gb_28181_bionic_build:latest ./docker_build_bionic_build_impl.sh

这里将项目源码目录挂载在制定路径,执行编译脚本即可

最后:拷贝程序

将编译好的程序拷贝保存后,即可清理编译环境。

总结

docker容器可以针对不同的运行环境进行编译,但是并不能架构。
比如x86_64的宿主机,是无法做aarch64架构下的编译的,
当然如果能找到合适的交叉编译工具链,也可以做交叉编译,
但此文中不在深入探究。