docker容器化编译C/C++程序
文章目录
- docker容器化编译C/C++程序
- C/C++程序为什么需要再容器内编译
- 如何制作ubuntu下C/C++编译镜像
- 第一步,找一个基础镜像
- 第二步,配置一下基础环境
- 第三步:安装调试工具
- 第四步:安装依赖库
- 第五步: 安装编译工具
- 如何执行编译
- 首先: 准备容器内的编译脚本
- 其次:启容器进行编译
- 最后:拷贝程序
- 总结
C/C++程序为什么需要再容器内编译
在C/C++程序中,将代码放置在容器内编译主要是出于以下几个原因:
- 环境隔离:将C/C++程序放置在容器内可以实现环境的隔离。容器是一种虚拟化技术,可以在容器内部创建一个独立的运行环境,包括操作系统、依赖库等。这样可以确保程序在不同的环境中具有一致的行为,减少由于环境差异导致的问题。
- 依赖管理:C/C++程序可能依赖于各种库和工具,而不同项目和不同版本的依赖项之间可能存在冲突。通过将程序放置在容器内,可以将依赖项与程序隔离开来,确保每个项目都使用其所需的特定依赖版本,而不会与其他项目产生冲突。
- 可移植性:容器可以在不同的计算机和操作系统上运行,使得程序更具可移植性。无论是在开发环境中还是在生产环境中,只需确保容器在目标机器上正确配置,程序就能在各个环境中进行部署和运行。
- 部署和扩展:容器提供了方便的部署和扩展机制。通过使用容器编排工具,可以轻松地在集群中部署多个容器实例,实现高可用性和横向扩展。这对于大规模的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架构下的编译的,
当然如果能找到合适的交叉编译工具链,也可以做交叉编译,
但此文中不在深入探究。