How to Build Containerd
tags: containerd, container
How to Build Containerd
containerd没有提供编译环境,本文分析如何使用官方的构建环境编译containerd。
1. Standard
根据官方文档, 一步一步来即可编译containerd。
1. 安装依赖
安装golang, btrfs等依赖
2. 下载代码
git clone https://github.com/containerd/containerd.git
cd containerd
git checkout v1.6.7
3. 修改代码
sed -i 's/app.Name = "containerd"/app.Name = "containerd-st0n3"/g' cmd/containerd/command/main.go
4. 编译
make
5. binary
编译好的二进制文件,位于bin目录
# ./bin/containerd -v
containerd-st0n3 github.com/containerd/containerd v1.6.7.m 0197261a30bf81f1ee8e6a4dd2dea0ef95d67ccb.m
2. Build in a container
2.1 Github action release
上文描述的是自行搭建编译环境进行编译的过程,但可能与官方release环境不同,所以我们需要理解官方是在什么环境中编译containerd。
containerd使用github action自动进行release版本的构建:
https://github.com/containerd/containerd/runs/7681874106?check_suite_focus=true
github action的源码核心部分如下:
https://github.com/containerd/containerd/blob/v1.6.7/.github/workflows/release.yml
on:
push:
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
name: Containerd Release
jobs:
...
build:
...
steps:
...
- name: Make
shell: bash
run: |
cache="--cache-from=type=gha,scope=containerd-release --cache-to=type=gha,scope=containerd-release"
if [[ "${PLATFORM}" =~ "windows" ]]; then
# For Windows the cni build script generates a config but shells out to powershell (and also assume it is running on windows) to get a gateway and subnet.
# The values provided here are taken from packages that we previously generated.
export GATEWAY=172.21.16.1
export PREFIX_LEN=12
BUILD_ARGS="--build-arg GATEWAY --build-arg PREFIX_LEN"
fi
docker buildx build ${cache} --build-arg RELEASE_VER --build-arg GO_VERSION ${BUILD_ARGS} -f .github/workflows/release/Dockerfile --platform=${PLATFORM} -o releases/ .
echo PLATFORM_CLEAN=${PLATFORM/\//-} >> $GITHUB_ENV
# Remove symlinks since we don't want these in the release Artifacts
find ./releases/ -maxdepth 1 -type l | xargs rm
working-directory: src/github.com/containerd/containerd
env:
GO_VERSION: '1.17.13'
PLATFORM: ${{ matrix.platform }}
- name: Save Artifacts
uses: actions/upload-artifact@v2
with:
name: release-tars-${{env.PLATFORM_CLEAN}}
path: src/github.com/containerd/containerd/releases/*.tar.gz*
...
注意到具体的编译命令为docker buildx build ${cache} --build-arg RELEASE_VER --build-arg GO_VERSION ${BUILD_ARGS} -f .github/workflows/release/Dockerfile --platform=${PLATFORM} -o releases/ .
, 其中Dockerfile为.github/workflows/release/Dockerfile
。
https://github.com/containerd/containerd/blob/v1.6.7/.github/workflows/release/Dockerfile
...
FROM ${TARGETOS} AS target
...
RUN \
--mount=type=bind,from=go,source=/usr/local/go,target=/usr/local/go \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg \
export CC=$(xx-info)-gcc && xx-go --wrap && \
make release cri-release cri-cni-release && \
for f in $(find bin -executable -type f); do xx-verify $f; done
...
FROM scratch AS release
COPY --from=target /go/src/github.com/containerd/containerd/releases/ /
因此,理论上我们可以使用该Dockerfile和对应的参数,自行构造一套编译环境。
2.2 Custom
cat << EOF > build.sh
#!/bin/bash
set -x
export cache="--cache-from=type=gha,scope=containerd-release --cache-to=type=gha,scope=containerd-release"
export RELEASE_VER="v1.6.7"
export GO_VERSION="1.17.13"
export BUILD_ARGS=""
export PLATFORM="linux/amd64"
docker buildx build ${cache} --build-arg RELEASE_VER --build-arg GO_VERSION ${BUILD_ARGS} -f .github/workflows/release/Dockerfile --platform=${PLATFORM} -o releases/ .
EOF
git add . && git commit -m "add build.sh"
./build.sh
编译后位于containerd/release
目录。
注意: Dockerfile中有校验git状态,如果修改了源码,应该在build前commit。
https://github.com/containerd/containerd/blob/v1.6.7/.github/workflows/release/Dockerfile#L54-L56
...
RUN \
export GIT_STATUS_OUTPUT=$(git status --porcelain) && \
test -z $GIT_STATUS_OUTPUT || (echo $GIT_STATUS_OUTPUT && exit 1)
...
3. Advance
3.1 修改编译命令
阅读Makefile,可以容易找到具体的编译命令。
搜索$(GO) build
可以找到以下几处涉及具体编译的命令:
https://github.com/containerd/containerd/blob/v1.6.7/Makefile
...
build: ## build the go packages
@echo "$(WHALE) $@"
@$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${EXTRA_FLAGS} ${GO_LDFLAGS} ${PACKAGES}
...
define BUILD_BINARY
@echo "$(WHALE) $@"
@$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_LDFLAGS} ${GO_TAGS} ./$<
endef
# Build a binary from a cmd.
bin/%: cmd/% FORCE
$(call BUILD_BINARY)
bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220
@echo "$(WHALE) $@"
@CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim
bin/containerd-shim-runc-v1: cmd/containerd-shim-runc-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220
@echo "$(WHALE) $@"
@CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v1
bin/containerd-shim-runc-v2: cmd/containerd-shim-runc-v2 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220
@echo "$(WHALE) $@"
@CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v2
...
修改这些命令,即可自定义编译命令。