使用 Docker 运行器创建 Conan 包¶
警告
此功能处于实验阶段,可能会发生重大更改。有关更多信息,请参阅Conan 稳定性部分。
首先,您需要安装并运行 Docker 守护程序,以及 Conan 和 docker
Python 包。本教程假设您在 Python 虚拟环境中运行 Conan,如果您已经在虚拟环境中安装了 docker
Python 包,请跳过第一行。
# install docker in your virtual environment if you don't have it already installed
$ pip install conan docker
$ docker ps
$ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
现在,我们将创建一个简单的 cmake_lib
Conan 模板,以便稍后使用运行器功能在 Docker 中运行。让我们在项目文件夹中创建 Conan 包和 Dockerfile。
$ cd </my/runner/folder>
$ mkdir mylib
$ cd mylib
$ conan new cmake_lib -d name=mylib -d version=0.1
$ tree
.
├── CMakeLists.txt
├── conanfile.py
├── include
│ └── mylib.h
├── src
│ └── mylib.cpp
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── src
└── example.cpp
Dockerfile
FROM ubuntu:22.04
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential \
cmake \
python3 \
python3-pip \
python3-venv \
&& rm -rf /var/lib/apt/lists/*
RUN pip install conan
$ cd </my/runner/folder>/mylib
$ tree
.
...
├── Dockerfile
...
现在,我们需要在 conan 的 profiles
文件夹中定义两个新的配置文件。将 </my/runner/folder>
替换为您真实的项目文件夹路径。
docker_example_host
配置文件
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
[runner]
type=docker
dockerfile=</my/runner/folder>/mylib
cache=copy
remove=true
docker_example_build
配置文件
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
我们将从一个完全干净的环境开始,没有任何容器、镜像或 Conan 包。
$ conan list "*:*"
Found 0 pkg/version recipes matching * in local cache
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
现在,是时候使用我们新的运行器定义创建我们的库 mylib
了。
$ conan create . --version 0.1 -pr:h docker_example_host -pr:b docker_example_build
如果我们拆分并分析命令输出,我们可以看到发生了什么以及命令在哪里执行。
1. 标准 Conan 执行。
======== Exporting recipe to the cache ========
mylib/0.1: Exporting package recipe: </my/runner/folder>/mylib/conanfile.py
mylib/0.1: Copied 1 '.py' file: conanfile.py
mylib/0.1: Copied 1 '.txt' file: CMakeLists.txt
mylib/0.1: Copied 1 '.h' file: mylib.h
mylib/0.1: Copied 1 '.cpp' file: mylib.cpp
mylib/0.1: Exported to cache folder: /Users/davidsanfal/.conan2/p/mylib4abd06a04bdaa/e
mylib/0.1: Exported: mylib/0.1#8760bf5a311f01cc26f3b95428203210 (2024-07-08 12:22:01 UTC)
======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
2. 构建 Docker 镜像
**********************************************
* Building the Docker image: my-conan-runner *
**********************************************
Dockerfile path: '</my/runner/folder>/mylib/Dockerfile'
Docker build context: '</my/runner/folder>/mylib'
Step 1/4 : FROM ubuntu:22.04
...
---> 2bcf70201cce
Successfully built 2bcf70201cce
Successfully tagged conan-runner-default:latest
3. 运行 conan cache save
保存本地缓存。
***********************************************************************************
* Save host cache in: </my/runner/folder>/mylib/.conanrunner/local_cache_save.tgz *
***********************************************************************************
Found 1 pkg/version recipes matching * in local cache
Saving mylib/0.1: mylib4abd06a04bdaa
4. 创建并初始化 Docker 容器。
*********************************
* Creating the docker container *
*********************************
*****************************************
* Container conan-runner-docker running *
*****************************************
5. 检查容器是否具有具有运行器功能的 Conan 版本。
*******************************************
* Running in container: "conan --version" *
*******************************************
Conan version 2.5.0
6. 使用主机副本运行 conan cache restore
初始化容器 Conan 缓存。
***********************************************************************************************************
* Running in container: "conan cache restore "/root/conanrunner/mylib/.conanrunner/local_cache_save.tgz"" *
***********************************************************************************************************
Restore: mylib/0.1 in mylib4abd06a04bdaa
Local Cache
mylib
mylib/0.1
revisions
8760bf5a311f01cc26f3b95428203210 (2024-07-08 12:22:19 UTC)
packages
recipe_folder: mylib4abd06a04bdaa
7. 在容器内运行 conan create 并构建“mylib”。
*********************************************************************************************************************************************************
* Running in container: "conan create /root/conanrunner/mylib --version 0.1 -pr:h docker_example_host -pr:b docker_example_build -f json > create.json" *
*********************************************************************************************************************************************************
======== Exporting recipe to the cache ========
mylib/0.1: Exporting package recipe: /root/conanrunner/mylib/conanfile.py
mylib/0.1: Copied 1 '.py' file: conanfile.py
mylib/0.1: Copied 1 '.txt' file: CMakeLists.txt
mylib/0.1: Copied 1 '.cpp' file: mylib.cpp
mylib/0.1: Copied 1 '.h' file: mylib.h
mylib/0.1: Exported to cache folder: /root/.conan2/p/mylib4abd06a04bdaa/e
mylib/0.1: Exported: mylib/0.1#8760bf5a311f01cc26f3b95428203210 (2024-07-08 12:22:20 UTC)
======== Input profiles ========
Profile host:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
Profile build:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu17
compiler.libcxx=libstdc++11
compiler.version=11
os=Linux
======== Computing dependency graph ========
Graph root
cli
Requirements
mylib/0.1#8760bf5a311f01cc26f3b95428203210 - Cache
======== Computing necessary packages ========
mylib/0.1: Forced build from source
Requirements
mylib/0.1#8760bf5a311f01cc26f3b95428203210:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe - Build
======== Installing packages ========
-------- Installing package mylib/0.1 (1 of 1) --------
...
[ 50%] Building CXX object CMakeFiles/example.dir/src/example.cpp.o
[100%] Linking CXX executable example
[100%] Built target example
======== Testing the package: Executing test ========
mylib/0.1 (test package): Running test()
mylib/0.1 (test package): RUN: ./example
mylib/0.1: Hello World Release!
mylib/0.1: __x86_64__ defined
mylib/0.1: _GLIBCXX_USE_CXX11_ABI 1
mylib/0.1: __cplusplus201703
mylib/0.1: __GNUC__11
mylib/0.1: __GNUC_MINOR__4
mylib/0.1 test_package
8. 使用上一个 conan create
中的 pkglist.json
信息复制容器内创建的包,运行 conan cache save
将此新包恢复到主机缓存中,并删除容器。
************************************************************************************************************************************
* Running in container: "conan cache save --list=pkglist.json --file "/root/conanrunner/mylib"/.conanrunner/docker_cache_save.tgz" *
************************************************************************************************************************************
Saving mylib/0.1: mylib4abd06a04bdaa
Saving mylib/0.1:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe: b/mylib503035e4ee8ae/p
Saving mylib/0.1:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata: b/mylib503035e4ee8ae/d/metadata
Local Cache
mylib
mylib/0.1
revisions
8760bf5a311f01cc26f3b95428203210 (2024-07-08 12:22:20 UTC)
packages
8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe
revisions
ded6547554ff2306db5250451340fa43
package_folder: b/mylib503035e4ee8ae/p
metadata_folder: b/mylib503035e4ee8ae/d/metadata
info
settings
os: Linux
arch: x86_64
compiler: gcc
compiler.cppstd: gnu17
compiler.libcxx: libstdc++11
compiler.version: 11
build_type: Release
options
fPIC: True
shared: False
recipe_folder: mylib4abd06a04bdaa
******************************************************************************************
* Restore host cache from: </my/runner/folder>/mylib/.conanrunner/docker_cache_save.tgz *
******************************************************************************************
Restore: mylib/0.1 in mylib4abd06a04bdaa
Restore: mylib/0.1:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe in b/mylib503035e4ee8ae/p
Restore: mylib/0.1:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata in b/mylib503035e4ee8ae/d/metadata
**********************
* Stopping container *
**********************
**********************
* Removing container *
**********************
如果我们现在检查 Conan 和 Docker 缓存的状态,我们将看到为 Linux 编译的新 mylib 包和新的 Docker 镜像,但我们没有任何容器,因为我们定义了 remove=true
$ conan list "*:*"
Found 1 pkg/version recipes matching * in local cache
Local Cache
mylib
mylib/0.1
revisions
8760bf5a311f01cc26f3b95428203210 (2024-07-08 12:33:28 UTC)
packages
8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe
info
settings
arch: x86_64
build_type: Release
compiler: gcc
compiler.cppstd: gnu17
compiler.libcxx: libstdc++11
compiler.version: 11
os: Linux
options
fPIC: True
shared: False
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-conan-runner latest 2bcf70201cce 11 minutes ago 531MB
我们刚刚做的是在 Docker 容器内从头开始编译库,无需运行任何 Docker 命令,并通过终端输出以完全透明且易于调试的方式检索生成的包。
这样,无论是在我们的机器上还是在容器中,我们都可以像往常一样工作,无需多个打开的终端,并且每个操作的结果都在同一个缓存中,能够自动且透明地重用先前编译中其他容器的已编译包。