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/bashscriptPath=$(cd $(dirname $0) && pwd)cd ${scriptPath}function exit_build {echo "[xuean_gb28181_bionic_x86_64]清理数据"cd ${scriptPath}rm -rf ./buildexit $1}echo "[xuean_gb28181_bionic_x86_64]开始编译"rm -rf ./buildrm -f ./CMakeLists.txtecho "[xuean_gb28181_bionic_x86_64]设置编译环境"./env/reset.bionic.shecho "[xuean_gb28181_bionic_x86_64]创建编译目录"mkdir buildcd buildecho "[xuean_gb28181_bionic_x86_64]cmake开始生成Makefile"cmake ..if [ $? -ne 0 ]; thenecho "[xuean_gb28181_bionic_x86_64]cmake生成Makefile失败"exit_build -1elseecho "[xuean_gb28181_bionic_x86_64]cmake生成Makefile成功"fiecho "[xuean_gb28181_bionic_x86_64]开始编译"makeif [ $? -ne 0 ]; thenecho "[xuean_gb28181_bionic_x86_64]编译失败"exit_build -1elseecho "[xuean_gb28181_bionic_x86_64]编译成功"ficd ${scriptPath}echo "[xuean_gb28181_bionic_x86_64]重命名二进制文件"if test -f ./bin/xuean_gb28181; thenmv -f ./bin/xuean_gb28181 ./bin/xuean_gb28181_bionic_x64elseecho "[xuean_gb28181_bionic_x86_64]未发现编译后的二进制文件"exit_build -1fiecho "[xuean_gb28181_bionic_x86_64]完成编译"exit_build 0

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

其次:启容器进行编译

#!/bin/bashdocker 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架构下的编译的,
当然如果能找到合适的交叉编译工具链,也可以做交叉编译,
但此文中不在深入探究。